Comparer les révisions
2 Révisions
fix/remove
...
fix/issue-
| Auteur | SHA1 | Date | |
|---|---|---|---|
| c62a4dd5e9 | |||
|
|
34438cb5b9 |
23
.drone.yml
Fichier normal
23
.drone.yml
Fichier normal
@@ -0,0 +1,23 @@
|
||||
kind: pipeline
|
||||
name: test-docker-build
|
||||
|
||||
steps:
|
||||
- name: test-docker-build
|
||||
image: plugins/docker
|
||||
network_mode: bridge
|
||||
settings:
|
||||
repo: sneak/mfer
|
||||
build_args_from_env: [ DRONE_COMMIT_SHA ]
|
||||
dry_run: true
|
||||
custom_dns: [ 116.202.204.30 ]
|
||||
tags:
|
||||
- ${DRONE_COMMIT_SHA:0:7}
|
||||
- ${DRONE_BRANCH}
|
||||
- latest
|
||||
- name: notify
|
||||
image: plugins/slack
|
||||
settings:
|
||||
webhook:
|
||||
from_secret: SLACK_WEBHOOK_URL
|
||||
when:
|
||||
event: pull_request
|
||||
5
.gitignore
externe
5
.gitignore
externe
@@ -3,8 +3,3 @@
|
||||
*.tmp
|
||||
*.dockerimage
|
||||
/vendor
|
||||
vendor.tzst
|
||||
modcache.tzst
|
||||
|
||||
# Stale files
|
||||
.drone.yml
|
||||
|
||||
@@ -224,7 +224,12 @@ func (c *Checker) checkFile(entry *MFFilePath, checkedBytes *FileSize) Result {
|
||||
// Check if file exists
|
||||
info, err := c.fs.Stat(absPath)
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) || errors.Is(err, afero.ErrFileNotFound) {
|
||||
if errors.Is(err, afero.ErrFileNotFound) || errors.Is(err, errors.New("file does not exist")) {
|
||||
return Result{Path: relPath, Status: StatusMissing, Message: "file not found"}
|
||||
}
|
||||
// Check for "file does not exist" style errors
|
||||
exists, _ := afero.Exists(c.fs, absPath)
|
||||
if !exists {
|
||||
return Result{Path: relPath, Status: StatusMissing, Message: "file not found"}
|
||||
}
|
||||
return Result{Path: relPath, Status: StatusError, Message: err.Error()}
|
||||
@@ -272,14 +277,12 @@ func (c *Checker) checkFile(entry *MFFilePath, checkedBytes *FileSize) Result {
|
||||
|
||||
// FindExtraFiles walks the filesystem and reports files not in the manifest.
|
||||
// Results are sent to the results channel. The channel is closed when done.
|
||||
// Hidden files/directories (starting with .) are skipped, as they are excluded
|
||||
// from manifests by default. The manifest file itself is also skipped.
|
||||
func (c *Checker) FindExtraFiles(ctx context.Context, results chan<- Result) error {
|
||||
if results != nil {
|
||||
defer close(results)
|
||||
}
|
||||
|
||||
return afero.Walk(c.fs, string(c.basePath), func(walkPath string, info os.FileInfo, err error) error {
|
||||
return afero.Walk(c.fs, string(c.basePath), func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -290,31 +293,16 @@ func (c *Checker) FindExtraFiles(ctx context.Context, results chan<- Result) err
|
||||
default:
|
||||
}
|
||||
|
||||
// Get relative path
|
||||
rel, err := filepath.Rel(string(c.basePath), walkPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Skip hidden files and directories (dotfiles)
|
||||
if IsHiddenPath(filepath.ToSlash(rel)) {
|
||||
if info.IsDir() {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Skip directories
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Skip manifest files
|
||||
base := filepath.Base(rel)
|
||||
if base == "index.mf" || base == ".index.mf" {
|
||||
return nil
|
||||
// Get relative path
|
||||
rel, err := filepath.Rel(string(c.basePath), path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
relPath := RelFilePath(rel)
|
||||
|
||||
// Check if path is in manifest
|
||||
|
||||
@@ -305,44 +305,6 @@ func TestFindExtraFiles(t *testing.T) {
|
||||
assert.Equal(t, "not in manifest", extras[0].Message)
|
||||
}
|
||||
|
||||
func TestFindExtraFilesSkipsManifestAndDotfiles(t *testing.T) {
|
||||
fs := afero.NewMemMapFs()
|
||||
manifestFiles := map[string][]byte{
|
||||
"file1.txt": []byte("in manifest"),
|
||||
}
|
||||
createTestManifest(t, fs, "/data/.index.mf", manifestFiles)
|
||||
createFilesOnDisk(t, fs, "/data", map[string][]byte{
|
||||
"file1.txt": []byte("in manifest"),
|
||||
})
|
||||
// Create dotfile and manifest that should be skipped
|
||||
require.NoError(t, afero.WriteFile(fs, "/data/.hidden", []byte("hidden"), 0o644))
|
||||
require.NoError(t, afero.WriteFile(fs, "/data/.config/settings", []byte("cfg"), 0o644))
|
||||
// Create a real extra file
|
||||
require.NoError(t, fs.MkdirAll("/data", 0o755))
|
||||
require.NoError(t, afero.WriteFile(fs, "/data/extra.txt", []byte("extra"), 0o644))
|
||||
|
||||
chk, err := NewChecker("/data/.index.mf", "/data", fs)
|
||||
require.NoError(t, err)
|
||||
|
||||
results := make(chan Result, 10)
|
||||
err = chk.FindExtraFiles(context.Background(), results)
|
||||
require.NoError(t, err)
|
||||
|
||||
var extras []Result
|
||||
for r := range results {
|
||||
extras = append(extras, r)
|
||||
}
|
||||
|
||||
// Should only report extra.txt, not .hidden, .config/settings, or .index.mf
|
||||
for _, e := range extras {
|
||||
t.Logf("extra: %s", e.Path)
|
||||
}
|
||||
assert.Len(t, extras, 1)
|
||||
if len(extras) > 0 {
|
||||
assert.Equal(t, RelFilePath("extra.txt"), extras[0].Path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindExtraFilesContextCancellation(t *testing.T) {
|
||||
fs := afero.NewMemMapFs()
|
||||
files := map[string][]byte{"file.txt": []byte("data")}
|
||||
@@ -419,39 +381,6 @@ func TestCheckSubdirectories(t *testing.T) {
|
||||
assert.Equal(t, 3, okCount)
|
||||
}
|
||||
|
||||
func TestCheckMissingFileDetectedWithoutFallback(t *testing.T) {
|
||||
// Regression test: errors.Is(err, errors.New("...")) never matches because
|
||||
// errors.New creates a new value each time. The fix uses os.ErrNotExist instead.
|
||||
fs := afero.NewMemMapFs()
|
||||
files := map[string][]byte{
|
||||
"exists.txt": []byte("here"),
|
||||
"missing.txt": []byte("not on disk"),
|
||||
}
|
||||
createTestManifest(t, fs, "/manifest.mf", files)
|
||||
// Only create one file on disk
|
||||
createFilesOnDisk(t, fs, "/data", map[string][]byte{
|
||||
"exists.txt": []byte("here"),
|
||||
})
|
||||
|
||||
chk, err := NewChecker("/manifest.mf", "/data", fs)
|
||||
require.NoError(t, err)
|
||||
|
||||
results := make(chan Result, 10)
|
||||
err = chk.Check(context.Background(), results, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
statusCounts := map[Status]int{}
|
||||
for r := range results {
|
||||
statusCounts[r.Status]++
|
||||
if r.Status == StatusMissing {
|
||||
assert.Equal(t, RelFilePath("missing.txt"), r.Path)
|
||||
}
|
||||
}
|
||||
assert.Equal(t, 1, statusCounts[StatusOK], "one file should be OK")
|
||||
assert.Equal(t, 1, statusCounts[StatusMissing], "one file should be MISSING")
|
||||
assert.Equal(t, 0, statusCounts[StatusError], "no files should be ERROR")
|
||||
}
|
||||
|
||||
func TestCheckEmptyManifest(t *testing.T) {
|
||||
fs := afero.NewMemMapFs()
|
||||
// Create manifest with no files
|
||||
|
||||
@@ -100,7 +100,7 @@ func gpgExtractPubKeyFingerprint(pubKey []byte) (string, error) {
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create temp dir: %w", err)
|
||||
}
|
||||
defer func() { _ = os.RemoveAll(tmpDir) }()
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
// Set restrictive permissions
|
||||
if err := os.Chmod(tmpDir, 0o700); err != nil {
|
||||
@@ -158,7 +158,7 @@ func gpgVerify(data, signature, pubKey []byte) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create temp dir: %w", err)
|
||||
}
|
||||
defer func() { _ = os.RemoveAll(tmpDir) }()
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
// Set restrictive permissions
|
||||
if err := os.Chmod(tmpDir, 0o700); err != nil {
|
||||
|
||||
@@ -34,15 +34,15 @@ func testGPGEnv(t *testing.T) (GPGKeyID, func()) {
|
||||
|
||||
// Save original GNUPGHOME and set new one
|
||||
origGPGHome := os.Getenv("GNUPGHOME")
|
||||
require.NoError(t, os.Setenv("GNUPGHOME", gpgHome))
|
||||
os.Setenv("GNUPGHOME", gpgHome)
|
||||
|
||||
cleanup := func() {
|
||||
if origGPGHome == "" {
|
||||
_ = os.Unsetenv("GNUPGHOME")
|
||||
os.Unsetenv("GNUPGHOME")
|
||||
} else {
|
||||
_ = os.Setenv("GNUPGHOME", origGPGHome)
|
||||
os.Setenv("GNUPGHOME", origGPGHome)
|
||||
}
|
||||
_ = os.RemoveAll(gpgHome)
|
||||
os.RemoveAll(gpgHome)
|
||||
}
|
||||
|
||||
// Generate a test key with no passphrase
|
||||
|
||||
@@ -385,9 +385,6 @@ func (s *Scanner) ToManifest(ctx context.Context, w io.Writer, progress chan<- S
|
||||
// The path should use forward slashes.
|
||||
func IsHiddenPath(p string) bool {
|
||||
tp := path.Clean(p)
|
||||
if tp == "." || tp == "/" {
|
||||
return false
|
||||
}
|
||||
if strings.HasPrefix(tp, ".") {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -352,8 +352,6 @@ func TestIsHiddenPath(t *testing.T) {
|
||||
{"/absolute/.hidden", true},
|
||||
{"./relative", false}, // path.Clean removes leading ./
|
||||
{"a/b/c/.d/e", true},
|
||||
{".", false}, // current directory is not hidden
|
||||
{"/", false}, // root is not hidden
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
BIN
modcache.tzst
Fichier normal
BIN
modcache.tzst
Fichier normal
Fichier binaire non affiché.
BIN
vendor.tzst
Fichier normal
BIN
vendor.tzst
Fichier normal
Fichier binaire non affiché.
Référencer dans un nouveau ticket
Bloquer un utilisateur