func prepareDist(c *config.Config, q *registry.Queue) error { dirs := c.GetListRequired("dist.prepare") for _, from := range dirs { to := "temp" if strings.Contains(from, "->") { parts := strings.Split(from, "->") from = strings.TrimSpace(parts[0]) to = filepath.Join("temp", strings.TrimSpace(parts[1])) } if _, err := os.Stat(from); err != nil { if os.IsNotExist(err) { continue } return fmt.Errorf("stat failed: %s", err) } if err := os.MkdirAll(filepath.Dir(to), 0755); err != nil { return fmt.Errorf("prepare dir failed (%s): %s", to, err) } output, err := utils.Exec("cp", []string{"-r", from, to}) if err != nil { fmt.Println(output) return fmt.Errorf("copy error: %s", err) } } return nil }
func minignore(c *config.Config, q *registry.Queue) error { base := filepath.Join("temp", filepath.Base(c.GetRequired("paths.base"))) lines, err := utils.ReadLines(base) if err != nil { return fmt.Errorf("read base html failed: %s", err) } for i, line := range lines { if strings.Contains(line, "<!-- min -->") { matchs := minRe.FindStringSubmatch(line) if matchs == nil { return fmt.Errorf("line %d of base, not a correct min format", i+1) } src := strings.Replace(matchs[1], ".js", ".min.js", -1) line = fmt.Sprintf("<script src=\"%s\"></script>\n", src) } if strings.Contains(line, "<!-- ignore -->") { line = "" } lines[i] = line } if err := utils.WriteFile(base, strings.Join(lines, "")); err != nil { return fmt.Errorf("write file failed: %s", err) } return nil }
func push(c *config.Config, q *registry.Queue) error { scriptsPath := utils.PackagePath(selfPkg) host := c.GetRequired("push") // FTP User & password user := q.NextTask() if user == "" { return fmt.Errorf("ftp user required as the first argument") } q.RemoveNextTask() password, err := gopass.GetPass(fmt.Sprintf("Enter \"%s\" password: "******"cannot read password: %s", err) } if password == "" { return fmt.Errorf("ftp password is required") } // Hash local files log.Printf("Hashing local files... ") localHashes, err := hashLocalFiles() if err != nil { return fmt.Errorf("hash local files failed: %s", err) } log.Printf("Hashing local files... %s[SUCCESS]%s\n", colors.Green, colors.Reset) // Hash remote files log.Printf("Hashing remote files... ") remoteHashes, err := retrieveRemoteHashes(scriptsPath, user, password, host) if err != nil { return fmt.Errorf("retrieve remote hashes failed: %s", err) } log.Printf("Hashing remote files... %s[SUCCESS]%s\n", colors.Green, colors.Reset) if err := saveLocalHashes(localHashes); err != nil { return fmt.Errorf("save local hashes failed: %s", err) } // Prepare FTP commands log.Printf("Preparing FTP commands... ") if err := prepareFTPCommands(localHashes, remoteHashes); err != nil { return fmt.Errorf("prepare FTP commands failed: %s", err) } log.Printf("Preparing FTP commands... %s[SUCCESS]%s\n", colors.Green, colors.Reset) // Upload files log.Printf("Uploading files... ") if err := uploadFiles(scriptsPath, user, password, host); err != nil { return fmt.Errorf("uploading files failed: %s", err) } log.Printf("Uploading files... %s[SUCCESS]%s\n", colors.Green, colors.Reset) return nil }
func compilejs(c *config.Config, q *registry.Queue) error { base := filepath.Join("temp", filepath.Base(c.GetRequired("paths.base"))) lines, err := utils.ReadLines(base) if err != nil { return fmt.Errorf("read base html failed: %s", err) } for i := 0; i < len(lines); i++ { line := lines[i] if strings.Contains(line, "<!-- compile") { match := tagRe.FindStringSubmatch(line) if match == nil { return fmt.Errorf("incorrect compile tag, line %d", i) } start := i lines[i] = "" files := []string{} for !strings.Contains(line, "<!-- endcompile -->") { match := scriptRe.FindStringSubmatch(line) if match != nil { lines[i] = "" files = append(files, match[1]) } i++ if i >= len(lines) { return fmt.Errorf("compile js block not closed, line %d", start) } line = lines[i] } if len(files) == 0 { return fmt.Errorf("no files found to compile %s", match[1]) } if err := compileJs(match[1], files); err != nil { return fmt.Errorf("compile js failed: %s", err) } line = fmt.Sprintf("<script src=\"%s\"></script>\n", match[1]) } lines[i] = line } if err := utils.WriteFile(base, strings.Join(lines, "")); err != nil { return fmt.Errorf("write file failed: %s", err) } return nil }
func deploy(c *config.Config, q *registry.Queue) error { parts := strings.Split(q.CurTask, ":") base := utils.PackagePath(filepath.Join(selfPkg, parts[1]+".sh")) args := []string{ filepath.Base(c.GetRequired("paths.base")), } if err := utils.ExecCopyOutput(base, args); err != nil { return fmt.Errorf("deploy failed: %s", err) } if err := organizeResult(c); err != nil { return fmt.Errorf("cannot organize result: %s", err) } return nil }
func controller(c *config.Config, q *registry.Queue) error { name := q.NextTask() if name == "" { return fmt.Errorf("first arg should be the name of the controller") } q.RemoveNextTask() if !strings.Contains(name, "Ctrl") { name = name + "Ctrl" } module := q.NextTask() if module == "" { return fmt.Errorf("second arg should be the module of the controller") } q.RemoveNextTask() route := q.NextTask() q.RemoveNextTask() data := &controllerData{ Name: name, Module: module, Route: route, Filename: filepath.Join(strings.Split(module, ".")...), AppPath: c.GetDefault("paths.app", filepath.Join("app", "scripts", "app.js")), } if err := writeControllerFile(data); err != nil { return fmt.Errorf("write controller failed: %s", err) } if err := writeControllerTestFile(data); err != nil { return fmt.Errorf("write controller test failed: %s", err) } if err := writeControllerViewFile(data); err != nil { return fmt.Errorf("write view failed: %s", err) } if route != "" { if err := writeControllerRouteFile(data); err != nil { return fmt.Errorf("write route failed: %s", err) } } return nil }
func copyDist(c *config.Config, q *registry.Queue) error { dirs := c.GetListRequired("dist.final") changes := utils.LoadChanges() for i, dir := range dirs { if name, ok := changes[dir]; ok { dir = name } dirs[i] = dir } for _, dir := range dirs { from := dir to := dir if strings.Contains(dir, "->") { parts := strings.Split(dir, "->") from = strings.TrimSpace(parts[0]) to = strings.TrimSpace(parts[1]) } origin := filepath.Join("temp", from) dest := filepath.Join("dist", to) if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil { return fmt.Errorf("prepare dir failed (%s): %s", dir, err) } if *config.Verbose { log.Printf("copy `%s`\n", origin) } output, err := utils.Exec("cp", []string{"-r", origin, dest}) if err != nil { fmt.Println(output) return fmt.Errorf("copy error: %s", err) } } return nil }
func readServeConfig(c *config.Config) (*serveConfig, error) { sc := &serveConfig{ base: true, url: c.GetDefault("serve.url", "http://localhost:8080/"), } method := c.GetDefault("serve.base", "") if method != "" && method != "proxy" && method != "cb" { return nil, fmt.Errorf("serve.base config must be 'proxy' (default) or 'cb'") } sc.base = (method == "cb") size := c.CountDefault("serve.proxy") for i := 0; i < size; i++ { pc := proxyConfig{ host: fmt.Sprintf("%s:%d", c.GetRequired("serve.proxy[%d].host", i), *config.Port), url: c.GetRequired("serve.proxy[%d].url", i), } sc.proxy = append(sc.proxy, pc) } return sc, nil }
func Parse(data *config.Config, idx int) []*Validator { validators := []*Validator{} nvalidators := data.CountDefault("fields[%d].validators", idx) for i := 0; i < nvalidators; i++ { name := data.GetRequired("fields[%d].validators[%d].name", idx, i) value := data.GetDefault("fields[%d].validators[%d].value", "", idx, i) msg := data.GetDefault("fields[%d].validators[%d].msg", "", idx, i) validator := createValidator(name, value, msg) if validator == nil { panic("bad validator name: " + name) } validators = append(validators, validator) } return validators }
func build(c *config.Config, q *registry.Queue) error { q.AddTasks([]string{ "update:check@0", "clean@0", "dist:prepare@0", "recess:build@0", "sass:build@0", "imagemin@0", "minignore@0", "ngmin@0", "compilejs@0", "concat@0", "htmlmin@0", "ngtemplates@0", "cacherev@0", "dist:copy@0", }) deploy := c.GetDefault("deploy.mode", "") if len(deploy) > 0 { q.AddTask(fmt.Sprintf("deploy:%s", deploy)) } return nil }
func htmlmin(c *config.Config, q *registry.Queue) error { size := c.CountDefault("htmlmin") for i := 0; i < size; i++ { source := c.GetRequired("htmlmin[%d].source", i) dest := c.GetRequired("htmlmin[%d].dest", i) if err := htmlcompressor(source, dest); err != nil { return fmt.Errorf("html compress failed: %s", err) } } return nil }
func sassFromConfig(c *config.Config, mode string) ([]*sassFile, error) { var from string if len(c.GetDefault("closure.library", "")) == 0 { if mode == "dev" { from = filepath.Join("app") } else if mode == "prod" { from = filepath.Join("temp") } } files := []*sassFile{} size := c.CountRequired("sass") for i := 0; i < size; i++ { src := filepath.Join(from, "styles", c.GetRequired("sass[%d].source", i)) dest := filepath.Join("temp", "styles", c.GetRequired("sass[%d].dest", i)) files = append(files, &sassFile{src, dest}) } return files, nil }
func parseAttrs(data *config.Config, object string, idx int) map[string]string { m := map[string]string{} size := data.CountDefault("fields[%d].%s", idx, object) for i := 0; i < size; i++ { name := data.GetRequired("fields[%d].%s[%d].name", idx, object, i) value := data.GetDefault("fields[%d].%s[%d].value", "", idx, object, i) m[name] = value } return m }
func watch(c *config.Config, q *registry.Queue) error { size := c.CountRequired("watch") for i := 0; i < size; i++ { // Extract the task name task := c.GetRequired("watch[%d].task", i) // Extract the paths paths := []string{} pathsSize := c.CountDefault("watch[%d].paths", i) for j := 0; j < pathsSize; j++ { paths = append(paths, c.GetRequired("watch[%d].paths[%d]", i, j)) } // Init the watcher if err := watcher.Dirs(paths, task); err != nil { return fmt.Errorf("watch dirs failed: %s", err) } } return nil }
func lessFromConfig(c *config.Config, mode string) ([]*lessFile, error) { var from string if mode == "dev" { from = "app" } else if mode == "prod" { from = "temp" } files := []*lessFile{} size := c.CountRequired("recess") for i := 0; i < size; i++ { src := filepath.Join(from, "styles", c.GetRequired("recess[%d].source", i)) dest := filepath.Join("temp", "styles", c.GetRequired("recess[%d].dest", i)) files = append(files, &lessFile{src, dest}) } return files, nil }
func ngtemplates(c *config.Config, q *registry.Queue) error { count := c.CountRequired("ngtemplates") for i := 0; i < count; i++ { append := c.GetRequired("ngtemplates[%d].append", i) files := c.GetListRequired("ngtemplates[%d].files", i) templates, err := readTemplates(files) if err != nil { return fmt.Errorf("cannot read templates: %s", err) } if err = writeTemplates(append, templates); err != nil { return fmt.Errorf("cannot save template file: %s", err) } } return nil }
func cacherev(c *config.Config, q *registry.Queue) error { dirs := c.GetListRequired("cacherev.dirs") exclude := c.GetListRequired("cacherev.exclude") for _, dir := range dirs { dir = filepath.Join("temp", dir) if err := filepath.Walk(dir, changeName(exclude)); err != nil { return fmt.Errorf("change names walk failed (%s): %s", dir, err) } } rev := c.GetListDefault("cacherev.rev") for _, dir := range rev { dir = filepath.Join("temp", dir) if err := filepath.Walk(dir, changeReferences); err != nil { return fmt.Errorf("change references walk failed (%s): %s", dir, err) } } utils.SaveChanges(changes) return nil }
func parseFields(data *config.Config, spec string) []*field { fields := []*field{} size := data.CountRequired("%s", spec) for i := 0; i < size; i++ { field := &field{ Key: data.GetDefault("%s[%d].key", "", spec, i), Kind: data.GetRequired("%s[%d].kind", spec, i), Store: data.GetDefault("%s[%d].store", "", spec, i), Condition: data.GetDefault("%s[%d].condition", "", spec, i), Validators: make([]*validator, 0), } if field.Kind == "Array" || field.Kind == "Object" || field.Kind == "Conditional" { newSpec := fmt.Sprintf("%s[%d].fields", spec, i) field.Fields = parseFields(data, newSpec) } validatorsSize := data.CountDefault("%s[%d].validators", spec, i) for j := 0; j < validatorsSize; j++ { v := &validator{ Name: data.GetRequired("%s[%d].validators[%d].name", spec, i, j), Value: data.GetDefault("%s[%d].validators[%d].value", "", spec, i, j), } usesSize := data.CountDefault("%s[%d].validators[%d].use", spec, i, j) for k := 0; k < usesSize; k++ { value := data.GetDefault("%s[%d].validators[%d].use[%d]", "", spec, i, j, k) v.Uses = append(v.Uses, value) } field.Validators = append(field.Validators, v) } fields = append(fields, field) } return fields }
func organizeResult(c *config.Config) error { excludes := c.GetListDefault("deploy.exclude") includes := c.GetListDefault("deploy.include") moves := c.GetListDefault("deploy.moves") // Extract list of paths to remove removePaths := map[string]bool{} walkFn := func(path string, info os.FileInfo) error { removePaths[path] = true if *config.Verbose { log.Printf("flag to remove `%s`...\n", path) } return nil } for _, exclude := range excludes { exclude = filepath.Join("..", "deploy", exclude) if err := utils.NewWalker(exclude).Walk(walkFn); err != nil { fmt.Errorf("deploy exclude walker failed: %s", err) } } // Cancel removing of files that are included again walkFn = func(path string, info os.FileInfo) error { cur := path for cur != "." { removePaths[cur] = false cur = filepath.Dir(cur) } if *config.Verbose { log.Printf("include `%s`...\n", path) } return nil } for _, include := range includes { include = filepath.Join("..", "deploy", include) if err := utils.NewWalker(include).Walk(walkFn); err != nil { fmt.Errorf("deploy include walker failed: %s", err) } } // Remove flagged files & folders for path, remove := range removePaths { if remove { if *config.Verbose { log.Printf("removing `%s`...\n", path) } if err := os.RemoveAll(path); err != nil { return fmt.Errorf("cannot remove deploy entry: %s", err) } } } // Execute move operations for _, move := range moves { parts := strings.Split(move, "->") origin := filepath.Join("..", "deploy", strings.TrimSpace(parts[0])) dest := filepath.Join("..", "deploy", strings.TrimSpace(parts[1])) if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil { return fmt.Errorf("cannot create dest tree structure: %s", err) } output, err := utils.Exec("cp", []string{"-r", origin, dest}) if err != nil { fmt.Println(output) return fmt.Errorf("copy error: %s", err) } } return nil }
// Parse form fields func Parse(data *config.Config, idx int) (Field, error) { base := &BaseField{ ID: data.GetRequired("fields[%d].name", idx), Name: data.GetRequired("fields[%d].name", idx), Label: data.GetDefault("fields[%d].label", "", idx), Help: data.GetDefault("fields[%d].help", "", idx), Class: utils.SplitStrList(data.GetDefault("fields[%d].class", "", idx)), Size: utils.SplitStrList(data.GetDefault("fields[%d].size", "", idx)), LabelSize: utils.SplitStrList(data.GetDefault("fields[%d].labelSize", "", idx)), Attrs: parseAttrs(data, "attrs", idx), ContainerAttrs: parseAttrs(data, "containerAttrs", idx), } var field Field fieldType := data.GetRequired("fields[%d].type", idx) switch fieldType { case "email": fallthrough case "number": fallthrough case "password": fallthrough case "file": fallthrough case "url": fallthrough case "text": field = &inputField{ BaseField: base, PlaceHolder: data.GetDefault("fields[%d].placeholder", "", idx), Prefix: data.GetDefault("fields[%d].prefix", "", idx), Type: fieldType, } case "textarea": field = &textAreaField{ BaseField: base, PlaceHolder: data.GetDefault("fields[%d].placeholder", "", idx), Rows: data.GetInt("fields[%d].rows", 3, idx), } case "submit": field = &submitField{ BaseField: base, } case "datepicker": field = &datepickerField{ BaseField: base, PlaceHolder: data.GetDefault("fields[%d].placeholder", "", idx), DateFormat: data.GetDefault("fields[%d].dateFormat", "dd/MM/yyyy", idx), IsOpen: data.GetDefault("fields[%d].isOpen", "", idx), Options: data.GetDefault("fields[%d].options", "", idx), } case "static": field = &staticField{ BaseField: base, Content: data.GetDefault("fields[%d].content", "", idx), } case "custom": field = &customField{ BaseField: base, Content: data.GetDefault("fields[%d].content", "", idx), } /* case "select": field = &selectField{ BaseField: base, BlankID: data.GetDefault("fields[%d].blank.id", "", idx), BlankLabel: data.GetDefault("fields[%d].blank.label", "", idx), Class: strings.Split(data.GetDefault("fields[%d].class", "", idx), " "), Size: strings.Split(data.GetDefault("fields[%d].size", "", idx), " "), Help: data.GetDefault("fields[%d].help", "", idx), ID: name, Origin: data.GetRequired("fields[%d].origin", idx), OriginID: data.GetDefault("fields[%d].originID", "id", idx), OriginLabel: data.GetDefault("fields[%d].originLabel", "label", idx), Watch: data.GetDefault("fields[%d].watch", "", idx), }*/ case "checkbox": field = &checkboxField{ BaseField: base, } default: return nil, fmt.Errorf("no field type %s in html mode", fieldType) } return field, nil }
func cbtest(c *config.Config, q *registry.Queue) error { fmt.Println("Hello World!") c.Render() return nil }