Use fsx package and friends from pkglib
This commit is contained in:
parent
1f8c55da7c
commit
0f6803f890
35 changed files with 91 additions and 493 deletions
|
|
@ -10,9 +10,10 @@ import (
|
|||
"github.com/FAU-CDI/wisski-distillery/internal/cli"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/config"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/logging"
|
||||
"github.com/tkw1536/goprogram/exit"
|
||||
"github.com/tkw1536/pkglib/fsx"
|
||||
"github.com/tkw1536/pkglib/fsx/umaskfree"
|
||||
)
|
||||
|
||||
// Bootstrap is the 'bootstrap' command
|
||||
|
|
@ -81,7 +82,7 @@ func (bs cBootstrap) Run(context wisski_distillery.Context) error {
|
|||
|
||||
{
|
||||
logging.LogMessage(context.Stderr, "Creating root deployment directory")
|
||||
if err := fsx.MkdirAll(root, fsx.DefaultDirPerm); err != nil {
|
||||
if err := umaskfree.MkdirAll(root, umaskfree.DefaultDirPerm); err != nil {
|
||||
return errBootstrapFailedToCreateDirectory.WithMessageF(root).Wrap(err)
|
||||
}
|
||||
if err := cli.WriteBaseDirectory(root); err != nil {
|
||||
|
|
@ -111,22 +112,22 @@ func (bs cBootstrap) Run(context wisski_distillery.Context) error {
|
|||
return errBoostrapFailedToCopyExe.WithMessageF(err)
|
||||
}
|
||||
|
||||
err = fsx.CopyFile(context.Context, wdcliPath, exe)
|
||||
if err != nil && err != fsx.ErrCopySameFile {
|
||||
err = umaskfree.CopyFile(context.Context, wdcliPath, exe)
|
||||
if err != nil && err != umaskfree.ErrCopySameFile {
|
||||
return errBoostrapFailedToCopyExe.WithMessageF(err)
|
||||
}
|
||||
context.Println(wdcliPath)
|
||||
}
|
||||
|
||||
{
|
||||
if !fsx.IsFile(cfgPath) {
|
||||
if !fsx.IsRegular(cfgPath) {
|
||||
// generate the configuration from the template
|
||||
cfg := tpl.Generate()
|
||||
|
||||
// write out all the extra config files
|
||||
if err := logging.LogOperation(func() error {
|
||||
context.Println(cfg.Paths.OverridesJSON)
|
||||
if err := fsx.WriteFile(
|
||||
if err := umaskfree.WriteFile(
|
||||
cfg.Paths.OverridesJSON,
|
||||
bootstrap.DefaultOverridesJSON,
|
||||
fs.ModePerm,
|
||||
|
|
@ -135,7 +136,7 @@ func (bs cBootstrap) Run(context wisski_distillery.Context) error {
|
|||
}
|
||||
|
||||
context.Println(cfg.Paths.ResolverBlocks)
|
||||
if err := fsx.WriteFile(
|
||||
if err := umaskfree.WriteFile(
|
||||
cfg.Paths.ResolverBlocks,
|
||||
bootstrap.DefaultResolverBlockedTXT,
|
||||
fs.ModePerm,
|
||||
|
|
@ -155,7 +156,7 @@ func (bs cBootstrap) Run(context wisski_distillery.Context) error {
|
|||
|
||||
// and marshal it out!
|
||||
if err := logging.LogOperation(func() error {
|
||||
configYML, err := fsx.Create(cfgPath, fsx.DefaultFilePerm)
|
||||
configYML, err := umaskfree.Create(cfgPath, umaskfree.DefaultFilePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ package cmd
|
|||
import (
|
||||
wisski_distillery "github.com/FAU-CDI/wisski-distillery"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/cli"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/logging"
|
||||
"github.com/tkw1536/pkglib/fsx"
|
||||
)
|
||||
|
||||
// Monday is the 'monday' command
|
||||
|
|
@ -28,7 +28,7 @@ func (monday) Description() wisski_distillery.Description {
|
|||
}
|
||||
|
||||
func (monday monday) AfterParse() error {
|
||||
if !fsx.IsFile(monday.Positionals.GraphdbZip) {
|
||||
if !fsx.IsRegular(monday.Positionals.GraphdbZip) {
|
||||
return errNoGraphDBZip.WithMessageF(monday.Positionals.GraphdbZip)
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ import (
|
|||
wisski_distillery "github.com/FAU-CDI/wisski-distillery"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/cli"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/logging"
|
||||
"github.com/tkw1536/goprogram/exit"
|
||||
"github.com/tkw1536/pkglib/fsx"
|
||||
)
|
||||
|
||||
// Reserve is the 'reserve' command
|
||||
|
|
|
|||
|
|
@ -9,10 +9,11 @@ import (
|
|||
"github.com/FAU-CDI/wisski-distillery/internal/cli"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/execx"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/logging"
|
||||
"github.com/tkw1536/goprogram/exit"
|
||||
"github.com/tkw1536/goprogram/parser"
|
||||
"github.com/tkw1536/pkglib/fsx"
|
||||
"github.com/tkw1536/pkglib/fsx/umaskfree"
|
||||
"github.com/tkw1536/pkglib/status"
|
||||
)
|
||||
|
||||
|
|
@ -46,7 +47,7 @@ var errNoGraphDBZip = exit.Error{
|
|||
|
||||
func (s systemupdate) AfterParse() error {
|
||||
// TODO: Use a generic environment here!
|
||||
if !fsx.IsFile(s.Positionals.GraphdbZip) {
|
||||
if !fsx.IsRegular(s.Positionals.GraphdbZip) {
|
||||
return errNoGraphDBZip.WithMessageF(s.Positionals.GraphdbZip)
|
||||
}
|
||||
return nil
|
||||
|
|
@ -92,7 +93,7 @@ func (si systemupdate) Run(context wisski_distillery.Context) (err error) {
|
|||
dis.Templating().CustomAssetsPath(),
|
||||
} {
|
||||
context.Println(d)
|
||||
if err := fsx.MkdirAll(d, fsx.DefaultDirPerm); err != nil {
|
||||
if err := umaskfree.MkdirAll(d, umaskfree.DefaultDirPerm); err != nil {
|
||||
return errBoostrapFailedToCreateDirectory.WithMessageF(d).Wrap(err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -16,7 +16,7 @@ require (
|
|||
github.com/pquerna/otp v1.4.0
|
||||
github.com/rs/zerolog v1.29.0
|
||||
github.com/tkw1536/goprogram v0.3.5
|
||||
github.com/tkw1536/pkglib v0.0.0-20230319133918-3edc36187874
|
||||
github.com/tkw1536/pkglib v0.0.0-20230408155139-3ef777879e0f
|
||||
github.com/yuin/goldmark v1.5.4
|
||||
github.com/yuin/goldmark-meta v1.1.0
|
||||
golang.org/x/crypto v0.7.0
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -115,8 +115,8 @@ github.com/tdewolff/parse v2.3.4+incompatible/go.mod h1:8oBwCsVmUkgHO8M5iCzSIDtp
|
|||
github.com/tdewolff/test v1.0.7 h1:8Vs0142DmPFW/bQeHRP3MV19m1gvndjUb1sn8yy74LM=
|
||||
github.com/tkw1536/goprogram v0.3.5 h1:S0axKo3R/vGa4zhYqYDKAZEPhAfwUSSeMtVwnAu4sNY=
|
||||
github.com/tkw1536/goprogram v0.3.5/go.mod h1:pYr4dMHOSVurbPQ4KTR0ett8XWNISbsRS6zlh9Nsxa8=
|
||||
github.com/tkw1536/pkglib v0.0.0-20230319133918-3edc36187874 h1:BrsHJnkecpO1OOXiuFcJG2t4EiaLhhMdLMrfPldYWl4=
|
||||
github.com/tkw1536/pkglib v0.0.0-20230319133918-3edc36187874/go.mod h1:RjPEyRcq+g1GMd3D/o7d9WCtVNXY4QZyFRs9hLlZbew=
|
||||
github.com/tkw1536/pkglib v0.0.0-20230408155139-3ef777879e0f h1:sGb/t/cM2extjiArB6q0Yx1f4IK2NyZ5Kw3lP2w8Vg4=
|
||||
github.com/tkw1536/pkglib v0.0.0-20230408155139-3ef777879e0f/go.mod h1:RjPEyRcq+g1GMd3D/o7d9WCtVNXY4QZyFRs9hLlZbew=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/bootstrap"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||
"github.com/tkw1536/pkglib/fsx/umaskfree"
|
||||
)
|
||||
|
||||
// metaConfigFile is the path to a configuration file that contains the path to the last used wdcli executable.
|
||||
|
|
@ -68,5 +68,5 @@ func WriteBaseDirectory(dir string) error {
|
|||
}
|
||||
|
||||
// just put the directory inside it!
|
||||
return fsx.WriteFile(path, []byte(dir), fs.ModePerm)
|
||||
return umaskfree.WriteFile(path, []byte(dir), fs.ModePerm)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/bootstrap"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||
"github.com/tkw1536/pkglib/fsx"
|
||||
)
|
||||
|
||||
type PathsConfig struct {
|
||||
|
|
@ -38,14 +38,14 @@ func (pcfg PathsConfig) UsingDistilleryExecutable() bool {
|
|||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return fsx.SameFile(exe, pcfg.ExecutablePath())
|
||||
return fsx.Same(exe, pcfg.ExecutablePath())
|
||||
}
|
||||
|
||||
// CurrentExecutable returns the path to the current executable being used.
|
||||
// When it does not exist, falls back to the default executable.
|
||||
func (pcfg PathsConfig) CurrentExecutable() string {
|
||||
exe, err := os.Executable()
|
||||
if err != nil || !fsx.IsFile(exe) {
|
||||
if err != nil || !fsx.IsRegular(exe) {
|
||||
return pcfg.ExecutablePath()
|
||||
}
|
||||
return exe
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
package validators
|
||||
|
||||
import (
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tkw1536/pkglib/fsx"
|
||||
)
|
||||
|
||||
func ValidateFile(path *string, dflt string) error {
|
||||
if *path == "" {
|
||||
*path = dflt
|
||||
}
|
||||
if !fsx.IsFile(*path) {
|
||||
if !fsx.IsRegular(*path) {
|
||||
return errors.Errorf("%q does not exist or is not a file", *path)
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package auth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
|
|
@ -14,7 +15,6 @@ import (
|
|||
"github.com/pquerna/otp"
|
||||
"github.com/pquerna/otp/totp"
|
||||
"github.com/tkw1536/pkglib/password"
|
||||
"github.com/tkw1536/pkglib/pools"
|
||||
"github.com/tkw1536/pkglib/reflectx"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
|
@ -187,10 +187,9 @@ func TOTPLink(secret *otp.Key, width, height int) (string, error) {
|
|||
}
|
||||
|
||||
// encode image as base64
|
||||
buffer := pools.GetBuffer()
|
||||
defer pools.ReleaseBuffer(buffer)
|
||||
var buffer bytes.Buffer
|
||||
|
||||
if err := png.Encode(buffer, img); err != nil {
|
||||
if err := png.Encode(&buffer, img); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/models"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tkw1536/pkglib/fsx/umaskfree"
|
||||
)
|
||||
|
||||
// Backupable represents a component with a Backup method
|
||||
|
|
@ -122,7 +122,7 @@ func (sc *stagingContext) AddDirectory(path string, op func(context.Context) err
|
|||
}
|
||||
|
||||
// run the make directory
|
||||
if err := fsx.Mkdir(dst, fsx.DefaultDirPerm); err != nil {
|
||||
if err := umaskfree.Mkdir(dst, umaskfree.DefaultDirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -143,7 +143,7 @@ func (sc *stagingContext) CopyFile(dst, src string) error {
|
|||
return err
|
||||
}
|
||||
sc.sendPath(dst)
|
||||
return fsx.CopyFile(sc.ctx, dstPath, src)
|
||||
return umaskfree.CopyFile(sc.ctx, dstPath, src)
|
||||
}
|
||||
|
||||
func (sc *stagingContext) CopyDirectory(dst, src string) error {
|
||||
|
|
@ -156,7 +156,7 @@ func (sc *stagingContext) CopyDirectory(dst, src string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return fsx.CopyDirectory(sc.ctx, dstPath, src, func(dst, src string) {
|
||||
return umaskfree.CopyDirectory(sc.ctx, dstPath, src, func(dst, src string) {
|
||||
sc.sendPath(dst)
|
||||
})
|
||||
}
|
||||
|
|
@ -174,7 +174,7 @@ func (sc *stagingContext) AddFile(path string, op func(ctx context.Context, file
|
|||
}
|
||||
|
||||
// create the file
|
||||
file, err := fsx.Create(dst, fsx.DefaultFilePerm)
|
||||
file, err := umaskfree.Create(dst, umaskfree.DefaultFilePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ import (
|
|||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/wisski"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/logging"
|
||||
"github.com/tkw1536/pkglib/fsx/umaskfree"
|
||||
"github.com/tkw1536/pkglib/status"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
|
@ -118,7 +118,7 @@ func (backup *Backup) run(ctx context.Context, progress io.Writer, exporter *Exp
|
|||
defer st.Stop()
|
||||
|
||||
instancesBackupDir := filepath.Join(backup.Description.Dest, "instances")
|
||||
if err := fsx.Mkdir(instancesBackupDir, fsx.DefaultDirPerm); err != nil {
|
||||
if err := umaskfree.Mkdir(instancesBackupDir, umaskfree.DefaultDirPerm); err != nil {
|
||||
backup.InstanceListErr = err
|
||||
return nil
|
||||
}
|
||||
|
|
@ -139,7 +139,7 @@ func (backup *Backup) run(ctx context.Context, progress io.Writer, exporter *Exp
|
|||
|
||||
Handler: func(instance *wisski.WissKI, index int, writer io.Writer) Snapshot {
|
||||
dir := filepath.Join(instancesBackupDir, instance.Slug)
|
||||
if err := fsx.Mkdir(dir, fsx.DefaultDirPerm); err != nil {
|
||||
if err := umaskfree.Mkdir(dir, umaskfree.DefaultDirPerm); err != nil {
|
||||
return Snapshot{
|
||||
ErrPanic: err,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ import (
|
|||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/instances"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/sql"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/passwordx"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||
"github.com/tkw1536/pkglib/fsx"
|
||||
"github.com/tkw1536/pkglib/fsx/umaskfree"
|
||||
"github.com/tkw1536/pkglib/password"
|
||||
)
|
||||
|
||||
|
|
@ -75,7 +76,7 @@ func (*Exporter) newSnapshotName(prefix string) string {
|
|||
func (dis *Exporter) NewStagingDir(prefix string) (path string, err error) {
|
||||
for path == "" || errors.Is(err, fs.ErrExist) {
|
||||
path = filepath.Join(dis.StagingPath(), dis.newSnapshotName(prefix))
|
||||
err = fsx.Mkdir(path, fsx.DefaultFilePerm)
|
||||
err = umaskfree.Mkdir(path, umaskfree.DefaultFilePerm)
|
||||
}
|
||||
if err != nil {
|
||||
path = ""
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@ import (
|
|||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/models"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/wisski"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/logging"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/targz"
|
||||
"github.com/tkw1536/pkglib/collection"
|
||||
"github.com/tkw1536/pkglib/fsx/umaskfree"
|
||||
"github.com/tkw1536/pkglib/status"
|
||||
)
|
||||
|
||||
|
|
@ -98,7 +98,7 @@ func (exporter *Exporter) MakeExport(ctx context.Context, progress io.Writer, ta
|
|||
|
||||
// create the staging directory
|
||||
logging.LogMessage(progress, "Creating staging directory")
|
||||
err = fsx.Mkdir(stagingDir, fsx.DefaultDirPerm)
|
||||
err = umaskfree.Mkdir(stagingDir, umaskfree.DefaultDirPerm)
|
||||
if !errors.Is(err, fs.ErrExist) && err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -136,7 +136,7 @@ func (exporter *Exporter) MakeExport(ctx context.Context, progress io.Writer, ta
|
|||
reportPath := filepath.Join(stagingDir, ReportMachinePath)
|
||||
fmt.Fprintln(progress, reportPath)
|
||||
|
||||
report, err := fsx.Create(reportPath, fsx.DefaultFilePerm)
|
||||
report, err := umaskfree.Create(reportPath, umaskfree.DefaultFilePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -151,7 +151,7 @@ func (exporter *Exporter) MakeExport(ctx context.Context, progress io.Writer, ta
|
|||
reportPath := filepath.Join(stagingDir, ReportPlainPath)
|
||||
fmt.Fprintln(progress, reportPath)
|
||||
|
||||
report, err := fsx.Create(reportPath, fsx.DefaultFilePerm)
|
||||
report, err := umaskfree.Create(reportPath, umaskfree.DefaultFilePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,16 +4,15 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/tkw1536/pkglib/pools"
|
||||
"github.com/tkw1536/pkglib/sequence"
|
||||
)
|
||||
|
||||
func (snapshot Snapshot) String() string {
|
||||
builder := pools.GetBuilder()
|
||||
defer pools.ReleaseBuilder(builder)
|
||||
var builder strings.Builder
|
||||
|
||||
snapshot.ReportPlain(builder)
|
||||
snapshot.ReportPlain(&builder)
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
|
|
@ -68,10 +67,8 @@ func (snapshot Snapshot) ReportPlain(w io.Writer) error {
|
|||
|
||||
// Strings turns this backup into a string for the BackupReport.
|
||||
func (backup Backup) String() string {
|
||||
builder := pools.GetBuilder()
|
||||
defer pools.ReleaseBuilder(builder)
|
||||
|
||||
backup.ReportPlain(builder)
|
||||
var builder strings.Builder
|
||||
backup.ReportPlain(&builder)
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ import (
|
|||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/instances"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/wisski"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/logging"
|
||||
"github.com/tkw1536/pkglib/fsx"
|
||||
)
|
||||
|
||||
type Provision struct {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import (
|
|||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/templating"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/status"
|
||||
"github.com/tkw1536/pkglib/httpx"
|
||||
"github.com/tkw1536/pkglib/pools"
|
||||
)
|
||||
|
||||
//go:embed "public.html"
|
||||
|
|
@ -62,8 +61,7 @@ func (home *Home) publicHandler(ctx context.Context) http.Handler {
|
|||
}
|
||||
|
||||
// get a builder
|
||||
builder := pools.GetBuilder()
|
||||
defer pools.ReleaseBuilder(builder)
|
||||
var builder strings.Builder
|
||||
|
||||
// prepare about
|
||||
pc.aboutContext.Logo = logoHTML
|
||||
|
|
@ -72,7 +70,7 @@ func (home *Home) publicHandler(ctx context.Context) http.Handler {
|
|||
|
||||
// render the about template
|
||||
|
||||
if err := about.Execute(builder, pc.aboutContext); err != nil {
|
||||
if err := about.Execute(&builder, pc.aboutContext); err != nil {
|
||||
return pc, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import (
|
|||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/assets"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/templating"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/tkw1536/pkglib/pools"
|
||||
"github.com/yuin/goldmark"
|
||||
gmmeta "github.com/yuin/goldmark-meta"
|
||||
"github.com/yuin/goldmark/parser"
|
||||
|
|
@ -90,8 +89,7 @@ var newsFS embed.FS
|
|||
|
||||
// Items returns a list of all news items
|
||||
func Items() ([]Item, error) {
|
||||
builder := pools.GetBuilder()
|
||||
defer pools.ReleaseBuilder(builder)
|
||||
var builder strings.Builder
|
||||
|
||||
files, err := fs.Glob(newsFS, "NEWS/*.md")
|
||||
if err != nil {
|
||||
|
|
@ -101,7 +99,7 @@ func Items() ([]Item, error) {
|
|||
items := make([]Item, len(files))
|
||||
for i, file := range files {
|
||||
items[i].ID = file[len("NEWS/") : len(file)-len(".md")]
|
||||
if err := items[i].parse(file, builder); err != nil {
|
||||
if err := items[i].parse(file, &builder); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ import (
|
|||
"html/template"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/csrf"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/tkw1536/pkglib/httpx"
|
||||
"github.com/tkw1536/pkglib/pools"
|
||||
"github.com/tkw1536/pkglib/timex"
|
||||
)
|
||||
|
||||
|
|
@ -251,9 +251,7 @@ func (ctx *tContext[C]) renderSafe(name string, t *template.Template, c any) (te
|
|||
}
|
||||
|
||||
value, err, panicked := func() (value template.HTML, err error, panicked bool) {
|
||||
// get a builder
|
||||
builder := pools.GetBuilder()
|
||||
defer pools.ReleaseBuilder(builder)
|
||||
var builder strings.Builder
|
||||
|
||||
defer func() {
|
||||
if panicked {
|
||||
|
|
@ -267,7 +265,7 @@ func (ctx *tContext[C]) renderSafe(name string, t *template.Template, c any) (te
|
|||
}()
|
||||
|
||||
panicked = true
|
||||
err = t.Execute(builder, c)
|
||||
err = t.Execute(&builder, c)
|
||||
panicked = false
|
||||
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||
"github.com/tkw1536/pkglib/fsx/umaskfree"
|
||||
)
|
||||
|
||||
type SQL struct {
|
||||
|
|
@ -50,7 +50,7 @@ func (sql *SQL) Stack() component.StackWithResources {
|
|||
"HTTPS_ENABLED": sql.Config.HTTP.HTTPSEnabledEnv(),
|
||||
},
|
||||
|
||||
MakeDirsPerm: fsx.DefaultDirPerm,
|
||||
MakeDirsPerm: umaskfree.DefaultDirPerm,
|
||||
MakeDirs: []string{
|
||||
"data",
|
||||
"imports",
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ import (
|
|||
"io/fs"
|
||||
"os"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||
"github.com/gliderlabs/ssh"
|
||||
"github.com/tkw1536/pkglib/fsx/umaskfree"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
gossh "golang.org/x/crypto/ssh"
|
||||
|
|
@ -120,7 +120,7 @@ func (ssh2 *SSH2) makeHostKey(progress io.Writer, ctx context.Context, key HostK
|
|||
}
|
||||
|
||||
// generate and write private key as PEM
|
||||
privateKeyFile, err := fsx.Create(path, fsx.DefaultFilePerm)
|
||||
privateKeyFile, err := umaskfree.Create(path, umaskfree.DefaultFilePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ import (
|
|||
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/compose"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/execx"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/unpack"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tkw1536/pkglib/fsx/umaskfree"
|
||||
"github.com/tkw1536/pkglib/stream"
|
||||
)
|
||||
|
||||
|
|
@ -193,7 +193,7 @@ func (is StackWithResources) Install(ctx context.Context, progress io.Writer, co
|
|||
return err
|
||||
}
|
||||
} else {
|
||||
if err := fsx.MkdirAll(is.Dir, fsx.DefaultDirPerm); err != nil {
|
||||
if err := umaskfree.MkdirAll(is.Dir, umaskfree.DefaultDirPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -206,7 +206,7 @@ func (is StackWithResources) Install(ctx context.Context, progress io.Writer, co
|
|||
defer fmt.Fprintf(progress, "[install] %s\n", dst)
|
||||
|
||||
// create the file
|
||||
yml, err := fsx.Create(dst, fsx.DefaultFilePerm)
|
||||
yml, err := umaskfree.Create(dst, umaskfree.DefaultFilePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -253,9 +253,9 @@ func (is StackWithResources) Install(ctx context.Context, progress io.Writer, co
|
|||
|
||||
fmt.Fprintf(progress, "[make] %s\n", dst)
|
||||
if is.MakeDirsPerm == fs.FileMode(0) {
|
||||
is.MakeDirsPerm = fsx.DefaultDirPerm
|
||||
is.MakeDirsPerm = umaskfree.DefaultDirPerm
|
||||
}
|
||||
if err := fsx.MkdirAll(dst, is.MakeDirsPerm); err != nil {
|
||||
if err := umaskfree.MkdirAll(dst, is.MakeDirsPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -273,7 +273,7 @@ func (is StackWithResources) Install(ctx context.Context, progress io.Writer, co
|
|||
|
||||
// copy over file from context
|
||||
fmt.Fprintf(progress, "[copy] %s (from %s)\n", dst, src)
|
||||
if err := fsx.CopyFile(ctx, dst, src); err != nil {
|
||||
if err := umaskfree.CopyFile(ctx, dst, src); err != nil {
|
||||
return errors.Wrapf(err, "Unable to copy file %s", src)
|
||||
}
|
||||
}
|
||||
|
|
@ -284,7 +284,7 @@ func (is StackWithResources) Install(ctx context.Context, progress io.Writer, co
|
|||
dst := filepath.Join(is.Dir, name)
|
||||
|
||||
fmt.Fprintf(progress, "[touch] %s\n", dst)
|
||||
if err := fsx.Touch(dst, is.TouchFilesPerm); err != nil {
|
||||
if err := umaskfree.Touch(dst, is.TouchFilesPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import (
|
|||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/tkw1536/pkglib/pools"
|
||||
"github.com/tkw1536/pkglib/timex"
|
||||
)
|
||||
|
||||
|
|
@ -39,12 +38,10 @@ func (ts Triplestore) OpenRaw(ctx context.Context, method, url string, body any,
|
|||
// for "PUT" and "POST" we setup a body
|
||||
if method == http.MethodPut || method == http.MethodPost {
|
||||
if bodyName != "" {
|
||||
// create a new buffer for the body
|
||||
buffer := pools.GetBuffer()
|
||||
defer pools.ReleaseBuffer(buffer)
|
||||
var buffer bytes.Buffer
|
||||
|
||||
// write the file to it
|
||||
writer := multipart.NewWriter(buffer)
|
||||
writer := multipart.NewWriter(&buffer)
|
||||
{
|
||||
part, err := writer.CreateFormFile(bodyName, "filename.txt")
|
||||
if err != nil {
|
||||
|
|
@ -55,7 +52,7 @@ func (ts Triplestore) OpenRaw(ctx context.Context, method, url string, body any,
|
|||
writer.Close()
|
||||
|
||||
// use it for the request
|
||||
reader = buffer
|
||||
reader = &buffer
|
||||
contentType = writer.FormDataContentType()
|
||||
} else {
|
||||
mbytes, err := json.Marshal(body)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import (
|
|||
"github.com/FAU-CDI/wisski-distillery/pkg/unpack"
|
||||
"github.com/tkw1536/goprogram/exit"
|
||||
"github.com/tkw1536/pkglib/errorx"
|
||||
"github.com/tkw1536/pkglib/pools"
|
||||
)
|
||||
|
||||
var errTripleStoreFailedRepository = exit.Error{
|
||||
|
|
@ -39,9 +38,9 @@ func (ts *Triplestore) CreateRepository(ctx context.Context, name, domain, user,
|
|||
}
|
||||
|
||||
// prepare the create repo request
|
||||
createRepo := pools.GetBuffer()
|
||||
defer pools.ReleaseBuffer(createRepo)
|
||||
err := unpack.WriteTemplate(createRepo, map[string]string{
|
||||
var createRepo bytes.Buffer
|
||||
|
||||
err := unpack.WriteTemplate(&createRepo, map[string]string{
|
||||
"GRAPHDB_REPO": name,
|
||||
"INSTANCE_DOMAIN": domain,
|
||||
}, bytes.NewReader(createRepoTTL))
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/phpx"
|
||||
"github.com/tkw1536/pkglib/pools"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
|
|
@ -25,20 +24,19 @@ type DrupalUser struct {
|
|||
}
|
||||
|
||||
func (du DrupalUser) String() string {
|
||||
builder := pools.GetBuilder()
|
||||
defer pools.ReleaseBuilder(builder)
|
||||
var builder strings.Builder
|
||||
|
||||
builder.WriteString("DrupalUser{")
|
||||
defer builder.WriteString("}")
|
||||
|
||||
fmt.Fprintf(builder, "UID: %d, ", du.UID)
|
||||
fmt.Fprintf(builder, "Name: %q, ", du.Name)
|
||||
fmt.Fprintf(&builder, "UID: %d, ", du.UID)
|
||||
fmt.Fprintf(&builder, "Name: %q, ", du.Name)
|
||||
|
||||
if du.Mail != "" {
|
||||
fmt.Fprintf(builder, "Mail: %q, ", du.Mail)
|
||||
fmt.Fprintf(&builder, "Mail: %q, ", du.Mail)
|
||||
}
|
||||
|
||||
fmt.Fprintf(builder, "Status: %t, ", du.Status)
|
||||
fmt.Fprintf(&builder, "Status: %t, ", du.Status)
|
||||
|
||||
for _, tn := range []struct {
|
||||
Name string
|
||||
|
|
@ -52,10 +50,10 @@ func (du DrupalUser) String() string {
|
|||
if tn.Time.IsZero() {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(builder, "%s: %q, ", tn.Name, tn.Time.Format(time.Stamp))
|
||||
fmt.Fprintf(&builder, "%s: %q, ", tn.Name, tn.Time.Format(time.Stamp))
|
||||
}
|
||||
|
||||
fmt.Fprintf(builder, "Roles: %s", du.Roles)
|
||||
fmt.Fprintf(&builder, "Roles: %s", du.Roles)
|
||||
|
||||
return builder.String()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ import (
|
|||
"github.com/FAU-CDI/wisski-distillery/internal/wisski/ingredient"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/wisski/ingredient/mstore"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/wisski/ingredient/php"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||
"github.com/tkw1536/pkglib/collection"
|
||||
"github.com/tkw1536/pkglib/fsx"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
_ "embed"
|
||||
|
|
@ -35,7 +35,7 @@ var (
|
|||
// NoPrefix checks if this WissKI instance is excluded from generating prefixes.
|
||||
// TODO: Move this to the database!
|
||||
func (prefixes *Prefixes) NoPrefix() bool {
|
||||
return fsx.IsFile(filepath.Join(prefixes.FilesystemBase, "prefixes.skip"))
|
||||
return fsx.IsRegular(filepath.Join(prefixes.FilesystemBase, "prefixes.skip"))
|
||||
}
|
||||
|
||||
//go:embed prefixes.php
|
||||
|
|
@ -121,7 +121,7 @@ func hasAnyPrefix(candidate string, prefixes []string) bool {
|
|||
|
||||
func (wisski *Prefixes) filePrefixes() (prefixes []string, err error) {
|
||||
path := filepath.Join(wisski.FilesystemBase, "prefixes")
|
||||
if !fsx.IsFile(path) {
|
||||
if !fsx.IsRegular(path) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
150
pkg/fsx/copy.go
150
pkg/fsx/copy.go
|
|
@ -1,150 +0,0 @@
|
|||
package fsx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/tkw1536/pkglib/contextx"
|
||||
)
|
||||
|
||||
var ErrCopySameFile = errors.New("src and dst must be different")
|
||||
|
||||
// CopyFile copies a file from src to dst.
|
||||
// When src points to a symbolic link, will copy the symbolic link.
|
||||
//
|
||||
// When dst and src are the same file, returns [ErrCopySameFile].
|
||||
// When ctx is closed, the file is not copied.
|
||||
func CopyFile(ctx context.Context, dst, src string) error {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if SameFile(src, dst) {
|
||||
return ErrCopySameFile
|
||||
}
|
||||
|
||||
// open the source
|
||||
srcFile, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer srcFile.Close()
|
||||
|
||||
// stat it to get the mode!
|
||||
srcStat, err := srcFile.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// open or create the destination
|
||||
dstFile, err := Create(dst, srcStat.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dstFile.Close()
|
||||
|
||||
// and do the copy!
|
||||
_, err = contextx.Copy(ctx, dstFile, srcFile)
|
||||
return err
|
||||
}
|
||||
|
||||
// CopyLink copies a link from src to dst.
|
||||
// If dst already exists, it is deleted and then re-created.
|
||||
func CopyLink(ctx context.Context, dst, src string) error {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// if they're the same file that is an error
|
||||
if SameFile(dst, src) {
|
||||
return ErrCopySameFile
|
||||
}
|
||||
|
||||
// read the link target
|
||||
target, err := os.Readlink(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// delete it if it already exists
|
||||
if Exists(dst) {
|
||||
if err := os.Remove(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// make the symbolic link!
|
||||
return os.Symlink(target, dst)
|
||||
}
|
||||
|
||||
var ErrDstFile = errors.New("dst is a file")
|
||||
|
||||
// CopyDirectory copies the directory src to dst recursively.
|
||||
// Copying is aborted when ctx is closed.
|
||||
//
|
||||
// Existing files and directories are overwritten.
|
||||
// When a directory already exists, additional files are not deleted.
|
||||
//
|
||||
// onCopy, when not nil, is called for each file or directory being copied.
|
||||
func CopyDirectory(ctx context.Context, dst, src string, onCopy func(dst, src string)) error {
|
||||
// sanity checks
|
||||
if SameFile(src, dst) {
|
||||
return ErrCopySameFile
|
||||
}
|
||||
if IsFile(dst) {
|
||||
return ErrDstFile
|
||||
}
|
||||
|
||||
return filepath.WalkDir(src, func(path string, d fs.DirEntry, err error) error {
|
||||
// someone previously returned an error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// context was closed
|
||||
if err := ctx.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// determine the real target path
|
||||
var relpath string
|
||||
relpath, err = filepath.Rel(src, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dst := filepath.Join(dst, relpath)
|
||||
|
||||
// call the hook
|
||||
if onCopy != nil {
|
||||
onCopy(dst, src)
|
||||
}
|
||||
|
||||
// stat the directory, so that we can get mode, and info later!
|
||||
info, err := d.Info()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// if we have a symbolic link, copy the link!
|
||||
if info.Mode()&fs.ModeSymlink != 0 {
|
||||
return CopyLink(ctx, dst, path)
|
||||
}
|
||||
|
||||
// if we got a file, we should copy it normally
|
||||
if !d.IsDir() {
|
||||
return CopyFile(ctx, dst, path)
|
||||
}
|
||||
|
||||
// create the directory, but ignore an error if the directory already exists.
|
||||
// this is so that we can copy one tree into another tree.
|
||||
err = Mkdir(dst, info.Mode())
|
||||
if errors.Is(err, fs.ErrExist) && IsDirectory(dst) {
|
||||
err = nil
|
||||
}
|
||||
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
package fsx
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/fs"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Create is like [os.Create] with an additional mode argument.
|
||||
func Create(path string, mode fs.FileMode) (*os.File, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
return os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode)
|
||||
}
|
||||
|
||||
// WriteFile is like [os.WriteFile].
|
||||
func WriteFile(path string, data []byte, mode fs.FileMode) error {
|
||||
handle, err := Create(path, mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer handle.Close()
|
||||
|
||||
if _, err := handle.Write(data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Touch touches a file.
|
||||
// It is similar to the unix 'touch' command.
|
||||
//
|
||||
// If the file does not exist, it is created using [Create].
|
||||
// If the file does exist, its' access and modification times are updated to the current time.
|
||||
func Touch(path string, perm fs.FileMode) error {
|
||||
if perm == 0 {
|
||||
perm = DefaultFilePerm
|
||||
}
|
||||
_, err := os.Stat(path)
|
||||
switch {
|
||||
case errors.Is(err, fs.ErrNotExist):
|
||||
f, err := Create(path, perm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
return nil
|
||||
case err != nil:
|
||||
return err
|
||||
default:
|
||||
now := time.Now().Local()
|
||||
return os.Chtimes(path, now, now)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
package fsx
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"os"
|
||||
)
|
||||
|
||||
// DefaultDirPerm should be used by callers to use a consistent mode for new directories.
|
||||
const DefaultDirPerm fs.FileMode = fs.ModeDir | fs.ModePerm
|
||||
|
||||
// Mkdir is like [os.Mkdir].
|
||||
func Mkdir(path string, mode fs.FileMode) error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
return os.Mkdir(path, fs.ModeDir|mode)
|
||||
}
|
||||
|
||||
// MkdirAll is like [os.MkdirAll].
|
||||
func MkdirAll(path string, mode fs.FileMode) error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
return os.MkdirAll(path, fs.ModeDir|mode)
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
// Package fsx provides additional file system functionality.
|
||||
//
|
||||
// All functions in this package ignore the umask.
|
||||
// As such it is not safe to use otherwise equivalent functions provided by the standard go library concurrently with this package.
|
||||
// Users should take care that no other code in their application uses these functions.
|
||||
package fsx
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"sync"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// DefaultFilePerm should be used by callers to use a consistent file mode for new files.
|
||||
const DefaultFilePerm fs.FileMode = 0666
|
||||
|
||||
// mask is the global mask lock
|
||||
var m mask
|
||||
|
||||
// mask allows disabling and re-enabling the global umask.
|
||||
// it is used by allow functions of this package.
|
||||
type mask struct {
|
||||
l sync.Mutex // locked?
|
||||
umask int // previous mask
|
||||
}
|
||||
|
||||
// Lock blocks until no other function is using this umask
|
||||
// and then sets it to 0.
|
||||
func (mask *mask) Lock() {
|
||||
mask.l.Lock()
|
||||
mask.umask = syscall.Umask(0)
|
||||
}
|
||||
|
||||
func (mask *mask) Unlock() {
|
||||
mask.umask = syscall.Umask(mask.umask)
|
||||
mask.l.Unlock()
|
||||
}
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
package fsx
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// SameFile checks if path1 and path2 refer to the same file.
|
||||
// If both files exist, they are compared using [os.SameFile].
|
||||
// If both files do not exist, the paths are first compared syntactically and then via recursion on [filepath.Dir].
|
||||
func SameFile(path1, path2 string) bool {
|
||||
|
||||
// initial attempt: check if directly
|
||||
same, certain := couldBeSameFile(path1, path2)
|
||||
if certain {
|
||||
return same
|
||||
}
|
||||
|
||||
// second attempt: find the directory names and base paths
|
||||
d1, n1 := filepath.Dir(path1), filepath.Base(path1)
|
||||
d2, n2 := filepath.Dir(path2), filepath.Base(path2)
|
||||
|
||||
// if we have different file names (and they don't exist)
|
||||
// we don't need to continue
|
||||
if n1 != n2 {
|
||||
return false
|
||||
}
|
||||
|
||||
// compare the base names!
|
||||
{
|
||||
same, _ := couldBeSameFile(d1, d2)
|
||||
return same
|
||||
}
|
||||
}
|
||||
|
||||
// couldBeSameFile checks if path1 might be the same as path2.
|
||||
//
|
||||
// If both files exist, compares using [os.SameFile].
|
||||
// Otherwise compares absolute paths using string comparison.
|
||||
//
|
||||
// same indicates if they might be the same file.
|
||||
// authorative indiciates if the result is authorative.
|
||||
func couldBeSameFile(path1, path2 string) (same, authorative bool) {
|
||||
{
|
||||
// stat both files
|
||||
info1, err1 := os.Stat(path1)
|
||||
info2, err2 := os.Stat(path2)
|
||||
|
||||
// both files exist => check using env.SameFile
|
||||
// the result is always authorative
|
||||
if err1 == nil && err2 == nil {
|
||||
same = os.SameFile(info1, info2)
|
||||
authorative = true
|
||||
return
|
||||
}
|
||||
|
||||
// only 1 file errored => they could be different
|
||||
if (err1 == nil) != (err2 == nil) {
|
||||
return
|
||||
}
|
||||
|
||||
// only 1 file does not exist => they could be different
|
||||
if errors.Is(err1, fs.ErrNotExist) != errors.Is(err2, fs.ErrNotExist) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// resolve paths absolutely
|
||||
rpath1, err1 := filepath.Abs(path1)
|
||||
rpath2, err2 := filepath.Abs(path2)
|
||||
|
||||
// if either path could not be resolved absolutely
|
||||
// fallback to just using clean!
|
||||
if err1 != nil {
|
||||
rpath1 = filepath.Clean(path1)
|
||||
}
|
||||
if err2 != nil {
|
||||
rpath2 = filepath.Clean(path2)
|
||||
}
|
||||
|
||||
// compare using strings
|
||||
same = rpath1 == rpath2
|
||||
authorative = same // positive result is authorative!
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
// Package fsx provides convenient abstractions to work with the filesystem.
|
||||
package fsx
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Exists checks if the given path exists
|
||||
func Exists(path string) bool {
|
||||
_, err := os.Lstat(path)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// IsDirectory checks if the provided path exists and is a directory
|
||||
func IsDirectory(path string) bool {
|
||||
info, err := os.Stat(path)
|
||||
return err == nil && info.Mode().IsDir()
|
||||
}
|
||||
|
||||
// IsFile checks if the provided path exists and is a regular file
|
||||
func IsFile(path string) bool {
|
||||
info, err := os.Stat(path)
|
||||
return err == nil && info.Mode().IsRegular()
|
||||
}
|
||||
|
||||
// IsLink checks if the provided path exists and is a symlink
|
||||
func IsLink(path string) bool {
|
||||
info, err := os.Lstat(path)
|
||||
return err == nil && info.Mode()&fs.ModeSymlink != 0
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||
"github.com/tkw1536/pkglib/fsx/umaskfree"
|
||||
)
|
||||
|
||||
// Package packages the source directory into a 'tar.gz' file into destination.
|
||||
|
|
@ -18,7 +18,7 @@ import (
|
|||
// onCopy, when not nil, is called for each file being copied into the archive.
|
||||
func Package(dst, src string, onCopy func(rel string, src string)) (count int64, err error) {
|
||||
// create the target archive
|
||||
archive, err := fsx.Create(dst, fsx.DefaultFilePerm)
|
||||
archive, err := umaskfree.Create(dst, umaskfree.DefaultFilePerm)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tkw1536/pkglib/fsx/umaskfree"
|
||||
)
|
||||
|
||||
var errExpectedFileButGotDirectory = errors.New("expected a file, but got a directory")
|
||||
|
|
@ -84,7 +84,7 @@ func installDir(dst string, srcInfo fs.FileInfo, srcFile fs.ReadDirFile, src str
|
|||
dstStat, dstErr := os.Stat(dst)
|
||||
switch {
|
||||
case errors.Is(dstErr, fs.ErrNotExist):
|
||||
if err := fsx.MkdirAll(dst, srcInfo.Mode()); err != nil {
|
||||
if err := umaskfree.MkdirAll(dst, srcInfo.Mode()); err != nil {
|
||||
return errors.Wrapf(err, "Error creating destination directory %s", dst)
|
||||
}
|
||||
case dstErr != nil:
|
||||
|
|
@ -120,7 +120,7 @@ func installDir(dst string, srcInfo fs.FileInfo, srcFile fs.ReadDirFile, src str
|
|||
|
||||
func installFile(dst string, srcInfo fs.FileInfo, src fs.File) error {
|
||||
// create the file using the right mode!
|
||||
file, err := fsx.Create(dst, srcInfo.Mode())
|
||||
file, err := umaskfree.Create(dst, srcInfo.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import (
|
|||
"io/fs"
|
||||
"strings"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||
"github.com/tkw1536/pkglib/fsx/umaskfree"
|
||||
"golang.org/x/exp/maps"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
|
@ -222,7 +222,7 @@ func InstallTemplate(dst string, context map[string]string, src string, fsys fs.
|
|||
}
|
||||
|
||||
// open the destination file
|
||||
file, err := fsx.Create(dst, srcInfo.Mode())
|
||||
file, err := umaskfree.Create(dst, srcInfo.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue