]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
Add `--force` to `hugo new`
authorsatotake <doublequotation@gmail.com>
Wed, 31 Aug 2022 15:23:31 +0000 (00:23 +0900)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Thu, 8 Sep 2022 13:35:11 +0000 (15:35 +0200)
Closes #9243

commands/new.go
create/content.go
create/content_test.go
hugolib/content_factory.go
hugolib/content_factory_test.go

index c5b5cd182715b5c64e04b11efce5d689cf4cc4a4..bf626a6a51af6ca3ff6097a47d68dea8a2d82fb9 100644 (file)
@@ -32,6 +32,7 @@ var _ cmder = (*newCmd)(nil)
 type newCmd struct {
        contentEditor string
        contentType   string
+       force         bool
 
        *baseBuilderCmd
 }
@@ -54,6 +55,7 @@ Ensure you run this within the root directory of your site.`,
 
        cmd.Flags().StringVarP(&cc.contentType, "kind", "k", "", "content type to create")
        cmd.Flags().StringVar(&cc.contentEditor, "editor", "", "edit new content with this editor, if provided")
+       cmd.Flags().BoolVarP(&cc.force, "force", "f", false, "allow to override file")
 
        cmd.AddCommand(b.newNewSiteCmd().getCommand())
        cmd.AddCommand(b.newNewThemeCmd().getCommand())
@@ -80,7 +82,7 @@ func (n *newCmd) newContent(cmd *cobra.Command, args []string) error {
                return newUserError("path needs to be provided")
        }
 
-       return create.NewContent(c.hugo(), n.contentType, args[0])
+       return create.NewContent(c.hugo(), n.contentType, args[0], n.force)
 }
 
 func mkdir(x ...string) {
index 5f05e25f9d95bdf0d2967aecc0c3d3a93b116ca3..0b9f277970ce92f7ca0bd013632ec74a0bcb4700 100644 (file)
@@ -52,7 +52,7 @@ draft: true
 
 // NewContent creates a new content file in h (or a full bundle if the archetype is a directory)
 // in targetPath.
-func NewContent(h *hugolib.HugoSites, kind, targetPath string) error {
+func NewContent(h *hugolib.HugoSites, kind, targetPath string, force bool) error {
        if h.BaseFs.Content.Dirs == nil {
                return errors.New("no existing content directory configured for this project")
        }
@@ -76,6 +76,7 @@ func NewContent(h *hugolib.HugoSites, kind, targetPath string) error {
 
                kind:       kind,
                targetPath: targetPath,
+               force:      force,
        }
 
        ext := paths.Ext(targetPath)
@@ -132,6 +133,7 @@ type contentBuilder struct {
        kind              string
        isDir             bool
        dirMap            archetypeMap
+       force             bool
 }
 
 func (b *contentBuilder) buildDir() error {
@@ -145,7 +147,7 @@ func (b *contentBuilder) buildDir() error {
 
        for _, fi := range b.dirMap.contentFiles {
                targetFilename := filepath.Join(b.targetPath, strings.TrimPrefix(fi.Meta().Path, b.archetypeFilename))
-               abs, err := b.cf.CreateContentPlaceHolder(targetFilename)
+               abs, err := b.cf.CreateContentPlaceHolder(targetFilename, b.force)
                if err != nil {
                        return err
                }
@@ -218,7 +220,7 @@ func (b *contentBuilder) buildDir() error {
 }
 
 func (b *contentBuilder) buildFile() (string, error) {
-       contentPlaceholderAbsFilename, err := b.cf.CreateContentPlaceHolder(b.targetPath)
+       contentPlaceholderAbsFilename, err := b.cf.CreateContentPlaceHolder(b.targetPath, b.force)
        if err != nil {
                return "", err
        }
index 80a66609367f0473cf05f2b09cb6649a53a8254e..fdfee6e68c4e9e7f85b3964d0e1a72083b64e5a6 100644 (file)
@@ -82,7 +82,7 @@ func TestNewContentFromFile(t *testing.T) {
                        cfg, fs := newTestCfg(c, mm)
                        h, err := hugolib.NewHugoSites(deps.DepsCfg{Cfg: cfg, Fs: fs})
                        c.Assert(err, qt.IsNil)
-                       err = create.NewContent(h, cas.kind, cas.path)
+                       err = create.NewContent(h, cas.kind, cas.path, false)
 
                        if b, ok := cas.expected.(bool); ok && !b {
                                if !b {
@@ -145,7 +145,7 @@ i18n: {{ T "hugo" }}
        c.Assert(err, qt.IsNil)
        c.Assert(len(h.Sites), qt.Equals, 2)
 
-       c.Assert(create.NewContent(h, "my-bundle", "post/my-post"), qt.IsNil)
+       c.Assert(create.NewContent(h, "my-bundle", "post/my-post", false), qt.IsNil)
 
        cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/resources/hugo1.json")), `hugo1: {{ printf "no template handling in here" }}`)
        cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/resources/hugo2.xml")), `hugo2: {{ printf "no template handling in here" }}`)
@@ -157,7 +157,7 @@ i18n: {{ T "hugo" }}
 
        cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/pages/bio.md")), `File: bio.md`, `Site Lang: en`, `Name: Bio`)
 
-       c.Assert(create.NewContent(h, "my-theme-bundle", "post/my-theme-post"), qt.IsNil)
+       c.Assert(create.NewContent(h, "my-theme-bundle", "post/my-theme-post", false), qt.IsNil)
        cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-theme-post/index.md")), `File: index.md`, `Site Lang: en`, `Name: My Theme Post`, `i18n: Hugo Rocks!`)
        cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-theme-post/resources/hugo1.json")), `hugo1: {{ printf "no template handling in here" }}`)
 }
@@ -187,19 +187,19 @@ site RegularPages: {{ len site.RegularPages  }}
        c.Assert(err, qt.IsNil)
        c.Assert(len(h.Sites), qt.Equals, 2)
 
-       c.Assert(create.NewContent(h, "my-bundle", "post/my-post"), qt.IsNil)
+       c.Assert(create.NewContent(h, "my-bundle", "post/my-post", false), qt.IsNil)
        cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/index.md")), `site RegularPages: 10`)
 
        // Default bundle archetype
-       c.Assert(create.NewContent(h, "", "post/my-post2"), qt.IsNil)
+       c.Assert(create.NewContent(h, "", "post/my-post2", false), qt.IsNil)
        cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post2/index.md")), `default archetype index.md`)
 
        // Regular file with bundle kind.
-       c.Assert(create.NewContent(h, "my-bundle", "post/foo.md"), qt.IsNil)
+       c.Assert(create.NewContent(h, "my-bundle", "post/foo.md", false), qt.IsNil)
        cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/foo.md")), `draft: true`)
 
        // Regular files should fall back to the default archetype (we have no regular file archetype).
-       c.Assert(create.NewContent(h, "my-bundle", "mypage.md"), qt.IsNil)
+       c.Assert(create.NewContent(h, "my-bundle", "mypage.md", false), qt.IsNil)
        cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "mypage.md")), `draft: true`)
 
 }
@@ -237,7 +237,7 @@ i18n: {{ T "hugo" }}
        c.Assert(err, qt.IsNil)
        c.Assert(len(h.Sites), qt.Equals, 2)
 
-       c.Assert(create.NewContent(h, "my-bundle", "post/my-post"), qt.IsNil)
+       c.Assert(create.NewContent(h, "my-bundle", "post/my-post", false), qt.IsNil)
 
        cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/resources/hugo1.json")), `hugo1: {{ printf "no template handling in here" }}`)
        cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/resources/hugo2.xml")), `hugo2: {{ printf "no template handling in here" }}`)
@@ -247,11 +247,38 @@ i18n: {{ T "hugo" }}
 
        cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/pages/bio.md")), `File: bio.md`, `Name: Bio`)
 
-       c.Assert(create.NewContent(h, "my-theme-bundle", "post/my-theme-post"), qt.IsNil)
+       c.Assert(create.NewContent(h, "my-theme-bundle", "post/my-theme-post", false), qt.IsNil)
        cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-theme-post/index.md")), `File: index.md`, `Name: My Theme Post`, `i18n: Hugo Rocks!`)
        cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-theme-post/resources/hugo1.json")), `hugo1: {{ printf "no template handling in here" }}`)
 }
 
+func TestNewContentForce(t *testing.T) {
+       mm := afero.NewMemMapFs()
+       c := qt.New(t)
+
+       archetypeDir := filepath.Join("archetypes", "my-bundle")
+       c.Assert(mm.MkdirAll(archetypeDir, 0o755), qt.IsNil)
+       c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "index.md"), []byte(""), 0o755), qt.IsNil)
+       c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "index.nn.md"), []byte(""), 0o755), qt.IsNil)
+
+       c.Assert(initFs(mm), qt.IsNil)
+       cfg, fs := newTestCfg(c, mm)
+
+       h, err := hugolib.NewHugoSites(deps.DepsCfg{Cfg: cfg, Fs: fs})
+       c.Assert(err, qt.IsNil)
+       c.Assert(len(h.Sites), qt.Equals, 2)
+
+       // from file
+       c.Assert(create.NewContent(h, "post", "post/my-post.md", false), qt.IsNil)
+       c.Assert(create.NewContent(h, "post", "post/my-post.md", false), qt.IsNotNil)
+       c.Assert(create.NewContent(h, "post", "post/my-post.md", true), qt.IsNil)
+
+       // from dir
+       c.Assert(create.NewContent(h, "my-bundle", "post/my-post", false), qt.IsNil)
+       c.Assert(create.NewContent(h, "my-bundle", "post/my-post", false), qt.IsNotNil)
+       c.Assert(create.NewContent(h, "my-bundle", "post/my-post", true), qt.IsNil)
+}
+
 func initFs(fs afero.Fs) error {
        perm := os.FileMode(0o755)
        var err error
index 0a4d0aa0aa851b63b5ea05d1f81ee392e6f31557..017a0bc979c656c15142d40f9d4b5728c973693d 100644 (file)
@@ -110,7 +110,7 @@ func (f ContentFactory) SectionFromFilename(filename string) (string, error) {
 
 // CreateContentPlaceHolder creates a content placeholder file inside the
 // best matching content directory.
-func (f ContentFactory) CreateContentPlaceHolder(filename string) (string, error) {
+func (f ContentFactory) CreateContentPlaceHolder(filename string, force bool) (string, error) {
        filename = filepath.Clean(filename)
        _, abs, err := f.h.AbsProjectContentDir(filename)
 
@@ -130,6 +130,9 @@ _build:
 
 `
 
+       if force {
+               return abs, afero.WriteReader(f.h.Fs.Source, abs, strings.NewReader(placeholder))
+       }
        return abs, afero.SafeWriteReader(f.h.Fs.Source, abs, strings.NewReader(placeholder))
 }
 
index 23dcd660ac412553813cee280fd18e2ce15a2282..2c4b843a92fe674cab0d54323e3888eb89e2e0fa 100644 (file)
@@ -43,7 +43,7 @@ Hello World.
 `)
                b.CreateSites()
                cf := NewContentFactory(b.H)
-               abs, err := cf.CreateContentPlaceHolder(filepath.FromSlash("mcontent/en/blog/mypage.md"))
+               abs, err := cf.CreateContentPlaceHolder(filepath.FromSlash("mcontent/en/blog/mypage.md"), false)
                b.Assert(err, qt.IsNil)
                b.Assert(abs, qt.Equals, filepath.FromSlash("/my/work/mcontent/en/blog/mypage.md"))
                b.Build(BuildCfg{SkipRender: true})
@@ -69,7 +69,7 @@ theme = 'ipsum'
                b.WithSourceFile(filepath.Join(themeDir, "content/posts/foo.txt"), `Hello.`)
                b.CreateSites()
                cf := NewContentFactory(b.H)
-               abs, err := cf.CreateContentPlaceHolder(filepath.FromSlash("posts/test.md"))
+               abs, err := cf.CreateContentPlaceHolder(filepath.FromSlash("posts/test.md"), false)
                b.Assert(err, qt.IsNil)
                b.Assert(abs, qt.Equals, filepath.FromSlash("content/posts/test.md"))