// NewPageOfMarkdown create new page from markdown file func NewPageOfMarkdown(file, slug string, page *Page) (*Page, error) { // page-node need not read file if page != nil && page.Node == true { return page, nil } fileBytes, err := ioutil.ReadFile(file) if err != nil { return nil, err } if len(fileBytes) < 3 { return nil, fmt.Errorf("page content is too less") } if page == nil { dataSlice := bytes.SplitN(fileBytes, postBlockSeparator, 3) if len(dataSlice) != 3 { return nil, fmt.Errorf("page need front-matter block and markdown block") } idx := getFirstBreakByte(dataSlice[1]) if idx == 0 { return nil, fmt.Errorf("page need front-matter block and markdown block") } formatType := detectFormat(string(dataSlice[1][:idx])) if formatType == 0 { return nil, fmt.Errorf("page front-matter block is unrecognized") } page = new(Page) if formatType == FormatTOML { if err = toml.Unmarshal(dataSlice[1][idx:], page); err != nil { return nil, err } } if formatType == FormatINI { iniObj, err := ini.Load(dataSlice[1][idx:]) if err != nil { return nil, err } if err = newPageFromIniObject(iniObj, page, "DEFAULT", "meta"); err != nil { return nil, err } } if page.Node == false { page.Bytes = bytes.Trim(dataSlice[2], "\n") } } else { page.Bytes = bytes.Trim(fileBytes, "\n") } page.fileURL = file if page.Slug == "" { page.Slug = slug } if page.Date == "" && page.Node == false { // page-node need not time t, _ := com.FileMTime(file) page.dateTime = time.Unix(t, 0) } return page, page.normalize() }
// NewPostOfMarkdown create new post from markdown file func NewPostOfMarkdown(file string, post *Post) (*Post, error) { fileBytes, err := ioutil.ReadFile(file) if err != nil { return nil, err } if len(fileBytes) < 3 { return nil, fmt.Errorf("post content is too less") } if post == nil { dataSlice := bytes.SplitN(fileBytes, postBlockSeparator, 3) if len(dataSlice) != 3 { return nil, fmt.Errorf("post need front-matter block and markdown block") } idx := getFirstBreakByte(dataSlice[1]) if idx == 0 { return nil, fmt.Errorf("post need front-matter block and markdown block") } formatType := detectFormat(string(dataSlice[1][:idx])) if formatType == 0 { return nil, fmt.Errorf("post front-matter block is unrecognized") } post = new(Post) if formatType == FormatTOML { if err = toml.Unmarshal(dataSlice[1][idx:], post); err != nil { return nil, err } } if formatType == FormatINI { iniObj, err := ini.Load(dataSlice[1][idx:]) if err != nil { return nil, err } section := iniObj.Section("DEFAULT") if err = newPostFromIniSection(section, post); err != nil { return nil, err } } post.Bytes = bytes.Trim(dataSlice[2], "\n") } else { post.Bytes = bytes.Trim(fileBytes, "\n") } post.fileURL = file if post.Date == "" { t, _ := com.FileMTime(file) post.dateTime = time.Unix(t, 0) } return post, post.normalize() }
func TestModelPageIni(t *testing.T) { Convey("ParseIniFrontMatter", t, func() { p, err := NewPageOfMarkdown("testdata/page/page_ini.md", "page/page_ini", nil) if err != nil { So(err, ShouldNotBeNil) return } So(p.Title, ShouldEqual, "Welcome") t, _ := com.FileMTime("testdata/page/page_ini.md") So(p.Created().Unix(), ShouldEqual, t) So(p.IsUpdated(), ShouldEqual, false) So(p.Meta, ShouldContainKey, "key") }) }
func TestModelPostWrong(t *testing.T) { Convey("ParsePostWrong", t, func() { Convey("ParseNoTime", func() { file := "testdata/post/post_wrong.md" p, err := NewPostOfMarkdown(file, nil) So(err, ShouldBeNil) t, _ := com.FileMTime(file) So(p.dateTime.Unix(), ShouldEqual, t) }) Convey("ParseWrongTime", func() { _, err := parseTimeString("") So(err.Error(), ShouldEqual, "empty time string") }) Convey("ParseWrongFrontMatter", func() { _, err := NewPostOfMarkdown("testdata/post/post_wrong2.md", nil) So(err.Error(), ShouldContainSubstring, "unrecognized") _, err = NewPostOfMarkdown("testdata/post/post_wrong3.md", nil) So(err.Error(), ShouldContainSubstring, "need front-matter") }) }) }
func runRun(ctx *cli.Context) { setup(ctx) go catchSignals() go notify(setting.Cfg.Run.InitCmds) watchPathes := append([]string{setting.WorkDir}, setting.Cfg.Run.WatchDirs...) if setting.Cfg.Run.WatchAll { subdirs := make([]string, 0, 10) for _, dir := range watchPathes[1:] { dirs, err := com.GetAllSubDirs(setting.UnpackPath(dir)) if err != nil { log.Fatal("Fail to get sub-directories: %v", err) } for i := range dirs { if !setting.IgnoreDir(dirs[i]) { subdirs = append(subdirs, path.Join(dir, dirs[i])) } } } watchPathes = append(watchPathes, subdirs...) } watcher, err := fsnotify.NewWatcher() if err != nil { log.Fatal("Fail to create new watcher: %v", err) } defer watcher.Close() go func() { for { select { case e := <-watcher.Events: needsNotify := true if isTmpFile(e.Name) || !hasWatchExt(e.Name) || setting.IgnoreFile(e.Name) { continue } // Prevent duplicated builds. if lastBuild.Add(time.Duration(setting.Cfg.Run.BuildDelay) * time.Millisecond). After(time.Now()) { continue } lastBuild = time.Now() showName := e.String() if !log.NonColor { showName = strings.Replace(showName, setting.WorkDir, "\033[47;30m$WORKDIR\033[0m", 1) } if e.Op&fsnotify.Remove != fsnotify.Remove { mt, err := com.FileMTime(e.Name) if err != nil { log.Error("Fail to get file modify time: %v", err) continue } if eventTime[e.Name] == mt { log.Debug("Skipped %s", showName) needsNotify = false } eventTime[e.Name] = mt } if needsNotify { log.Info(showName) if runningCmd != nil && runningCmd.Process != nil { if runningCmd.Args[0] == "sudo" && runtime.GOOS == "linux" { // 给父进程发送一个TERM信号,试图杀死它和它的子进程 rootCmd := exec.Command("sudo", "kill", "-TERM", com.ToStr(runningCmd.Process.Pid)) rootCmd.Stdout = os.Stdout rootCmd.Stderr = os.Stderr if err := rootCmd.Run(); err != nil { log.Error("Fail to start rootCmd %s", err.Error()) fmt.Print("\x07") } } else { shutdown <- true } } go notify(setting.Cfg.Run.Cmds) } } } }() log.Info("Following directories are monitored:") for i, p := range watchPathes { if err = watcher.Add(setting.UnpackPath(p)); err != nil { log.Fatal("Fail to watch diretory(%s): %v", p, err) } if i > 0 && !log.NonColor { p = strings.Replace(p, setting.WorkDir, "\033[47;30m$WORKDIR\033[0m", 1) p = strings.Replace(p, "$WORKDIR", "\033[47;30m$WORKDIR\033[0m", 1) } fmt.Printf("-> %s\n", p) } select {} }