// Delete file func Delete() echo.HandlerFunc { return func(c echo.Context) error { appPath := c.Param("app_path") if appPath == "" { return api.ErrorNotFound(c, nil) } path := c.P(1) if api.IsAnonymous(c) { return api.ErrorUnauthorized(c, nil) } app, err := api.GetApp(appPath) if err != nil { return api.ErrorInternal(c, err) } if app == nil { return api.ErrorNotFound(c, nil) } parser, err := storage.NewLocalParser(api.Owner(c), appPath) if err != nil { return api.ErrorInternal(c, err) } parser.Storage.Delete(parser.Storage.GetSourceKey(path)) output := &get3w.FileDeleteOutput{ LastModified: timeutils.ToString(time.Now()), } return c.JSON(http.StatusOK, output) } }
// Get file content func Get() echo.HandlerFunc { return func(c echo.Context) error { appPath := c.Param("app_path") if appPath == "" { return api.ErrorNotFound(c, nil) } path := c.P(1) app, err := api.GetApp(appPath) if err != nil { return api.ErrorInternal(c, err) } if app == nil { return api.ErrorNotFound(c, nil) } parser, err := storage.NewLocalParser(api.Owner(c), appPath) if err != nil { return api.ErrorInternal(c, err) } data, err := parser.Storage.Read(parser.Storage.GetSourceKey(path)) if err != nil { return api.ErrorNotFound(c, nil) } output := &get3w.FileGetOutput{ Content: base64.StdEncoding.EncodeToString(data), } return c.JSON(http.StatusOK, output) } }
// Save app func Save() echo.HandlerFunc { return func(c echo.Context) error { appPath := c.Param("app_path") if appPath == "" { return api.ErrorNotFound(c, nil) } if api.IsAnonymous(c) { return api.ErrorUnauthorized(c, nil) } input := &get3w.AppSaveInput{} err := api.LoadRequestInput(c, input) if err != nil { return api.ErrorBadRequest(c, err) } parser, err := storage.NewLocalParser(api.Owner(c), appPath) if err != nil { return api.ErrorInternal(c, err) } err = parser.APISave(input.Payloads) if err != nil { return api.ErrorInternal(c, err) } return c.JSON(http.StatusOK, &get3w.AppSaveOutput{ LastModified: timeutils.ToString(time.Now()), }) } }
// List return files func List() echo.HandlerFunc { return func(c echo.Context) error { appPath := c.Param("app_path") if appPath == "" { return api.ErrorNotFound(c, nil) } path := c.P(1) app, err := api.GetApp(appPath) if err != nil { return api.ErrorInternal(c, err) } if app == nil { return api.ErrorNotFound(c, nil) } parser, err := storage.NewLocalParser(api.Owner(c), appPath) if err != nil { return api.ErrorInternal(c, err) } files, err := parser.Storage.GetFiles(parser.Storage.GetRootPrefix(path)) if err != nil { return api.ErrorInternal(c, err) } return c.JSON(http.StatusOK, files) } }
// Push file content func Push() echo.HandlerFunc { return func(c echo.Context) error { appPath := c.Param("app_path") if appPath == "" { return api.ErrorNotFound(c, nil) } if api.IsAnonymous(c) { return api.ErrorUnauthorized(c, nil) } input := &get3w.FilesPushInput{} err := api.LoadRequestInput(c, input) if err != nil { return api.ErrorBadRequest(c, err) } app, err := api.GetApp(appPath) if err != nil { return api.ErrorInternal(c, err) } if app == nil { return api.ErrorNotFound(c, nil) } parser, err := storage.NewLocalParser(api.Owner(c), appPath) if err != nil { return api.ErrorInternal(c, err) } data, err := base64.StdEncoding.DecodeString(input.Blob) if err != nil { return api.ErrorInternal(c, err) } pathBytesMap, err := ioutils.UnPack(data) if err != nil { return api.ErrorInternal(c, err) } for _, addedPath := range input.Added { parser.Storage.Write(parser.Storage.GetSourceKey(addedPath), pathBytesMap[addedPath]) } for _, modifiedPath := range input.Modified { parser.Storage.Write(parser.Storage.GetSourceKey(modifiedPath), pathBytesMap[modifiedPath]) } for _, removedPath := range input.Removed { parser.Storage.Delete(parser.Storage.GetSourceKey(removedPath)) } output := &get3w.FileEditOutput{ LastModified: timeutils.ToString(time.Now()), } return c.JSON(http.StatusOK, output) } }
func (cli *Get3WCli) build(dir string) error { parser, err := storage.NewLocalParser(cli.config.AuthConfig.Username, dir) if err != nil { return err } err = parser.Build(true) if err != nil { return err } fmt.Fprintln(cli.out, "done.") return nil }
func (cli *Get3WCli) run(dir string) error { parser, err := storage.NewLocalParser(cli.config.AuthConfig.Username, dir) if err != nil { return err } err = parser.Build(true) if err != nil { return err } destinationPath := parser.Storage.GetDestinationPrefix("") watch.Run(8000, destinationPath) return nil }
// Edit file content func Edit() echo.HandlerFunc { return func(c echo.Context) error { appPath := c.Param("app_path") if appPath == "" { return api.ErrorNotFound(c, nil) } path := c.P(1) if api.IsAnonymous(c) { return api.ErrorUnauthorized(c, nil) } input := &get3w.FileEditInput{} err := api.LoadRequestInput(c, input) if err != nil { return api.ErrorBadRequest(c, err) } app, err := api.GetApp(appPath) if err != nil { return api.ErrorInternal(c, err) } if app == nil { return api.ErrorNotFound(c, nil) } parser, err := storage.NewLocalParser(api.Owner(c), appPath) if err != nil { return api.ErrorInternal(c, err) } data, err := base64.StdEncoding.DecodeString(input.Content) if err != nil { return api.ErrorInternal(c, err) } err = parser.Storage.Write(parser.Storage.GetSourceKey(path), data) if err != nil { return api.ErrorInternal(c, err) } output := &get3w.FileEditOutput{ LastModified: timeutils.ToString(time.Now()), } return c.JSON(http.StatusOK, output) } }
// Sync app func Sync() echo.HandlerFunc { return func(c echo.Context) error { appPath := c.Param("app_path") if appPath == "" { return api.ErrorNotFound(c, nil) } if api.IsAnonymous(c) { return api.ErrorUnauthorized(c, nil) } app, err := api.GetApp(appPath) if err != nil { return api.ErrorInternal(c, err) } if app == nil { return api.ErrorNotFound(c, nil) } config, err := home.LoadConfig() if err != nil { return api.ErrorInternal(c, err) } parser, err := storage.NewLocalParser(api.Owner(c), appPath) if err != nil { return api.ErrorInternal(c, err) } buffer := bytes.NewBufferString("") shouldLogin, err := parser.Push(&config.AuthConfig, buffer) if shouldLogin { return api.ErrorUnauthorized(c, nil) } if err != nil { return api.ErrorInternal(c, err) } return c.JSON(http.StatusOK, &get3w.AppSyncOutput{ Log: strings.Replace(buffer.String(), "\n", "<br />", -1), }) } }
// Create create folder func Create() echo.HandlerFunc { return func(c echo.Context) error { appPath := c.Param("app_path") if appPath == "" { return api.ErrorNotFound(c, nil) } if api.IsAnonymous(c) { return api.ErrorUnauthorized(c, nil) } input := &get3w.FolderCreateInput{} err := api.LoadRequestInput(c, input) if err != nil { return api.ErrorBadRequest(c, err) } if input.Path == "" { return api.ErrorBadRequest(c, nil) } app, err := api.GetApp(appPath) if err != nil { return api.ErrorInternal(c, err) } if app == nil { return api.ErrorNotFound(c, nil) } parser, err := storage.NewLocalParser(api.Owner(c), appPath) if err != nil { return api.ErrorInternal(c, err) } parser.Storage.NewFolder(parser.Storage.GetSourcePrefix(input.Path)) output := &get3w.FolderCreateOutput{ LastModified: timeutils.ToString(time.Now()), } return c.JSON(http.StatusOK, output) } }
// Publish app func Publish() echo.HandlerFunc { return func(c echo.Context) error { appPath := c.Param("app_path") if appPath == "" { return api.ErrorNotFound(c, nil) } if api.IsAnonymous(c) { return api.ErrorUnauthorized(c, nil) } parser, err := storage.NewLocalParser(api.Owner(c), appPath) if err != nil { return api.ErrorInternal(c, err) } parser.Build(true) return c.String(http.StatusOK, "") } }
// Load app func Load() echo.HandlerFunc { return func(c echo.Context) error { appPath := c.Param("app_path") if appPath == "" { return api.ErrorNotFound(c, nil) } if api.IsAnonymous(c) { return api.ErrorUnauthorized(c, nil) } input := &get3w.AppLoadInput{} err := api.LoadRequestInput(c, input) if err != nil { return api.ErrorBadRequest(c, err) } app, err := api.GetApp(appPath) if err != nil { return api.ErrorInternal(c, err) } if app == nil { return api.ErrorNotFound(c, nil) } parser, err := storage.NewLocalParser(api.Owner(c), appPath) if err != nil { return api.ErrorBadRequest(c, err) } parser.APILoad() output := &get3w.AppLoadOutput{ LastModified: timeutils.ToString(time.Now()), App: app, Config: parser.Config, Sites: parser.Sites, } return c.JSON(http.StatusOK, output) } }
// Checksum get path and checksum map of all files, dedicated to cli func Checksum() echo.HandlerFunc { return func(c echo.Context) error { appPath := c.Param("app_path") if appPath == "" { return api.ErrorNotFound(c, nil) } app, err := api.GetApp(appPath) if err != nil { return api.ErrorInternal(c, err) } if app == nil { return api.ErrorNotFound(c, nil) } parser, err := storage.NewLocalParser(api.Owner(c), appPath) if err != nil { return api.ErrorInternal(c, err) } files, err := parser.Storage.GetAllFiles(parser.Storage.GetSourcePrefix("")) if err != nil { return api.ErrorInternal(c, err) } output := &get3w.FilesChecksumOutput{ Files: make(map[string]string), } for _, file := range files { output.Files[file.Path] = file.Checksum } return c.JSON(http.StatusOK, output) } }
func addFromCloud(dirPath, origin string, authConfig *home.AuthConfig) (string, error) { var err error nameParts := strings.SplitN(strings.Trim(origin, "/"), "/", 2) owner, name := nameParts[0], nameParts[1] appPath := filepath.Join(dirPath, name) parser, err := storage.NewLocalParser(authConfig.Username, appPath) if err != nil { return "", err } client := get3w.NewClient(authConfig.AccessToken) fmt.Printf("Getting repository '%s/%s'...\n", owner, name) fmt.Print("Counting objects: ") output, _, err := client.Apps.FilesChecksum(owner, name) if err != nil { return "", err } fmt.Printf("%d, done.\n", len(output.Files)) for path, remoteChecksum := range output.Files { download := false if !parser.Storage.IsExist(parser.Storage.GetSourceKey(path)) { download = true } else { checksum, _ := parser.Storage.Checksum(parser.Storage.GetSourceKey(path)) if checksum != remoteChecksum { download = true } } if download { fmt.Printf("Receiving object: %s", path) fileOutput, _, err := client.Apps.GetFile(owner, name, path) if err != nil { return "", err } data, err := base64.StdEncoding.DecodeString(fileOutput.Content) if err != nil { return "", err } parser.Storage.Write(parser.Storage.GetSourceKey(path), data) fmt.Println(", done.") } } // parser.Config.Repository = repo // err = parser.WriteConfig() // if err != nil { // return err // } builder, err := storage.NewLocalParser(authConfig.Username, appPath) if err != nil { return "", err } return appPath, builder.Build(true) }
// Upload files func Upload() echo.HandlerFunc { return func(c echo.Context) error { appPath := c.Param("app_path") if appPath == "" { return api.ErrorNotFound(c, nil) } if api.IsAnonymous(c) { return api.ErrorUnauthorized(c, nil) } location := c.Query("location") app, err := api.GetApp(appPath) if err != nil { return api.ErrorInternal(c, err) } if app == nil { return api.ErrorNotFound(c, nil) } parser, err := storage.NewLocalParser(api.Owner(c), appPath) if err != nil { return api.ErrorInternal(c, err) } req := c.Request().(*standard.Request) mr, err := req.MultipartReader() if err != nil { return api.ErrorInternal(c, err) } files := []*get3w.File{} for { part, err := mr.NextPart() if err != nil { if err == io.EOF { break } return api.ErrorInternal(c, err) } defer part.Close() data, err := ioutil.ReadAll(part) if err != nil { return api.ErrorInternal(c, err) } filename := part.FileName() err = parser.Storage.Write(parser.Storage.GetSourceKey(location, filename), data) if err != nil { return api.ErrorInternal(c, err) } file := &get3w.File{ IsDir: false, Path: strings.Trim(path.Join(location, filename), "/"), Name: filename, Size: 0, Checksum: "", LastModified: timeutils.ToString(time.Now()), } files = append(files, file) } return c.JSON(http.StatusOK, files) } }
// Add app, for open and clone operation func Add() echo.HandlerFunc { return func(c echo.Context) error { if api.IsAnonymous(c) { return api.ErrorUnauthorized(c, nil) } owner := api.Owner(c) input := &get3w.AppAddInput{} err := api.LoadRequestInput(c, input) if err != nil { return api.ErrorBadRequest(c, err) } dirPath := input.DirPath dirExists := true if dirPath == "" { dirExists = false } else { stat, err := os.Lstat(dirPath) if err != nil { dirExists = false } else if !stat.IsDir() { dirExists = false } } if !dirExists { return api.ErrorNotFound(c, nil) } config, err := home.LoadConfig() if err != nil { return api.ErrorBadRequest(c, err) } success := true configExists := true var app *get3w.App var appPath string if input.Origin != "" { appPath, err = addFromCloud(dirPath, input.Origin, &config.AuthConfig) if err != nil { return api.ErrorBadRequest(c, err) } } else { appPath, configExists, err = addFromLocal(dirPath, config) if err != nil { return api.ErrorBadRequest(c, err) } } if input.Check && !configExists { success = false } if success { parser, err := storage.NewLocalParser(config.AuthConfig.Username, appPath) if err != nil { return api.ErrorInternal(c, err) } app = &get3w.App{ Owner: owner, Name: parser.Name, Description: parser.Config.Description, Tags: "", Path: appPath, Private: false, CreatedAt: timeutils.ToString(time.Now()), UpdatedAt: timeutils.ToString(time.Now()), } exists := false for _, app := range config.Apps { if app.Path == appPath { exists = true break } } if !exists { config.Apps = append(config.Apps, app) config.Save() } } output := &get3w.AppAddOutput{ Config: configExists, App: app, } return c.JSON(http.StatusOK, output) } }
func (cli *Get3WCli) watch(dir string) error { parser, err := storage.NewLocalParser(cli.config.AuthConfig.Username, dir) if err != nil { return err } err = parser.Build(true) if err != nil { return err } sourcePath := parser.Storage.GetSourcePrefix("") destinationPath := strings.TrimRight(strings.ToLower(parser.Storage.GetDestinationPrefix("")), string(os.PathSeparator)) watcher, err := fsnotify.NewWatcher() if err != nil { log.Fatal(err) } defer watcher.Close() done := make(chan bool) go func() { lastTime := time.Now() for { select { case event := <-watcher.Events: if !strings.HasPrefix(strings.ToLower(event.Name), destinationPath) { now := time.Now() d := now.Sub(lastTime) if d.Seconds() > 1 { log.Println("build done.") parser, err := storage.NewLocalParser(cli.config.AuthConfig.Username, dir) if err != nil { log.Println("error:", err) } err = parser.Build(false) if err != nil { log.Println("error:", err) } lastTime = time.Now() } } // if event.Op&fsnotify.Write == fsnotify.Write { // log.Println("modified file:", event.Name) // } case err := <-watcher.Errors: log.Println("error:", err) } } }() err = watcher.Add(sourcePath) if err != nil { log.Fatal(err) } <-done return nil }
func (cli *Get3WCli) push(dir string) error { parser, err := storage.NewLocalParser(cli.config.AuthConfig.Username, dir) if err != nil { return err } authConfig := &cli.config.AuthConfig shouldLogin, err := parser.Push(authConfig, cli.out) if shouldLogin { fmt.Fprintf(cli.out, "\nPlease login prior to %s:\n", "push") authConfig, err = cli.login("", "") if err != nil { return err } _, err = parser.Push(authConfig, cli.out) if err != nil { return err } } else if err != nil { return err } return nil // var repo *get3w.Repository // if url != "" { // repo, err = repos.ParseRepository(url) // if err != nil { // return err // } // } else { // repo = parser.Config.Repository // if repo == nil || repo.Host == "" || repo.Owner == "" || repo.Name == "" { // //fmt.Fprintln(cli.out, "WARNING: repository is unset.") // repo = &get3w.Repository{ // Host: get3w.DefaultRepositoryHost(), // Owner: authConfig.Username, // Name: parser.Name, // } // } // } // // if repo == nil || repo.Host == "" || repo.Owner == "" || repo.Name == "" { // return fmt.Errorf("ERROR: remote repository invalid. use: get3w push URL") // } // // if authConfig.Username == "" || authConfig.AccessToken == "" || authConfig.Username != repo.Owner { // fmt.Fprintf(cli.out, "\nPlease login prior to %s:\n", "push") // authConfig, err = cli.login("", "") // if err != nil { // return err // } // } // // if authConfig.Username != repo.Owner { // return fmt.Errorf("ERROR: Authentication failed for '%s'\n", url) // } // // client := get3w.NewClient(authConfig.AccessToken) // output, _, err := client.Apps.FilesChecksum(repo.Owner, repo.Name) // if err != nil { // return err // } // files := output.Files // // localFiles, err := parser.Storage.GetAllFiles(parser.Storage.GetSourcePrefix("")) // if err != nil { // return err // } // // // 1 specified add, 0 specified edit, -1 specified delete // pathMap := make(map[string]int) // // for _, localFile := range localFiles { // if localFile.IsDir || parser.IsLocalFile(localFile) { // continue // } // checksum := files[localFile.Path] // if checksum == "" { // pathMap[localFile.Path] = 1 // } else { // localChecksum, _ := parser.Storage.Checksum(localFile.Path) // if checksum != localChecksum { // pathMap[localFile.Path] = 0 // } // } // } // for path := range files { // if !parser.Storage.IsExist(path) { // pathMap[path] = -1 // } // } // // fmt.Fprintf(cli.out, "Remote repository: %s/%s/%s\n", repo.Host, repo.Owner, repo.Name) // // if len(pathMap) == 0 { // fmt.Fprintln(cli.out, "Everything up-to-date") // return nil // } // // configPath := config.ConfigDir() // gzPath := filepath.Join(configPath, stringutils.UUID()+".tar.gz") // // err = ioutils.Pack(gzPath, parser.Path, pathMap) // if err != nil { // return err // } // // data, err := ioutil.ReadFile(gzPath) // if err != nil { // return err // } // os.Remove(gzPath) // // blob := base64.StdEncoding.EncodeToString(data) // // input := &get3w.FilesPushInput{ // Blob: blob, // } // // for path, val := range pathMap { // if val > 0 { // fmt.Fprintf(cli.out, "\t+added:%s\n", path) // input.Added = append(input.Added, path) // } // } // for path, val := range pathMap { // if val < 0 { // fmt.Fprintf(cli.out, "\t-removed:%s\n", path) // input.Removed = append(input.Removed, path) // } // } // for path, val := range pathMap { // if val == 0 { // fmt.Fprintf(cli.out, "\tmodified:%s\n", path) // input.Modified = append(input.Modified, path) // } // } // // _, _, err = client.Apps.FilesPush(repo.Owner, repo.Name, input) // if err != nil { // return err // } // // fmt.Fprintln(cli.out, "done.") // return nil }
func (cli *Get3WCli) get(url, dir string) error { authConfig := &cli.config.AuthConfig var host, owner, name string var err error if url != "" { host, owner, name, err = splitURL(url) if err != nil { return err } if dir == "" { dir = name } } parser, err := storage.NewLocalParser(authConfig.Username, dir) if err != nil { return err } if url == "" { host = get3w.DefaultRepositoryHost() owner = authConfig.Username name = parser.Name } client := get3w.NewClient(cli.config.AuthConfig.AccessToken) if host != get3w.DefaultRepositoryHost() { return fmt.Errorf("ERROR: Only %s supported\n", get3w.DefaultRepositoryHost()) } fmt.Printf("Getting repository '%s/%s/%s'...\n", host, owner, name) fmt.Print("Counting objects: ") output, _, err := client.Apps.FilesChecksum(owner, name) if err != nil { return err } fmt.Printf("%d, done.\n", len(output.Files)) for path, remoteChecksum := range output.Files { download := false if !parser.Storage.IsExist(parser.Storage.GetSourceKey(path)) { download = true } else { checksum, _ := parser.Storage.Checksum(parser.Storage.GetSourceKey(path)) if checksum != remoteChecksum { download = true } } if download { fmt.Printf("Receiving object: %s", path) fileOutput, _, err := client.Apps.GetFile(owner, name, path) if err != nil { return err } data, err := base64.StdEncoding.DecodeString(fileOutput.Content) if err != nil { return err } parser.Storage.Write(parser.Storage.GetSourceKey(path), data) fmt.Println(", done.") } } // parser.Config.Repository = repo // err = parser.WriteConfig() // if err != nil { // return err // } return cli.build(dir) }
func (cli *Get3WCli) status(dir string) error { authConfig := &cli.config.AuthConfig parser, err := storage.NewLocalParser(authConfig.Username, dir) if err != nil { return err } if authConfig.Username == "" || authConfig.AccessToken == "" { fmt.Fprintf(cli.out, "\nPlease login prior to %s:\n", "status") authConfig, err = cli.login("", "") if err != nil { return err } } else { fmt.Fprintf(cli.out, "\nYour Username:%s\n", authConfig.Username) } host := get3w.DefaultRepositoryHost() owner := authConfig.Username name := parser.Name client := get3w.NewClient(authConfig.AccessToken) output, _, err := client.Apps.FilesChecksum(owner, name) if err != nil { return err } files := output.Files localFiles, err := parser.Storage.GetAllFiles(parser.Storage.GetSourcePrefix("")) if err != nil { return err } // 1 specified add, 0 specified edit, -1 specified delete pathMap := make(map[string]int) for _, localFile := range localFiles { if localFile.IsDir || parser.IsLocalFile(localFile) { continue } checksum := files[localFile.Path] if checksum == "" { pathMap[localFile.Path] = 1 } else { localChecksum, _ := parser.Storage.Checksum(localFile.Path) if checksum != localChecksum { pathMap[localFile.Path] = 0 } } } for path := range files { if !parser.Storage.IsExist(path) { pathMap[path] = -1 } } fmt.Fprintf(cli.out, "Local repository: %s\n", parser.Path) fmt.Fprintf(cli.out, "Remote repository: %s/%s/%s\n", host, owner, name) //Your branch is up-to-date with 'origin/master'. if len(pathMap) == 0 { fmt.Fprintln(cli.out, "Everything up-to-date") return nil } fmt.Fprintln(cli.out, "Diff:") for path, val := range pathMap { if val > 0 { fmt.Fprintf(cli.out, "\t+added:%s\n", path) } } for path, val := range pathMap { if val < 0 { fmt.Fprintf(cli.out, "\t-removed:%s\n", path) } } for path, val := range pathMap { if val == 0 { fmt.Fprintf(cli.out, "\tmodified:%s\n", path) } } return nil }