depot/web/fup/cmd/extractstatic.go

88 lines
2.3 KiB
Go
Raw Normal View History

2021-03-20 20:40:40 +00:00
// SPDX-FileCopyrightText: 2021 Luke Granger-Brown <depot@lukegb.com>
//
// SPDX-License-Identifier: Apache-2.0
package cmd
import (
"fmt"
"io"
"io/fs"
"log"
"os"
"path/filepath"
"github.com/spf13/cobra"
"hg.lukegb.com/lukegb/depot/web/fup/fupstatic"
)
func init() {
rootCmd.AddCommand(extractstaticCmd)
extractstaticCmd.Flags().BoolVarP(&extractstaticForceOverwrite, "force", "f", false, "If set, will overwrite existing files.")
}
var (
extractstaticForceOverwrite bool
extractstaticCmd = &cobra.Command{
Use: "extractstatic dir",
Example: "extractstatic /srv/http/static",
Short: "Extracts static assets into a target directory.",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
targetDir := args[0]
log.Printf("extracting assets to %v", targetDir)
return fs.WalkDir(fupstatic.Static, ".", func(fpath string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
targetPath := filepath.Join(targetDir, fpath)
fi, err := os.Stat(targetPath)
if err != nil && !os.IsNotExist(err) {
return fmt.Errorf("checking for existence of %q: %w", targetPath, err)
}
if d.IsDir() {
switch {
case fi != nil && !fi.IsDir():
return fmt.Errorf("%q already exists and is not a directory", targetPath)
case fi != nil:
return nil
default:
// Ensure directory exists.
return os.Mkdir(filepath.Join(targetDir, fpath), 0755)
}
}
switch {
case fi != nil && fi.IsDir():
return fmt.Errorf("%q already exists and is a directory", targetPath)
case fi != nil && !extractstaticForceOverwrite:
return nil
}
src, err := fupstatic.Static.Open(fpath)
if err != nil {
return fmt.Errorf("open source %q: %w", fpath, err)
}
defer src.Close() // Don't care about errors for closing read-only file.
dst, err := os.Create(targetPath)
if err != nil {
return fmt.Errorf("create target %q: %w", targetPath, err)
}
if _, err := io.Copy(dst, src); err != nil {
return fmt.Errorf("copying from source %q to target %q: %w", fpath, targetPath, err)
}
if err := dst.Close(); err != nil {
return fmt.Errorf("close target %q: %w", targetPath, err)
}
return nil
})
},
}
)