Add custom types for type safety throughout codebase
- Add FileCount, FileSize, RelFilePath, AbsFilePath, ModTime, Multihash types - Add UnixSeconds and UnixNanos types for timestamp handling - Add URL types (ManifestURL, FileURL, BaseURL) with safe path joining - Consolidate scanner package into mfer package - Update checker to use custom types in Result and CheckStatus - Add ModTime.Timestamp() method for protobuf conversion - Update all tests to use proper custom types
This commit is contained in:
@@ -113,7 +113,7 @@ func (mfa *CLIApp) freshenManifestOperation(ctx *cli.Context) error {
|
||||
}
|
||||
|
||||
// Handle dotfiles
|
||||
if !includeDotfiles && pathIsHidden(relPath) {
|
||||
if !includeDotfiles && mfer.IsHiddenPath(filepath.ToSlash(relPath)) {
|
||||
if info.IsDir() {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
@@ -274,10 +274,14 @@ func (mfa *CLIApp) freshenManifestOperation(ctx *cli.Context) error {
|
||||
hashedFiles++
|
||||
|
||||
// Add to builder with computed hash
|
||||
addFileToBuilder(builder, e.path, e.size, e.mtime, hash)
|
||||
if err := addFileToBuilder(builder, e.path, e.size, e.mtime, hash); err != nil {
|
||||
return fmt.Errorf("failed to add %s: %w", e.path, err)
|
||||
}
|
||||
} else {
|
||||
// Use existing entry
|
||||
addExistingToBuilder(builder, e.existing)
|
||||
if err := addExistingToBuilder(builder, e.existing); err != nil {
|
||||
return fmt.Errorf("failed to add %s: %w", e.path, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,38 +364,15 @@ func hashFile(r io.Reader, size int64, progress func(int64)) ([]byte, int64, err
|
||||
}
|
||||
|
||||
// addFileToBuilder adds a new file entry to the builder
|
||||
func addFileToBuilder(b *mfer.Builder, path string, size int64, mtime time.Time, hash []byte) {
|
||||
// Use the builder's internal method indirectly by creating an entry
|
||||
// Since Builder.AddFile reads from a reader, we need to use a different approach
|
||||
// We'll access the builder's files directly through a custom method
|
||||
b.AddFileWithHash(path, size, mtime, hash)
|
||||
func addFileToBuilder(b *mfer.Builder, path string, size int64, mtime time.Time, hash []byte) error {
|
||||
return b.AddFileWithHash(mfer.RelFilePath(path), mfer.FileSize(size), mfer.ModTime(mtime), hash)
|
||||
}
|
||||
|
||||
// addExistingToBuilder adds an existing manifest entry to the builder
|
||||
func addExistingToBuilder(b *mfer.Builder, entry *mfer.MFFilePath) {
|
||||
func addExistingToBuilder(b *mfer.Builder, entry *mfer.MFFilePath) error {
|
||||
mtime := time.Unix(entry.Mtime.Seconds, int64(entry.Mtime.Nanos))
|
||||
if len(entry.Hashes) > 0 {
|
||||
b.AddFileWithHash(entry.Path, entry.Size, mtime, entry.Hashes[0].MultiHash)
|
||||
if len(entry.Hashes) == 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// pathIsHidden checks if a path contains hidden components
|
||||
func pathIsHidden(p string) bool {
|
||||
// "." is not hidden, it's the current directory
|
||||
if p == "." {
|
||||
return false
|
||||
}
|
||||
// Check each path component
|
||||
for p != "" && p != "." && p != "/" {
|
||||
base := filepath.Base(p)
|
||||
if len(base) > 0 && base[0] == '.' {
|
||||
return true
|
||||
}
|
||||
parent := filepath.Dir(p)
|
||||
if parent == p {
|
||||
break
|
||||
}
|
||||
p = parent
|
||||
}
|
||||
return false
|
||||
return b.AddFileWithHash(mfer.RelFilePath(entry.Path), mfer.FileSize(entry.Size), mfer.ModTime(mtime), entry.Hashes[0].MultiHash)
|
||||
}
|
||||
|
||||
@@ -13,29 +13,29 @@ import (
|
||||
"github.com/spf13/afero"
|
||||
"github.com/urfave/cli/v2"
|
||||
"sneak.berlin/go/mfer/internal/log"
|
||||
"sneak.berlin/go/mfer/internal/scanner"
|
||||
"sneak.berlin/go/mfer/mfer"
|
||||
)
|
||||
|
||||
func (mfa *CLIApp) generateManifestOperation(ctx *cli.Context) error {
|
||||
log.Debug("generateManifestOperation()")
|
||||
|
||||
opts := &scanner.Options{
|
||||
opts := &mfer.ScannerOptions{
|
||||
IncludeDotfiles: ctx.Bool("IncludeDotfiles"),
|
||||
FollowSymLinks: ctx.Bool("FollowSymLinks"),
|
||||
Fs: mfa.Fs,
|
||||
}
|
||||
|
||||
s := scanner.NewWithOptions(opts)
|
||||
s := mfer.NewScannerWithOptions(opts)
|
||||
|
||||
// Phase 1: Enumeration - collect paths and stat files
|
||||
args := ctx.Args()
|
||||
showProgress := ctx.Bool("progress")
|
||||
|
||||
// Set up enumeration progress reporting
|
||||
var enumProgress chan scanner.EnumerateStatus
|
||||
var enumProgress chan mfer.EnumerateStatus
|
||||
var enumWg sync.WaitGroup
|
||||
if showProgress {
|
||||
enumProgress = make(chan scanner.EnumerateStatus, 1)
|
||||
enumProgress = make(chan mfer.EnumerateStatus, 1)
|
||||
enumWg.Add(1)
|
||||
go func() {
|
||||
defer enumWg.Done()
|
||||
@@ -117,10 +117,10 @@ func (mfa *CLIApp) generateManifestOperation(ctx *cli.Context) error {
|
||||
}()
|
||||
|
||||
// Phase 2: Scan - read file contents and generate manifest
|
||||
var scanProgress chan scanner.ScanStatus
|
||||
var scanProgress chan mfer.ScanStatus
|
||||
var scanWg sync.WaitGroup
|
||||
if showProgress {
|
||||
scanProgress = make(chan scanner.ScanStatus, 1)
|
||||
scanProgress = make(chan mfer.ScanStatus, 1)
|
||||
scanWg.Add(1)
|
||||
go func() {
|
||||
defer scanWg.Done()
|
||||
|
||||
Reference in New Issue
Block a user