Remove unused legacy manifest APIs
Removed: - New(), NewFromPaths(), NewFromFS() - unused constructors - Scan(), addFile(), addInputPath(), addInputFS() - unused scanning code - WriteToFile(), Write() - unused output methods (Builder.Build() is used) - GetFileCount(), GetTotalFileSize() - unused accessors - pathIsHidden() - duplicated in internal/scanner - ManifestScanOptions - unused options struct - HasError(), AddError(), WithContext() - unused error/context handling - NewFromProto() - deprecated alias - manifestFile struct - unused internal type Kept: - manifest struct (simplified to just pbInner, pbOuter, output) - NewManifestFromReader(), NewManifestFromFile() - for loading manifests - Files() - returns files from loaded manifest - Builder and its methods - for creating manifests
This commit is contained in:
parent
09e8da0855
commit
1588e1bb9f
@ -61,7 +61,7 @@ func validateMagic(dat []byte) bool {
|
||||
|
||||
// NewManifestFromReader reads a manifest from an io.Reader.
|
||||
func NewManifestFromReader(input io.Reader) (*manifest, error) {
|
||||
m := New()
|
||||
m := &manifest{}
|
||||
dat, err := io.ReadAll(input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -102,8 +102,3 @@ func NewManifestFromFile(fs afero.Fs, path string) (*manifest, error) {
|
||||
defer func() { _ = f.Close() }()
|
||||
return NewManifestFromReader(f)
|
||||
}
|
||||
|
||||
// NewFromProto is deprecated, use NewManifestFromReader instead.
|
||||
func NewFromProto(input io.Reader) (*manifest, error) {
|
||||
return NewManifestFromReader(input)
|
||||
}
|
||||
|
||||
196
mfer/manifest.go
196
mfer/manifest.go
@ -2,139 +2,24 @@ package mfer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/afero"
|
||||
"sneak.berlin/go/mfer/internal/log"
|
||||
)
|
||||
|
||||
type manifestFile struct {
|
||||
path string
|
||||
info fs.FileInfo
|
||||
}
|
||||
|
||||
func (m *manifestFile) String() string {
|
||||
return fmt.Sprintf("<File \"%s\">", m.path)
|
||||
}
|
||||
|
||||
// manifest holds the internal representation of a manifest file.
|
||||
// Use NewManifestFromFile or NewManifestFromReader to load an existing manifest,
|
||||
// or use Builder to create a new one.
|
||||
type manifest struct {
|
||||
sourceFS []afero.Fs
|
||||
files []*manifestFile
|
||||
scanOptions *ManifestScanOptions
|
||||
totalFileSize int64
|
||||
pbInner *MFFile
|
||||
pbOuter *MFFileOuter
|
||||
output *bytes.Buffer
|
||||
ctx context.Context
|
||||
errors []*error
|
||||
}
|
||||
|
||||
func (m *manifest) String() string {
|
||||
return fmt.Sprintf("<Manifest count=%d totalSize=%d>", len(m.files), m.totalFileSize)
|
||||
}
|
||||
|
||||
// ManifestScanOptions configures behavior when scanning directories for manifest generation.
|
||||
type ManifestScanOptions struct {
|
||||
IncludeDotfiles bool // Include files and directories starting with a dot (default: exclude)
|
||||
FollowSymLinks bool // Resolve symlinks instead of skipping them
|
||||
}
|
||||
|
||||
func (m *manifest) HasError() bool {
|
||||
return len(m.errors) > 0
|
||||
}
|
||||
|
||||
func (m *manifest) AddError(e error) *manifest {
|
||||
m.errors = append(m.errors, &e)
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *manifest) WithContext(c context.Context) *manifest {
|
||||
m.ctx = c
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *manifest) addInputPath(inputPath string) error {
|
||||
abs, err := filepath.Abs(inputPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Validate path exists
|
||||
if _, err := os.Stat(abs); err != nil {
|
||||
return fmt.Errorf("path does not exist: %s", inputPath)
|
||||
}
|
||||
afs := afero.NewReadOnlyFs(afero.NewBasePathFs(afero.NewOsFs(), abs))
|
||||
return m.addInputFS(afs)
|
||||
}
|
||||
|
||||
func (m *manifest) addInputFS(f afero.Fs) error {
|
||||
if f == nil {
|
||||
return errors.New("filesystem cannot be nil")
|
||||
}
|
||||
// Validate filesystem is accessible by statting root
|
||||
if _, err := f.Stat("/"); err != nil {
|
||||
return fmt.Errorf("filesystem not accessible: %w", err)
|
||||
}
|
||||
if m.sourceFS == nil {
|
||||
m.sourceFS = make([]afero.Fs, 0)
|
||||
}
|
||||
m.sourceFS = append(m.sourceFS, f)
|
||||
return nil
|
||||
}
|
||||
|
||||
// New creates an empty manifest.
|
||||
func New() *manifest {
|
||||
m := &manifest{}
|
||||
return m
|
||||
}
|
||||
|
||||
// NewFromPaths creates a manifest configured to scan the given filesystem paths.
|
||||
func NewFromPaths(options *ManifestScanOptions, inputPaths ...string) (*manifest, error) {
|
||||
log.Dump(inputPaths)
|
||||
m := New()
|
||||
m.scanOptions = options
|
||||
for _, p := range inputPaths {
|
||||
err := m.addInputPath(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// NewFromFS creates a manifest configured to scan the given afero filesystem.
|
||||
func NewFromFS(options *ManifestScanOptions, fs afero.Fs) (*manifest, error) {
|
||||
m := New()
|
||||
m.scanOptions = options
|
||||
err := m.addInputFS(fs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m *manifest) GetFileCount() int64 {
|
||||
count := 0
|
||||
if m.pbInner != nil {
|
||||
return int64(len(m.pbInner.Files))
|
||||
count = len(m.pbInner.Files)
|
||||
}
|
||||
return int64(len(m.files))
|
||||
}
|
||||
|
||||
func (m *manifest) GetTotalFileSize() int64 {
|
||||
if m.pbInner != nil {
|
||||
var total int64
|
||||
for _, f := range m.pbInner.Files {
|
||||
total += f.Size
|
||||
}
|
||||
return total
|
||||
}
|
||||
return m.totalFileSize
|
||||
return fmt.Sprintf("<Manifest count=%d>", count)
|
||||
}
|
||||
|
||||
// Files returns all file entries from a loaded manifest.
|
||||
@ -144,72 +29,3 @@ func (m *manifest) Files() []*MFFilePath {
|
||||
}
|
||||
return m.pbInner.Files
|
||||
}
|
||||
|
||||
func pathIsHidden(p string) bool {
|
||||
tp := path.Clean(p)
|
||||
if strings.HasPrefix(tp, ".") {
|
||||
return true
|
||||
}
|
||||
for {
|
||||
d, f := path.Split(tp)
|
||||
if strings.HasPrefix(f, ".") {
|
||||
return true
|
||||
}
|
||||
if d == "" {
|
||||
return false
|
||||
}
|
||||
tp = d[0 : len(d)-1] // trim trailing slash from dir
|
||||
}
|
||||
}
|
||||
|
||||
func (m *manifest) addFile(p string, fi fs.FileInfo, sfsIndex int) error {
|
||||
if !m.scanOptions.IncludeDotfiles && pathIsHidden(p) {
|
||||
return nil
|
||||
}
|
||||
if fi == nil {
|
||||
// fi should come from Walk; if nil, stat to get info
|
||||
var err error
|
||||
fi, err = m.sourceFS[sfsIndex].Stat(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if fi.IsDir() {
|
||||
// manifests contain only files, directories are implied.
|
||||
return nil
|
||||
}
|
||||
cleanPath := p
|
||||
if cleanPath[0:1] == "/" {
|
||||
cleanPath = cleanPath[1:]
|
||||
}
|
||||
nf := &manifestFile{
|
||||
path: cleanPath,
|
||||
info: fi,
|
||||
}
|
||||
m.files = append(m.files, nf)
|
||||
m.totalFileSize = m.totalFileSize + fi.Size()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *manifest) Scan() error {
|
||||
for idx, sfs := range m.sourceFS {
|
||||
if sfs == nil {
|
||||
return errors.New("invalid source fs")
|
||||
}
|
||||
e := afero.Walk(sfs, "/", func(p string, info fs.FileInfo, err error) error {
|
||||
// Check for context cancellation
|
||||
if m.ctx != nil {
|
||||
select {
|
||||
case <-m.ctx.Done():
|
||||
return m.ctx.Err()
|
||||
default:
|
||||
}
|
||||
}
|
||||
return m.addFile(p, info, idx)
|
||||
})
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
package mfer
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPathHiddenFunc(t *testing.T) {
|
||||
assert.False(t, pathIsHidden("/a/b/c/hello.txt"))
|
||||
assert.True(t, pathIsHidden("/a/b/c/.hello.txt"))
|
||||
assert.True(t, pathIsHidden("/a/.b/c/hello.txt"))
|
||||
assert.True(t, pathIsHidden("/.a/b/c/hello.txt"))
|
||||
assert.False(t, pathIsHidden("./a/b/c/hello.txt"))
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
package mfer
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// WriteToFile writes the manifest to the given path.
|
||||
// It will overwrite any existing file. Callers should check for existing files
|
||||
// before calling if overwrite confirmation is needed.
|
||||
func (m *manifest) WriteToFile(path string) error {
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = f.Close() }()
|
||||
|
||||
return m.Write(f)
|
||||
}
|
||||
|
||||
func (m *manifest) Write(output io.Writer) error {
|
||||
if m.pbOuter == nil {
|
||||
err := m.generate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
_, err := output.Write(m.output.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user