Exclude dotfiles by default, add --include-dotfiles flag
Changed the default behavior to exclude dotfiles (files/dirs starting with .) which is the more common use case. Added --include-dotfiles flag for when hidden files need to be included in the manifest.
This commit is contained in:
parent
6dc496fa9e
commit
0e86562c09
2
Makefile
2
Makefile
@ -19,7 +19,7 @@ default: fmt test
|
|||||||
|
|
||||||
run: ./mfer.cmd
|
run: ./mfer.cmd
|
||||||
./$<
|
./$<
|
||||||
./$< gen --ignore-dotfiles
|
./$< gen
|
||||||
|
|
||||||
ci: test
|
ci: test
|
||||||
|
|
||||||
|
|||||||
@ -101,7 +101,7 @@ Reading file contents and computing cryptographic hashes for manifest generation
|
|||||||
### scanner.go
|
### scanner.go
|
||||||
- **Types**
|
- **Types**
|
||||||
- `Options struct` - Options for scanner behavior
|
- `Options struct` - Options for scanner behavior
|
||||||
- `IgnoreDotfiles bool`
|
- `IncludeDotfiles bool` - Include dot (hidden) files (excluded by default)
|
||||||
- `FollowSymLinks bool`
|
- `FollowSymLinks bool`
|
||||||
- `EnumerateStatus struct` - Progress information for enumeration phase
|
- `EnumerateStatus struct` - Progress information for enumeration phase
|
||||||
- `FilesFound int64`
|
- `FilesFound int64`
|
||||||
@ -171,7 +171,7 @@ Reading file contents and computing cryptographic hashes for manifest generation
|
|||||||
### manifest.go
|
### manifest.go
|
||||||
- **Types**
|
- **Types**
|
||||||
- `ManifestScanOptions struct` - Options for scanning directories
|
- `ManifestScanOptions struct` - Options for scanning directories
|
||||||
- `IgnoreDotfiles bool`
|
- `IncludeDotfiles bool` - Include dot (hidden) files (excluded by default)
|
||||||
- `FollowSymLinks bool`
|
- `FollowSymLinks bool`
|
||||||
- **Functions**
|
- **Functions**
|
||||||
- `New() *manifest` - Creates a new empty manifest
|
- `New() *manifest` - Creates a new empty manifest
|
||||||
|
|||||||
@ -15,5 +15,5 @@ trap cleanup EXIT
|
|||||||
echo "Building mfer..."
|
echo "Building mfer..."
|
||||||
go build -o "$TMPDIR/mfer" ./cmd/mfer
|
go build -o "$TMPDIR/mfer" ./cmd/mfer
|
||||||
|
|
||||||
"$TMPDIR/mfer" generate --ignore-dotfiles -o "$MANIFEST" .
|
"$TMPDIR/mfer" generate -o "$MANIFEST" .
|
||||||
"$TMPDIR/mfer" check --base . "$MANIFEST"
|
"$TMPDIR/mfer" check --base . "$MANIFEST"
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
urfcli "github.com/urfave/cli/v2"
|
urfcli "github.com/urfave/cli/v2"
|
||||||
|
"sneak.berlin/go/mfer/mfer"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -186,7 +187,7 @@ func TestUnknownCommand(t *testing.T) {
|
|||||||
assert.Equal(t, 1, exitCode)
|
assert.Equal(t, 1, exitCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGenerateWithIgnoreDotfiles(t *testing.T) {
|
func TestGenerateExcludesDotfilesByDefault(t *testing.T) {
|
||||||
fs := afero.NewMemMapFs()
|
fs := afero.NewMemMapFs()
|
||||||
|
|
||||||
// Create test files including dotfiles
|
// Create test files including dotfiles
|
||||||
@ -194,14 +195,39 @@ func TestGenerateWithIgnoreDotfiles(t *testing.T) {
|
|||||||
require.NoError(t, afero.WriteFile(fs, "/testdir/file1.txt", []byte("hello"), 0644))
|
require.NoError(t, afero.WriteFile(fs, "/testdir/file1.txt", []byte("hello"), 0644))
|
||||||
require.NoError(t, afero.WriteFile(fs, "/testdir/.hidden", []byte("secret"), 0644))
|
require.NoError(t, afero.WriteFile(fs, "/testdir/.hidden", []byte("secret"), 0644))
|
||||||
|
|
||||||
// Generate manifest with --ignore-dotfiles
|
// Generate manifest without --include-dotfiles (default excludes dotfiles)
|
||||||
opts := testOpts([]string{"mfer", "-q", "generate", "--ignore-dotfiles", "-o", "/testdir/test.mf", "/testdir"}, fs)
|
opts := testOpts([]string{"mfer", "-q", "generate", "-o", "/testdir/test.mf", "/testdir"}, fs)
|
||||||
exitCode := RunWithOptions(opts)
|
exitCode := RunWithOptions(opts)
|
||||||
require.Equal(t, 0, exitCode)
|
require.Equal(t, 0, exitCode)
|
||||||
|
|
||||||
// Check that manifest exists and we can verify (hidden file won't cause failure even if missing)
|
// Check that manifest exists
|
||||||
exists, _ := afero.Exists(fs, "/testdir/test.mf")
|
exists, _ := afero.Exists(fs, "/testdir/test.mf")
|
||||||
assert.True(t, exists)
|
assert.True(t, exists)
|
||||||
|
|
||||||
|
// Verify manifest only has 1 file (the non-dotfile)
|
||||||
|
manifest, err := mfer.NewManifestFromFile(fs, "/testdir/test.mf")
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, manifest.Files(), 1)
|
||||||
|
assert.Equal(t, "file1.txt", manifest.Files()[0].Path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGenerateWithIncludeDotfiles(t *testing.T) {
|
||||||
|
fs := afero.NewMemMapFs()
|
||||||
|
|
||||||
|
// Create test files including dotfiles
|
||||||
|
require.NoError(t, fs.MkdirAll("/testdir", 0755))
|
||||||
|
require.NoError(t, afero.WriteFile(fs, "/testdir/file1.txt", []byte("hello"), 0644))
|
||||||
|
require.NoError(t, afero.WriteFile(fs, "/testdir/.hidden", []byte("secret"), 0644))
|
||||||
|
|
||||||
|
// Generate manifest with --include-dotfiles
|
||||||
|
opts := testOpts([]string{"mfer", "-q", "generate", "--include-dotfiles", "-o", "/testdir/test.mf", "/testdir"}, fs)
|
||||||
|
exitCode := RunWithOptions(opts)
|
||||||
|
require.Equal(t, 0, exitCode)
|
||||||
|
|
||||||
|
// Verify manifest has 2 files (including dotfile)
|
||||||
|
manifest, err := mfer.NewManifestFromFile(fs, "/testdir/test.mf")
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, manifest.Files(), 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMultipleInputPaths(t *testing.T) {
|
func TestMultipleInputPaths(t *testing.T) {
|
||||||
|
|||||||
@ -40,7 +40,7 @@ func (mfa *CLIApp) freshenManifestOperation(ctx *cli.Context) error {
|
|||||||
|
|
||||||
basePath := ctx.String("base")
|
basePath := ctx.String("base")
|
||||||
showProgress := ctx.Bool("progress")
|
showProgress := ctx.Bool("progress")
|
||||||
ignoreDotfiles := ctx.Bool("IgnoreDotfiles")
|
includeDotfiles := ctx.Bool("IncludeDotfiles")
|
||||||
followSymlinks := ctx.Bool("FollowSymLinks")
|
followSymlinks := ctx.Bool("FollowSymLinks")
|
||||||
|
|
||||||
// Find manifest file
|
// Find manifest file
|
||||||
@ -112,7 +112,7 @@ func (mfa *CLIApp) freshenManifestOperation(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle dotfiles
|
// Handle dotfiles
|
||||||
if ignoreDotfiles && pathIsHidden(relPath) {
|
if !includeDotfiles && pathIsHidden(relPath) {
|
||||||
if info.IsDir() {
|
if info.IsDir() {
|
||||||
return filepath.SkipDir
|
return filepath.SkipDir
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ func (mfa *CLIApp) generateManifestOperation(ctx *cli.Context) error {
|
|||||||
log.Debug("generateManifestOperation()")
|
log.Debug("generateManifestOperation()")
|
||||||
|
|
||||||
opts := &scanner.Options{
|
opts := &scanner.Options{
|
||||||
IgnoreDotfiles: ctx.Bool("IgnoreDotfiles"),
|
IncludeDotfiles: ctx.Bool("IncludeDotfiles"),
|
||||||
FollowSymLinks: ctx.Bool("FollowSymLinks"),
|
FollowSymLinks: ctx.Bool("FollowSymLinks"),
|
||||||
Fs: mfa.Fs,
|
Fs: mfa.Fs,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -111,9 +111,9 @@ func (mfa *CLIApp) run(args []string) {
|
|||||||
Usage: "Resolve encountered symlinks",
|
Usage: "Resolve encountered symlinks",
|
||||||
},
|
},
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "IgnoreDotfiles",
|
Name: "IncludeDotfiles",
|
||||||
Aliases: []string{"ignore-dotfiles"},
|
Aliases: []string{"include-dotfiles"},
|
||||||
Usage: "Ignore any dot (hidden) files encountered",
|
Usage: "Include dot (hidden) files (excluded by default)",
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "output",
|
Name: "output",
|
||||||
@ -186,9 +186,9 @@ func (mfa *CLIApp) run(args []string) {
|
|||||||
Usage: "Resolve encountered symlinks",
|
Usage: "Resolve encountered symlinks",
|
||||||
},
|
},
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "IgnoreDotfiles",
|
Name: "IncludeDotfiles",
|
||||||
Aliases: []string{"ignore-dotfiles"},
|
Aliases: []string{"include-dotfiles"},
|
||||||
Usage: "Ignore any dot (hidden) files encountered",
|
Usage: "Include dot (hidden) files (excluded by default)",
|
||||||
},
|
},
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "progress",
|
Name: "progress",
|
||||||
|
|||||||
@ -42,7 +42,7 @@ type ScanStatus struct {
|
|||||||
|
|
||||||
// Options configures scanner behavior.
|
// Options configures scanner behavior.
|
||||||
type Options struct {
|
type Options struct {
|
||||||
IgnoreDotfiles bool // Skip files and directories starting with a dot
|
IncludeDotfiles bool // Include files and directories starting with a dot (default: exclude)
|
||||||
FollowSymLinks bool // Resolve symlinks instead of skipping them
|
FollowSymLinks bool // Resolve symlinks instead of skipping them
|
||||||
Fs afero.Fs // Filesystem to use, defaults to OsFs if nil
|
Fs afero.Fs // Filesystem to use, defaults to OsFs if nil
|
||||||
}
|
}
|
||||||
@ -152,7 +152,7 @@ func (s *Scanner) enumerateFS(afs afero.Fs, basePath string, progress chan<- Enu
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if s.options.IgnoreDotfiles && pathIsHidden(p) {
|
if !s.options.IncludeDotfiles && pathIsHidden(p) {
|
||||||
if info.IsDir() {
|
if info.IsDir() {
|
||||||
return filepath.SkipDir
|
return filepath.SkipDir
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,7 +41,7 @@ func (m *manifest) String() string {
|
|||||||
|
|
||||||
// ManifestScanOptions configures behavior when scanning directories for manifest generation.
|
// ManifestScanOptions configures behavior when scanning directories for manifest generation.
|
||||||
type ManifestScanOptions struct {
|
type ManifestScanOptions struct {
|
||||||
IgnoreDotfiles bool // Skip files and directories starting with a dot
|
IncludeDotfiles bool // Include files and directories starting with a dot (default: exclude)
|
||||||
FollowSymLinks bool // Resolve symlinks instead of skipping them
|
FollowSymLinks bool // Resolve symlinks instead of skipping them
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +153,7 @@ func pathIsHidden(p string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *manifest) addFile(p string, fi fs.FileInfo, sfsIndex int) error {
|
func (m *manifest) addFile(p string, fi fs.FileInfo, sfsIndex int) error {
|
||||||
if m.scanOptions.IgnoreDotfiles && pathIsHidden(p) {
|
if !m.scanOptions.IncludeDotfiles && pathIsHidden(p) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if fi != nil && fi.IsDir() {
|
if fi != nil && fi.IsDir() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user