2021-03-20 20:40:40 +00:00
|
|
|
// SPDX-FileCopyrightText: 2021 Luke Granger-Brown <depot@lukegb.com>
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
2021-03-20 19:53:04 +00:00
|
|
|
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
|
|
|
|
})
|
|
|
|
},
|
|
|
|
}
|
|
|
|
)
|