Add golangci-lint config

This commit is contained in:
2026-02-12 02:54:35 +03:00
parent f22111aa43
commit 9e59fa18e4
14 changed files with 112 additions and 50 deletions

View File

@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"runtime"
"strconv"
"sync"
"github.com/sirupsen/logrus"
@@ -34,6 +35,7 @@ func (a *App) Logger() *logrus.Entry {
func New(ctx context.Context) *App {
var m runtime.MemStats
runtime.ReadMemStats(&m)
app := new(App)
@@ -48,7 +50,7 @@ func New(ctx context.Context) *App {
app.logger = logger.WithContext(ctx).WithFields(logrus.Fields{
"memalloc": fmt.Sprintf("%dMB", m.Alloc/1024/1024),
"memsys": fmt.Sprintf("%dMB", m.Sys/1024/1024),
"numgc": fmt.Sprintf("%d", m.NumGC),
"numgc": strconv.FormatUint(uint64(m.NumGC), 10),
})
app.ctx = ctx

View File

@@ -40,6 +40,7 @@ func New() (*Config, error) {
}
config := new(Config)
err = yaml.Unmarshal(rawConfig, config)
if err != nil {
return nil, fmt.Errorf("%w: %w (%w)", ErrConfiguration, ErrCantParseConfigFile, err)

View File

@@ -2,6 +2,7 @@ package cacher
import (
"crypto/md5"
"encoding/hex"
"fmt"
"os"
"path/filepath"
@@ -31,7 +32,7 @@ func (c *Cacher) getFile(sourcePath string) (*models.CacheItem, error) {
keyData := fmt.Sprintf("%s:%d", sourcePath, sourceFileInfo.ModTime().UnixNano())
hash := md5.Sum([]byte(keyData))
cacheKey := fmt.Sprintf("%x", hash)
cacheKey := hex.EncodeToString(hash[:])
cacheFilePath := filepath.Join(c.cacheDir, cacheKey+".m4a")
c.itemsMutex.Lock()
@@ -73,6 +74,7 @@ func (c *Cacher) getFile(sourcePath string) (*models.CacheItem, error) {
// File does not exist on disk, need to transcode.
// Register in the queue
c.transcoder.QueueChannel() <- struct{}{}
defer func() {
<-c.transcoder.QueueChannel()
}()
@@ -94,7 +96,7 @@ func (c *Cacher) getFile(sourcePath string) (*models.CacheItem, error) {
c.updateCachedStat(sourcePath, size)
// TODO: run cleanup on inotify events.
// c.cleanup()
c.cleanup()
return item, nil
}

View File

@@ -2,6 +2,7 @@ package cacher
import (
"crypto/md5"
"encoding/hex"
"fmt"
"os"
"path/filepath"
@@ -10,7 +11,7 @@ import (
"source.hodakov.me/hdkv/faketunes/internal/domains/cacher/models"
)
// getStat returns file size without triggering conversion (for ls/stat)
// getStat returns file size without triggering conversion (for ls/stat).
func (c *Cacher) GetStat(sourcePath string) (int64, error) {
c.statMutex.RLock()
defer c.statMutex.RUnlock()
@@ -28,7 +29,7 @@ func (c *Cacher) GetStat(sourcePath string) (int64, error) {
keyData := fmt.Sprintf("%s:%d", sourcePath, info.ModTime().UnixNano())
hash := md5.Sum([]byte(keyData))
key := fmt.Sprintf("%x", hash)
key := hex.EncodeToString(hash[:])
cachePath := filepath.Join(c.cacheDir, key+".m4a")
// Check if converted file exists and is valid
@@ -44,7 +45,7 @@ func (c *Cacher) GetStat(sourcePath string) (int64, error) {
return info.Size(), nil
}
// updateCachedStat updates the stat cache
// updateCachedStat updates the stat cache.
func (c *Cacher) updateCachedStat(sourcePath string, size int64) {
c.statMutex.Lock()
defer c.statMutex.Unlock()
@@ -55,7 +56,7 @@ func (c *Cacher) updateCachedStat(sourcePath string, size int64) {
}
}
// getCachedStat returns cached file stats
// getCachedStat returns cached file stats.
func (c *Cacher) getCachedStat(sourcePath string) (int64, bool) {
c.statMutex.RLock()
defer c.statMutex.RUnlock()
@@ -63,5 +64,6 @@ func (c *Cacher) getCachedStat(sourcePath string) (int64, bool) {
if stat, ok := c.stat[sourcePath]; ok {
return stat.Size, true
}
return 0, false
}

View File

@@ -2,4 +2,4 @@ package domains
const FilesystemName = "filesystem"
type Filesystem interface{}
type Filesystem any

View File

@@ -35,7 +35,7 @@ func (f *FS) prepareDirectories() error {
// Create the structure for the virtual filesystem.
for _, dir := range []string{f.destinationDir, f.cacheDir, f.metadataDir} {
if err := os.MkdirAll(dir, 0755); err != nil {
if err := os.MkdirAll(dir, 0o755); err != nil {
f.app.Logger().WithField("path", dir).Error("Operation on directory was unsuccessful")
return fmt.Errorf("%w: %w (%w)", ErrFilesystem, ErrFailedToCreateDestinationDirectory, err)

View File

@@ -2,6 +2,7 @@ package filesystem
import (
"context"
"errors"
"io"
"os"
"sync"
@@ -33,7 +34,7 @@ func (fi *File) Read(ctx context.Context, dest []byte, off int64) (fuse.ReadResu
}
n, err := fi.file.Read(dest)
if err != nil && err != io.EOF {
if err != nil && !errors.Is(err, io.EOF) {
return nil, syscall.EIO
}

View File

@@ -30,7 +30,7 @@ var (
func (m *MusicAppMetadataFile) Getattr(ctx context.Context, fh fs.FileHandle, out *fuse.AttrOut) syscall.Errno {
info, err := os.Stat(m.path)
if err != nil {
out.Mode = fuse.S_IFREG | 0644
out.Mode = fuse.S_IFREG | 0o644
out.Nlink = 1
out.Ino = m.StableAttr().Ino
out.Size = 0
@@ -57,7 +57,7 @@ func (m *MusicAppMetadataFile) Getattr(ctx context.Context, fh fs.FileHandle, ou
func (m *MusicAppMetadataFile) Setattr(ctx context.Context, fh fs.FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno {
info, err := os.Stat(m.path)
if err != nil {
out.Mode = fuse.S_IFREG | 0644
out.Mode = fuse.S_IFREG | 0o644
out.Nlink = 1
out.Ino = m.StableAttr().Ino
out.Size = 0
@@ -90,7 +90,7 @@ func (m *MusicAppMetadataFile) Create(ctx context.Context, name string, flags ui
Ino: m.f.nextInode(),
})
out.Mode = fuse.S_IFREG | 0644
out.Mode = fuse.S_IFREG | 0o644
out.Nlink = 1
out.Ino = ch.StableAttr().Ino
out.Size = 0
@@ -104,12 +104,12 @@ func (m *MusicAppMetadataFile) Create(ctx context.Context, name string, flags ui
func (m *MusicAppMetadataFile) Open(ctx context.Context, flags uint32) (fh fs.FileHandle, fuseFlags uint32, errno syscall.Errno) {
if _, err := os.Stat(m.path); os.IsNotExist(err) {
if err := os.WriteFile(m.path, []byte{}, 0644); err != nil {
if err := os.WriteFile(m.path, []byte{}, 0o644); err != nil {
return nil, 0, syscall.EIO
}
}
file, err := os.OpenFile(m.path, int(flags), 0644)
file, err := os.OpenFile(m.path, int(flags), 0o644)
if err != nil {
return nil, 0, syscall.EIO
}
@@ -135,6 +135,7 @@ func (m *MusicAppMetadataFile) Unlink(ctx context.Context, name string) syscall.
if err := os.Remove(m.path); err != nil {
return syscall.ENOENT
}
return 0
}

View File

@@ -34,7 +34,7 @@ var (
)
func (d *MusicDir) Getattr(ctx context.Context, f fs.FileHandle, out *fuse.AttrOut) syscall.Errno {
out.Mode = fuse.S_IFDIR | 0755
out.Mode = fuse.S_IFDIR | 0o755
out.Nlink = 2 // Minimum . and ..
out.Ino = d.StableAttr().Ino
out.Size = 4096
@@ -77,6 +77,7 @@ func (d *MusicDir) Getxattr(ctx context.Context, attr string, dest []byte) (uint
if len(dest) > 0 {
return 0, 0
}
return 0, 0
default:
return 0, syscall.ENODATA
@@ -113,7 +114,7 @@ func (d *MusicDir) Create(ctx context.Context, name string, flags uint32, mode u
},
)
out.Mode = fuse.S_IFREG | 0644
out.Mode = fuse.S_IFREG | 0o644
out.Nlink = 1
out.Ino = ch.StableAttr().Ino
out.Size = 0
@@ -144,7 +145,7 @@ func (d *MusicDir) Lookup(ctx context.Context, name string, out *fuse.EntryOut)
},
)
out.Mode = fuse.S_IFREG | 0444
out.Mode = fuse.S_IFREG | 0o444
out.Nlink = 1
out.Ino = ch.StableAttr().Ino
@@ -165,6 +166,7 @@ func (d *MusicDir) Lookup(ctx context.Context, name string, out *fuse.EntryOut)
// Check real file or directory
fullPath := filepath.Join(d.path, name)
info, err := os.Stat(fullPath)
if err != nil {
return nil, syscall.ENOENT
@@ -179,7 +181,7 @@ func (d *MusicDir) Lookup(ctx context.Context, name string, out *fuse.EntryOut)
},
)
out.Mode = fuse.S_IFDIR | 0755
out.Mode = fuse.S_IFDIR | 0o755
out.Nlink = 2
out.Ino = ch.StableAttr().Ino
out.Size = 4096
@@ -201,9 +203,9 @@ func (d *MusicDir) Lookup(ctx context.Context, name string, out *fuse.EntryOut)
)
if isMeta {
out.Mode = fuse.S_IFREG | 0644
out.Mode = fuse.S_IFREG | 0o644
} else {
out.Mode = fuse.S_IFREG | 0444
out.Mode = fuse.S_IFREG | 0o444
}
out.Nlink = 1
@@ -224,12 +226,12 @@ func (d *MusicDir) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) {
dirEntries = append(dirEntries, fuse.DirEntry{
Name: ".",
Mode: fuse.S_IFDIR | 0755,
Mode: fuse.S_IFDIR | 0o755,
Ino: d.StableAttr().Ino,
})
dirEntries = append(dirEntries, fuse.DirEntry{
Name: "..",
Mode: fuse.S_IFDIR | 0755,
Mode: fuse.S_IFDIR | 0o755,
Ino: 1, // Parent (root) inode
})
@@ -249,19 +251,19 @@ func (d *MusicDir) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) {
continue
}
mode := fuse.S_IFREG | 0444
mode := fuse.S_IFREG | 0o444
if entry.IsDir() {
mode = fuse.S_IFDIR | 0755
mode = fuse.S_IFDIR | 0o755
}
// Convert .flac to .m4a in directory listing
if strings.HasSuffix(strings.ToLower(name), ".flac") {
name = name[:len(name)-5] + ".m4a"
if !d.f.isiTunesMetadata(name) {
mode = fuse.S_IFREG | 0644
mode = fuse.S_IFREG | 0o644
}
} else if !d.f.isiTunesMetadata(name) {
mode = fuse.S_IFREG | 0644
mode = fuse.S_IFREG | 0o644
}
dirEntries = append(dirEntries, fuse.DirEntry{

View File

@@ -31,7 +31,7 @@ func (f *MusicFile) Getattr(ctx context.Context, fh fs.FileHandle, out *fuse.Att
metaPath := filepath.Join(f.f.metadataDir, f.virtualName)
if info, err := os.Stat(metaPath); err == nil {
out.Mode = fuse.S_IFREG | 0644
out.Mode = fuse.S_IFREG | 0o644
out.Nlink = 1
out.Ino = f.StableAttr().Ino
out.Size = uint64(info.Size())
@@ -40,7 +40,7 @@ func (f *MusicFile) Getattr(ctx context.Context, fh fs.FileHandle, out *fuse.Att
out.Ctime = out.Mtime
out.Blocks = (out.Size + 511) / 512
} else {
out.Mode = fuse.S_IFREG | 0644
out.Mode = fuse.S_IFREG | 0o644
out.Nlink = 1
out.Ino = f.StableAttr().Ino
out.Size = 0
@@ -53,7 +53,7 @@ func (f *MusicFile) Getattr(ctx context.Context, fh fs.FileHandle, out *fuse.Att
return 0
}
out.Mode = fuse.S_IFREG | 0444
out.Mode = fuse.S_IFREG | 0o444
out.Nlink = 1
out.Ino = f.StableAttr().Ino
out.Blocks = 1
@@ -76,7 +76,7 @@ func (f *MusicFile) Setattr(ctx context.Context, fh fs.FileHandle, in *fuse.SetA
if f.isMetaFile {
metaPath := filepath.Join(f.f.metadataDir, f.virtualName)
if info, err := os.Stat(metaPath); err == nil {
out.Mode = fuse.S_IFREG | 0644
out.Mode = fuse.S_IFREG | 0o644
out.Nlink = 1
out.Ino = f.StableAttr().Ino
out.Size = uint64(info.Size())
@@ -85,7 +85,7 @@ func (f *MusicFile) Setattr(ctx context.Context, fh fs.FileHandle, in *fuse.SetA
out.Ctime = out.Mtime
out.Blocks = (out.Size + 511) / 512
} else {
out.Mode = fuse.S_IFREG | 0644
out.Mode = fuse.S_IFREG | 0o644
out.Nlink = 1
out.Ino = f.StableAttr().Ino
out.Size = 0
@@ -105,10 +105,11 @@ func (f *MusicFile) Open(ctx context.Context, flags uint32) (fh fs.FileHandle, f
if f.isMetaFile {
metaPath := filepath.Join(f.f.metadataDir, f.virtualName)
file, err := os.OpenFile(metaPath, int(flags), 0644)
file, err := os.OpenFile(metaPath, int(flags), 0o644)
if err != nil && os.IsNotExist(err) {
file, err = os.Create(metaPath)
}
if err != nil {
return nil, 0, syscall.EIO
}

View File

@@ -50,7 +50,7 @@ func (r *RootDirectory) Create(
},
)
out.Mode = fuse.S_IFREG | 0644
out.Mode = fuse.S_IFREG | 0o644
out.Nlink = 1
out.Ino = ch.StableAttr().Ino
out.Size = 0
@@ -77,7 +77,7 @@ func (r *RootDirectory) Lookup(ctx context.Context, name string, out *fuse.Entry
},
)
out.Mode = fuse.S_IFREG | 0644
out.Mode = fuse.S_IFREG | 0o644
out.Nlink = 1
out.Ino = ch.StableAttr().Ino
@@ -114,7 +114,7 @@ func (r *RootDirectory) Lookup(ctx context.Context, name string, out *fuse.Entry
},
)
out.Mode = fuse.S_IFREG | 0444
out.Mode = fuse.S_IFREG | 0o444
out.Nlink = 1
out.Ino = ch.StableAttr().Ino
@@ -135,6 +135,7 @@ func (r *RootDirectory) Lookup(ctx context.Context, name string, out *fuse.Entry
// Check real file or directory
fullPath := filepath.Join(r.f.sourceDir, name)
info, err := os.Stat(fullPath)
if err != nil {
return nil, syscall.ENOENT
@@ -146,7 +147,7 @@ func (r *RootDirectory) Lookup(ctx context.Context, name string, out *fuse.Entry
Ino: r.f.nextInode(),
})
out.Mode = fuse.S_IFDIR | 0755
out.Mode = fuse.S_IFDIR | 0o755
out.Nlink = 2 // Minimum . and ..
out.Ino = ch.StableAttr().Ino
out.Size = 4096
@@ -166,9 +167,9 @@ func (r *RootDirectory) Lookup(ctx context.Context, name string, out *fuse.Entry
})
if isMeta {
out.Mode = fuse.S_IFREG | 0644
out.Mode = fuse.S_IFREG | 0o644
} else {
out.Mode = fuse.S_IFREG | 0444
out.Mode = fuse.S_IFREG | 0o444
}
out.Nlink = 1
@@ -190,12 +191,12 @@ func (r *RootDirectory) Readdir(ctx context.Context) (fs.DirStream, syscall.Errn
// Always include . and .. first
dirEntries = append(dirEntries, fuse.DirEntry{
Name: ".",
Mode: fuse.S_IFDIR | 0755,
Mode: fuse.S_IFDIR | 0o755,
Ino: 1, // Root inode
})
dirEntries = append(dirEntries, fuse.DirEntry{
Name: "..",
Mode: fuse.S_IFDIR | 0755,
Mode: fuse.S_IFDIR | 0o755,
Ino: 1,
})
@@ -205,6 +206,7 @@ func (r *RootDirectory) Readdir(ctx context.Context) (fs.DirStream, syscall.Errn
r.f.app.Logger().WithError(err).WithField("path", r.f.sourceDir).Error(
"Error reading directory",
)
return fs.NewListDirStream(dirEntries), 0
}
@@ -215,9 +217,9 @@ func (r *RootDirectory) Readdir(ctx context.Context) (fs.DirStream, syscall.Errn
continue
}
mode := fuse.S_IFREG | 0444
mode := fuse.S_IFREG | 0o444
if entry.IsDir() {
mode = fuse.S_IFDIR | 0755
mode = fuse.S_IFDIR | 0o755
}
// Convert .flac to .m4a in directory listing
@@ -225,7 +227,7 @@ func (r *RootDirectory) Readdir(ctx context.Context) (fs.DirStream, syscall.Errn
name = name[:len(name)-5] + ".m4a"
}
mode = fuse.S_IFREG | 0644
mode = fuse.S_IFREG | 0o644
dirEntries = append(dirEntries, fuse.DirEntry{
Name: name,
@@ -246,7 +248,7 @@ func (r *RootDirectory) Getattr(
ctx context.Context, f fs.FileHandle, out *fuse.AttrOut,
) syscall.Errno {
// Set basic directory attributes
out.Mode = fuse.S_IFDIR | 0755
out.Mode = fuse.S_IFDIR | 0o755
// Set nlink to at least 2 (for . and ..)
out.Nlink = 2

View File

@@ -52,11 +52,11 @@ func (t *Transcoder) Convert(sourcePath, destinationPath string) (int64, error)
analyzeOutput, err := sourceAnalyzeCmd.Output()
if err == nil {
// Investiage bit depth and sample rate from ffprobe output.
// Investigate bit depth and sample rate from ffprobe output.
// We need that to make sure we don't oversample files that are lower
// than the default sample rate and bit depth.
lines := strings.Split(strings.TrimSpace(string(analyzeOutput)), "\n")
for _, line := range lines {
lines := strings.SplitSeq(strings.TrimSpace(string(analyzeOutput)), "\n")
for line := range lines {
if strings.Contains(line, "audio") {
parts := strings.Split(line, ",")
if len(parts) >= 6 {
@@ -137,7 +137,7 @@ func (t *Transcoder) Convert(sourcePath, destinationPath string) (int64, error)
"-af", "aresample=48000:resampler=soxr:precision=28",
)
} else {
ffmpegArgs = append(ffmpegArgs, "-ar", fmt.Sprintf("%d", sampleRate))
ffmpegArgs = append(ffmpegArgs, "-ar", strconv.Itoa(sampleRate))
}
if needsBitReduce {
@@ -151,7 +151,7 @@ func (t *Transcoder) Convert(sourcePath, destinationPath string) (int64, error)
// Handle metadata copying and sort_artist filling
ffmpegArgs = append(ffmpegArgs,
"-map_metadata", "0",
"-metadata", fmt.Sprintf("sort_artist=%s", t.escapeMetadata(sortArtist)),
"-metadata", "sort_artist="+t.escapeMetadata(sortArtist),
"-write_id3v2", "1",
"-id3v2_version", "3",
destinationPath,
@@ -165,7 +165,9 @@ func (t *Transcoder) Convert(sourcePath, destinationPath string) (int64, error)
).Debug("FFMpeg parameters")
ffmpeg := exec.Command("ffmpeg", ffmpegArgs...)
var stderr bytes.Buffer
ffmpeg.Stderr = &stderr
if err := ffmpeg.Run(); err != nil {