mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
commands: Create new 'hugo list all' command
New: - command `hugo list all`, return all posts meta in csv format Refactoring: - move common parts in commands/list.go to function `buildSites` - change way to detect path to content See #5904
This commit is contained in:
parent
2278b0eb02
commit
5b4b8bb3c1
2 changed files with 164 additions and 57 deletions
151
commands/list.go
151
commands/list.go
|
@ -16,7 +16,8 @@ package commands
|
||||||
import (
|
import (
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/hugolib"
|
"github.com/gohugoio/hugo/hugolib"
|
||||||
|
@ -32,6 +33,32 @@ type listCmd struct {
|
||||||
*baseCmd
|
*baseCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (lc *listCmd) buildSites(config map[string]interface{}) (*hugolib.HugoSites, error) {
|
||||||
|
cfgInit := func(c *commandeer) error {
|
||||||
|
for key, value := range config {
|
||||||
|
c.Set(key, value)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := initializeConfig(true, false, &lc.hugoBuilderCommon, lc, cfgInit)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sites, err := hugolib.NewHugoSites(*c.DepsCfg)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, newSystemError("Error creating sites", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := sites.Build(hugolib.BuildCfg{SkipRender: true}); err != nil {
|
||||||
|
return nil, newSystemError("Error Processing Source Content", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sites, nil
|
||||||
|
}
|
||||||
|
|
||||||
func newListCmd() *listCmd {
|
func newListCmd() *listCmd {
|
||||||
cc := &listCmd{}
|
cc := &listCmd{}
|
||||||
|
|
||||||
|
@ -50,59 +77,30 @@ List requires a subcommand, e.g. ` + "`hugo list drafts`.",
|
||||||
Short: "List all drafts",
|
Short: "List all drafts",
|
||||||
Long: `List all of the drafts in your content directory.`,
|
Long: `List all of the drafts in your content directory.`,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
cfgInit := func(c *commandeer) error {
|
sites, err := cc.buildSites(map[string]interface{}{"buildDrafts": true})
|
||||||
c.Set("buildDrafts", true)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
c, err := initializeConfig(true, false, &cc.hugoBuilderCommon, cc, cfgInit)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
sites, err := hugolib.NewHugoSites(*c.DepsCfg)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newSystemError("Error creating sites", err)
|
return newSystemError("Error building sites", err)
|
||||||
}
|
|
||||||
|
|
||||||
if err := sites.Build(hugolib.BuildCfg{SkipRender: true}); err != nil {
|
|
||||||
return newSystemError("Error Processing Source Content", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, p := range sites.Pages() {
|
for _, p := range sites.Pages() {
|
||||||
if p.Draft() {
|
if p.Draft() {
|
||||||
jww.FEEDBACK.Println(filepath.Join(p.File().Dir(), p.File().LogicalName()))
|
jww.FEEDBACK.Println(strings.TrimPrefix(p.File().Filename(), sites.WorkingDir+string(os.PathSeparator)))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&cobra.Command{
|
&cobra.Command{
|
||||||
Use: "future",
|
Use: "future",
|
||||||
Short: "List all posts dated in the future",
|
Short: "List all posts dated in the future",
|
||||||
Long: `List all of the posts in your content directory which will be
|
Long: `List all of the posts in your content directory which will be posted in the future.`,
|
||||||
posted in the future.`,
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
cfgInit := func(c *commandeer) error {
|
sites, err := cc.buildSites(map[string]interface{}{"buildFuture": true})
|
||||||
c.Set("buildFuture", true)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
c, err := initializeConfig(true, false, &cc.hugoBuilderCommon, cc, cfgInit)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
sites, err := hugolib.NewHugoSites(*c.DepsCfg)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newSystemError("Error creating sites", err)
|
return newSystemError("Error building sites", err)
|
||||||
}
|
|
||||||
|
|
||||||
if err := sites.Build(hugolib.BuildCfg{SkipRender: true}); err != nil {
|
|
||||||
return newSystemError("Error Processing Source Content", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
writer := csv.NewWriter(os.Stdout)
|
writer := csv.NewWriter(os.Stdout)
|
||||||
|
@ -110,7 +108,10 @@ posted in the future.`,
|
||||||
|
|
||||||
for _, p := range sites.Pages() {
|
for _, p := range sites.Pages() {
|
||||||
if resource.IsFuture(p) {
|
if resource.IsFuture(p) {
|
||||||
err := writer.Write([]string{filepath.Join(p.File().Dir(), p.File().LogicalName()), p.PublishDate().Format(time.RFC3339)})
|
err := writer.Write([]string{
|
||||||
|
strings.TrimPrefix(p.File().Filename(), sites.WorkingDir+string(os.PathSeparator)),
|
||||||
|
p.PublishDate().Format(time.RFC3339),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newSystemError("Error writing future posts to stdout", err)
|
return newSystemError("Error writing future posts to stdout", err)
|
||||||
}
|
}
|
||||||
|
@ -118,32 +119,17 @@ posted in the future.`,
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&cobra.Command{
|
&cobra.Command{
|
||||||
Use: "expired",
|
Use: "expired",
|
||||||
Short: "List all posts already expired",
|
Short: "List all posts already expired",
|
||||||
Long: `List all of the posts in your content directory which has already
|
Long: `List all of the posts in your content directory which has already expired.`,
|
||||||
expired.`,
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
cfgInit := func(c *commandeer) error {
|
sites, err := cc.buildSites(map[string]interface{}{"buildExpired": true})
|
||||||
c.Set("buildExpired", true)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
c, err := initializeConfig(true, false, &cc.hugoBuilderCommon, cc, cfgInit)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
sites, err := hugolib.NewHugoSites(*c.DepsCfg)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newSystemError("Error creating sites", err)
|
return newSystemError("Error building sites", err)
|
||||||
}
|
|
||||||
|
|
||||||
if err := sites.Build(hugolib.BuildCfg{SkipRender: true}); err != nil {
|
|
||||||
return newSystemError("Error Processing Source Content", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
writer := csv.NewWriter(os.Stdout)
|
writer := csv.NewWriter(os.Stdout)
|
||||||
|
@ -151,16 +137,67 @@ expired.`,
|
||||||
|
|
||||||
for _, p := range sites.Pages() {
|
for _, p := range sites.Pages() {
|
||||||
if resource.IsExpired(p) {
|
if resource.IsExpired(p) {
|
||||||
err := writer.Write([]string{filepath.Join(p.File().Dir(), p.File().LogicalName()), p.ExpiryDate().Format(time.RFC3339)})
|
err := writer.Write([]string{
|
||||||
|
strings.TrimPrefix(p.File().Filename(), sites.WorkingDir+string(os.PathSeparator)),
|
||||||
|
p.ExpiryDate().Format(time.RFC3339),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newSystemError("Error writing expired posts to stdout", err)
|
return newSystemError("Error writing expired posts to stdout", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "all",
|
||||||
|
Short: "List all posts",
|
||||||
|
Long: `List all of the posts in your content directory, include drafts, future and expired pages.`,
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
sites, err := cc.buildSites(map[string]interface{}{
|
||||||
|
"buildExpired": true,
|
||||||
|
"buildDrafts": true,
|
||||||
|
"buildFuture": true,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return newSystemError("Error building sites", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
writer := csv.NewWriter(os.Stdout)
|
||||||
|
defer writer.Flush()
|
||||||
|
|
||||||
|
writer.Write([]string{
|
||||||
|
"path",
|
||||||
|
"slug",
|
||||||
|
"title",
|
||||||
|
"date",
|
||||||
|
"expiryDate",
|
||||||
|
"publishDate",
|
||||||
|
"draft",
|
||||||
|
"permalink",
|
||||||
|
})
|
||||||
|
for _, p := range sites.Pages() {
|
||||||
|
if !p.IsPage() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
err := writer.Write([]string{
|
||||||
|
strings.TrimPrefix(p.File().Filename(), sites.WorkingDir+string(os.PathSeparator)),
|
||||||
|
p.Slug(),
|
||||||
|
p.Title(),
|
||||||
|
p.Date().Format(time.RFC3339),
|
||||||
|
p.ExpiryDate().Format(time.RFC3339),
|
||||||
|
p.PublishDate().Format(time.RFC3339),
|
||||||
|
strconv.FormatBool(p.Draft()),
|
||||||
|
p.Permalink(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return newSystemError("Error writing posts to stdout", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
70
commands/list_test.go
Normal file
70
commands/list_test.go
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/csv"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func captureStdout(f func() (*cobra.Command, error)) (string, error) {
|
||||||
|
old := os.Stdout
|
||||||
|
r, w, _ := os.Pipe()
|
||||||
|
os.Stdout = w
|
||||||
|
|
||||||
|
_, err := f()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Close()
|
||||||
|
os.Stdout = old
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
io.Copy(&buf, r)
|
||||||
|
return buf.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListAll(t *testing.T) {
|
||||||
|
assert := require.New(t)
|
||||||
|
dir, err := createSimpleTestSite(t, testSiteConfig{})
|
||||||
|
|
||||||
|
assert.NoError(err)
|
||||||
|
|
||||||
|
hugoCmd := newCommandsBuilder().addAll().build()
|
||||||
|
cmd := hugoCmd.getCommand()
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
os.RemoveAll(dir)
|
||||||
|
}()
|
||||||
|
|
||||||
|
cmd.SetArgs([]string{"-s=" + dir, "list", "all"})
|
||||||
|
|
||||||
|
out, err := captureStdout(cmd.ExecuteC)
|
||||||
|
assert.NoError(err)
|
||||||
|
|
||||||
|
r := csv.NewReader(strings.NewReader(out))
|
||||||
|
|
||||||
|
header, err := r.Read()
|
||||||
|
assert.NoError(err)
|
||||||
|
|
||||||
|
assert.Equal([]string{
|
||||||
|
"path", "slug", "title",
|
||||||
|
"date", "expiryDate", "publishDate",
|
||||||
|
"draft", "permalink",
|
||||||
|
}, header)
|
||||||
|
|
||||||
|
record, err := r.Read()
|
||||||
|
assert.Equal([]string{
|
||||||
|
filepath.Join("content", "p1.md"), "", "P1",
|
||||||
|
"0001-01-01T00:00:00Z", "0001-01-01T00:00:00Z", "0001-01-01T00:00:00Z",
|
||||||
|
"false", "https://example.org/p1/",
|
||||||
|
}, record)
|
||||||
|
}
|
Loading…
Reference in a new issue