package main import ( "bufio" "bytes" "flag" "io/ioutil" "log" "os" "path" "strings" "time" "github.com/BurntSushi/toml" ) const ( pageDir = "content/plugins/" ) type page struct { header meta content string } type meta struct { Title string `toml:"title"` Description string `toml:"description"` Weight int `toml:"weight"` Tags []string `toml:"tags"` Categories []string `toml:"categories"` Date string `toml:"date"` } var ( pluginDir = flag.String("plugindir", ".coredns/plugin", "directory where to find coredns") ) func main() { flag.Parse() // Current pages pages, err := getPages(pageDir) if err != nil { log.Fatalf("Failed getting all page contents: %s", err) } // Incoming content plugins, err := getContent(*pluginDir) if err != nil { log.Fatalf("Failed getting all plugin contents: %s", err) } neg, pos := compare(plugins, pages) if neg == nil && pos == nil { log.Printf("Nothing to update.") } // Remove any plugin files not present upstream for _, p := range neg { path := path.Join(pageDir, p) err := os.Remove(path + ".md") if err != nil { log.Fatalf("Error deleting file file %s: %s", path, err) } log.Printf("Removed content file: %s", path+".md") } // Overwrite/create necessary content files with toml header for _, p := range pos { h := plugins[p].header h.Date = time.Now().UTC().Format("2006-01-02T15:04:05.877581") h.Tags = []string{"plugin", h.Title} h.Categories = []string{"plugin"} var buf bytes.Buffer err := toml.NewEncoder(&buf).Encode(h) if err != nil { log.Fatalf("Error creating TOML header data: %s", err) } headerData := buf.String() contentData := plugins[p].content filePath := path.Join(pageDir, p) fileContent := strings.Join([]string{"", headerData, contentData}, "+++\n") err = ioutil.WriteFile(filePath+".md", []byte(fileContent), 0644) if err != nil { log.Fatalf("Error writing file: %s", err) } log.Printf("Wrote content changes %s to %s", path.Join(*pluginDir, p, "README.md"), filePath) } } // Get current content pages from hugo content directory // Returned map doesn't include header data as this isn't needed currently func getPages(pageDir string) (pages map[string]page, err error) { pages = make(map[string]page) pd, err := ioutil.ReadDir(pageDir) if err != nil { return nil, err } for _, p := range pd { if p.IsDir() { continue } path := path.Join(pageDir, p.Name()) file, err := os.Open(path) if err != nil { return nil, err } defer file.Close() var content string headerSeparator := 0 scanner := bufio.NewScanner(file) for scanner.Scan() { if headerSeparator == 2 { content += scanner.Text() + "\n" } if scanner.Text() == "+++" { headerSeparator++ } } pageData := page{content: content} pages[strings.Replace(p.Name(), ".md", "", -1)] = pageData } return pages, nil } // Get latest content from coreDNS code directory func getContent(pluginDir string) (plugins map[string]page, err error) { plugins = make(map[string]page) pl, err := ioutil.ReadDir(pluginDir) if err != nil { return nil, err } weight := 0 for _, p := range pl { if !p.IsDir() { continue } if getBlacklist()[p.Name()] { continue } weight++ path := path.Join(pluginDir, p.Name(), "README.md") file, err := os.Open(path) if err != nil { return nil, err } defer file.Close() var header meta var content string headerStarted := false contentStarted := false scanner := bufio.NewScanner(file) for scanner.Scan() { if contentStarted { content += scanner.Text() + "\n" } if headerStarted && scanner.Text() != "" { rawHeader := strings.Split(scanner.Text(), " - ") title := strings.Replace(rawHeader[0], "*", "", -1) header.Title = title header.Description = strings.Join([]string{"*", title, "* ", rawHeader[1]}, "") header.Weight = weight headerStarted = false contentStarted = true } if scanner.Text() == "## Name" { headerStarted = true } } pluginData := page{header: header, content: content} plugins[p.Name()] = pluginData } return plugins, nil } // Compare current and incoming state // Return a negative list to delete // Return a positive list to create/overwrite func compare(plugins map[string]page, pages map[string]page) (neg []string, pos []string) { // Prepare list of pages to delete for k := range pages { if _, ok := plugins[k]; !ok { neg = append(neg, k) } } // Prepare list of pages to create for k := range plugins { // New pages to create if _, ok := pages[k]; !ok { pos = append(pos, k) } // Check necessity for an update if plugins[k].content != pages[k].content { pos = append(pos, k) } } return neg, pos } // Return directory blacklist func getBlacklist() map[string]bool { var bl = map[string]bool{ "test": true, "pkg": true, "deprecated": true, } return bl }