Add golangci-lint config
This commit is contained in:
44
.golangci.yml
Normal file
44
.golangci.yml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
version: "2"
|
||||||
|
run:
|
||||||
|
tests: false
|
||||||
|
linters:
|
||||||
|
default: all
|
||||||
|
disable:
|
||||||
|
- revive
|
||||||
|
- noinlineerr
|
||||||
|
- mnd
|
||||||
|
- tagliatelle
|
||||||
|
- ireturn
|
||||||
|
- godox
|
||||||
|
- exhaustruct
|
||||||
|
- depguard
|
||||||
|
settings:
|
||||||
|
wsl_v5:
|
||||||
|
allow-first-in-block: true
|
||||||
|
allow-whole-block: false
|
||||||
|
branch-max-lines: 2
|
||||||
|
lll:
|
||||||
|
line-length: 120
|
||||||
|
staticcheck:
|
||||||
|
checks:
|
||||||
|
- -SA1029
|
||||||
|
varnamelen:
|
||||||
|
ignore-decls:
|
||||||
|
- tx *sqlx.Tx
|
||||||
|
wrapcheck:
|
||||||
|
ignore-sig-regexps:
|
||||||
|
- \.Write\(
|
||||||
|
- \.WriteString\(
|
||||||
|
- \.WriteJSON\(
|
||||||
|
- \.WriteHTML\(
|
||||||
|
- \.Redirect\(
|
||||||
|
- \.Error\(
|
||||||
|
- \.ErrorV0\(
|
||||||
|
issues:
|
||||||
|
max-issues-per-linter: 0
|
||||||
|
max-same-issues: 0
|
||||||
|
formatters:
|
||||||
|
enable:
|
||||||
|
- gofmt
|
||||||
|
- gofumpt
|
||||||
|
- goimports
|
||||||
@@ -46,7 +46,9 @@ func main() {
|
|||||||
// CTRL+C handler.
|
// CTRL+C handler.
|
||||||
interrupt := make(chan os.Signal, 1)
|
interrupt := make(chan os.Signal, 1)
|
||||||
signal.Notify(interrupt)
|
signal.Notify(interrupt)
|
||||||
|
|
||||||
shutdownDone := make(chan bool, 1)
|
shutdownDone := make(chan bool, 1)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
signalThing := <-interrupt
|
signalThing := <-interrupt
|
||||||
if signalThing == syscall.SIGTERM || signalThing == syscall.SIGINT {
|
if signalThing == syscall.SIGTERM || signalThing == syscall.SIGINT {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@@ -34,6 +35,7 @@ func (a *App) Logger() *logrus.Entry {
|
|||||||
|
|
||||||
func New(ctx context.Context) *App {
|
func New(ctx context.Context) *App {
|
||||||
var m runtime.MemStats
|
var m runtime.MemStats
|
||||||
|
|
||||||
runtime.ReadMemStats(&m)
|
runtime.ReadMemStats(&m)
|
||||||
|
|
||||||
app := new(App)
|
app := new(App)
|
||||||
@@ -48,7 +50,7 @@ func New(ctx context.Context) *App {
|
|||||||
app.logger = logger.WithContext(ctx).WithFields(logrus.Fields{
|
app.logger = logger.WithContext(ctx).WithFields(logrus.Fields{
|
||||||
"memalloc": fmt.Sprintf("%dMB", m.Alloc/1024/1024),
|
"memalloc": fmt.Sprintf("%dMB", m.Alloc/1024/1024),
|
||||||
"memsys": fmt.Sprintf("%dMB", m.Sys/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
|
app.ctx = ctx
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ func New() (*Config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
config := new(Config)
|
config := new(Config)
|
||||||
|
|
||||||
err = yaml.Unmarshal(rawConfig, config)
|
err = yaml.Unmarshal(rawConfig, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%w: %w (%w)", ErrConfiguration, ErrCantParseConfigFile, err)
|
return nil, fmt.Errorf("%w: %w (%w)", ErrConfiguration, ErrCantParseConfigFile, err)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package cacher
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -31,7 +32,7 @@ func (c *Cacher) getFile(sourcePath string) (*models.CacheItem, error) {
|
|||||||
|
|
||||||
keyData := fmt.Sprintf("%s:%d", sourcePath, sourceFileInfo.ModTime().UnixNano())
|
keyData := fmt.Sprintf("%s:%d", sourcePath, sourceFileInfo.ModTime().UnixNano())
|
||||||
hash := md5.Sum([]byte(keyData))
|
hash := md5.Sum([]byte(keyData))
|
||||||
cacheKey := fmt.Sprintf("%x", hash)
|
cacheKey := hex.EncodeToString(hash[:])
|
||||||
cacheFilePath := filepath.Join(c.cacheDir, cacheKey+".m4a")
|
cacheFilePath := filepath.Join(c.cacheDir, cacheKey+".m4a")
|
||||||
|
|
||||||
c.itemsMutex.Lock()
|
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.
|
// File does not exist on disk, need to transcode.
|
||||||
// Register in the queue
|
// Register in the queue
|
||||||
c.transcoder.QueueChannel() <- struct{}{}
|
c.transcoder.QueueChannel() <- struct{}{}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
<-c.transcoder.QueueChannel()
|
<-c.transcoder.QueueChannel()
|
||||||
}()
|
}()
|
||||||
@@ -94,7 +96,7 @@ func (c *Cacher) getFile(sourcePath string) (*models.CacheItem, error) {
|
|||||||
|
|
||||||
c.updateCachedStat(sourcePath, size)
|
c.updateCachedStat(sourcePath, size)
|
||||||
// TODO: run cleanup on inotify events.
|
// TODO: run cleanup on inotify events.
|
||||||
// c.cleanup()
|
c.cleanup()
|
||||||
|
|
||||||
return item, nil
|
return item, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package cacher
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -10,7 +11,7 @@ import (
|
|||||||
"source.hodakov.me/hdkv/faketunes/internal/domains/cacher/models"
|
"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) {
|
func (c *Cacher) GetStat(sourcePath string) (int64, error) {
|
||||||
c.statMutex.RLock()
|
c.statMutex.RLock()
|
||||||
defer c.statMutex.RUnlock()
|
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())
|
keyData := fmt.Sprintf("%s:%d", sourcePath, info.ModTime().UnixNano())
|
||||||
hash := md5.Sum([]byte(keyData))
|
hash := md5.Sum([]byte(keyData))
|
||||||
key := fmt.Sprintf("%x", hash)
|
key := hex.EncodeToString(hash[:])
|
||||||
cachePath := filepath.Join(c.cacheDir, key+".m4a")
|
cachePath := filepath.Join(c.cacheDir, key+".m4a")
|
||||||
|
|
||||||
// Check if converted file exists and is valid
|
// Check if converted file exists and is valid
|
||||||
@@ -44,7 +45,7 @@ func (c *Cacher) GetStat(sourcePath string) (int64, error) {
|
|||||||
return info.Size(), nil
|
return info.Size(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateCachedStat updates the stat cache
|
// updateCachedStat updates the stat cache.
|
||||||
func (c *Cacher) updateCachedStat(sourcePath string, size int64) {
|
func (c *Cacher) updateCachedStat(sourcePath string, size int64) {
|
||||||
c.statMutex.Lock()
|
c.statMutex.Lock()
|
||||||
defer c.statMutex.Unlock()
|
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) {
|
func (c *Cacher) getCachedStat(sourcePath string) (int64, bool) {
|
||||||
c.statMutex.RLock()
|
c.statMutex.RLock()
|
||||||
defer c.statMutex.RUnlock()
|
defer c.statMutex.RUnlock()
|
||||||
@@ -63,5 +64,6 @@ func (c *Cacher) getCachedStat(sourcePath string) (int64, bool) {
|
|||||||
if stat, ok := c.stat[sourcePath]; ok {
|
if stat, ok := c.stat[sourcePath]; ok {
|
||||||
return stat.Size, true
|
return stat.Size, true
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ package domains
|
|||||||
|
|
||||||
const FilesystemName = "filesystem"
|
const FilesystemName = "filesystem"
|
||||||
|
|
||||||
type Filesystem interface{}
|
type Filesystem any
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ func (f *FS) prepareDirectories() error {
|
|||||||
|
|
||||||
// Create the structure for the virtual filesystem.
|
// Create the structure for the virtual filesystem.
|
||||||
for _, dir := range []string{f.destinationDir, f.cacheDir, f.metadataDir} {
|
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")
|
f.app.Logger().WithField("path", dir).Error("Operation on directory was unsuccessful")
|
||||||
|
|
||||||
return fmt.Errorf("%w: %w (%w)", ErrFilesystem, ErrFailedToCreateDestinationDirectory, err)
|
return fmt.Errorf("%w: %w (%w)", ErrFilesystem, ErrFailedToCreateDestinationDirectory, err)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package filesystem
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -33,7 +34,7 @@ func (fi *File) Read(ctx context.Context, dest []byte, off int64) (fuse.ReadResu
|
|||||||
}
|
}
|
||||||
|
|
||||||
n, err := fi.file.Read(dest)
|
n, err := fi.file.Read(dest)
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && !errors.Is(err, io.EOF) {
|
||||||
return nil, syscall.EIO
|
return nil, syscall.EIO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ var (
|
|||||||
func (m *MusicAppMetadataFile) Getattr(ctx context.Context, fh fs.FileHandle, out *fuse.AttrOut) syscall.Errno {
|
func (m *MusicAppMetadataFile) Getattr(ctx context.Context, fh fs.FileHandle, out *fuse.AttrOut) syscall.Errno {
|
||||||
info, err := os.Stat(m.path)
|
info, err := os.Stat(m.path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
out.Mode = fuse.S_IFREG | 0644
|
out.Mode = fuse.S_IFREG | 0o644
|
||||||
out.Nlink = 1
|
out.Nlink = 1
|
||||||
out.Ino = m.StableAttr().Ino
|
out.Ino = m.StableAttr().Ino
|
||||||
out.Size = 0
|
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 {
|
func (m *MusicAppMetadataFile) Setattr(ctx context.Context, fh fs.FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno {
|
||||||
info, err := os.Stat(m.path)
|
info, err := os.Stat(m.path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
out.Mode = fuse.S_IFREG | 0644
|
out.Mode = fuse.S_IFREG | 0o644
|
||||||
out.Nlink = 1
|
out.Nlink = 1
|
||||||
out.Ino = m.StableAttr().Ino
|
out.Ino = m.StableAttr().Ino
|
||||||
out.Size = 0
|
out.Size = 0
|
||||||
@@ -90,7 +90,7 @@ func (m *MusicAppMetadataFile) Create(ctx context.Context, name string, flags ui
|
|||||||
Ino: m.f.nextInode(),
|
Ino: m.f.nextInode(),
|
||||||
})
|
})
|
||||||
|
|
||||||
out.Mode = fuse.S_IFREG | 0644
|
out.Mode = fuse.S_IFREG | 0o644
|
||||||
out.Nlink = 1
|
out.Nlink = 1
|
||||||
out.Ino = ch.StableAttr().Ino
|
out.Ino = ch.StableAttr().Ino
|
||||||
out.Size = 0
|
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) {
|
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.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
|
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 {
|
if err != nil {
|
||||||
return nil, 0, syscall.EIO
|
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 {
|
if err := os.Remove(m.path); err != nil {
|
||||||
return syscall.ENOENT
|
return syscall.ENOENT
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (d *MusicDir) Getattr(ctx context.Context, f fs.FileHandle, out *fuse.AttrOut) syscall.Errno {
|
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.Nlink = 2 // Minimum . and ..
|
||||||
out.Ino = d.StableAttr().Ino
|
out.Ino = d.StableAttr().Ino
|
||||||
out.Size = 4096
|
out.Size = 4096
|
||||||
@@ -77,6 +77,7 @@ func (d *MusicDir) Getxattr(ctx context.Context, attr string, dest []byte) (uint
|
|||||||
if len(dest) > 0 {
|
if len(dest) > 0 {
|
||||||
return 0, 0
|
return 0, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0, 0
|
return 0, 0
|
||||||
default:
|
default:
|
||||||
return 0, syscall.ENODATA
|
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.Nlink = 1
|
||||||
out.Ino = ch.StableAttr().Ino
|
out.Ino = ch.StableAttr().Ino
|
||||||
out.Size = 0
|
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.Nlink = 1
|
||||||
out.Ino = ch.StableAttr().Ino
|
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
|
// Check real file or directory
|
||||||
fullPath := filepath.Join(d.path, name)
|
fullPath := filepath.Join(d.path, name)
|
||||||
|
|
||||||
info, err := os.Stat(fullPath)
|
info, err := os.Stat(fullPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, syscall.ENOENT
|
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.Nlink = 2
|
||||||
out.Ino = ch.StableAttr().Ino
|
out.Ino = ch.StableAttr().Ino
|
||||||
out.Size = 4096
|
out.Size = 4096
|
||||||
@@ -201,9 +203,9 @@ func (d *MusicDir) Lookup(ctx context.Context, name string, out *fuse.EntryOut)
|
|||||||
)
|
)
|
||||||
|
|
||||||
if isMeta {
|
if isMeta {
|
||||||
out.Mode = fuse.S_IFREG | 0644
|
out.Mode = fuse.S_IFREG | 0o644
|
||||||
} else {
|
} else {
|
||||||
out.Mode = fuse.S_IFREG | 0444
|
out.Mode = fuse.S_IFREG | 0o444
|
||||||
}
|
}
|
||||||
|
|
||||||
out.Nlink = 1
|
out.Nlink = 1
|
||||||
@@ -224,12 +226,12 @@ func (d *MusicDir) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) {
|
|||||||
|
|
||||||
dirEntries = append(dirEntries, fuse.DirEntry{
|
dirEntries = append(dirEntries, fuse.DirEntry{
|
||||||
Name: ".",
|
Name: ".",
|
||||||
Mode: fuse.S_IFDIR | 0755,
|
Mode: fuse.S_IFDIR | 0o755,
|
||||||
Ino: d.StableAttr().Ino,
|
Ino: d.StableAttr().Ino,
|
||||||
})
|
})
|
||||||
dirEntries = append(dirEntries, fuse.DirEntry{
|
dirEntries = append(dirEntries, fuse.DirEntry{
|
||||||
Name: "..",
|
Name: "..",
|
||||||
Mode: fuse.S_IFDIR | 0755,
|
Mode: fuse.S_IFDIR | 0o755,
|
||||||
Ino: 1, // Parent (root) inode
|
Ino: 1, // Parent (root) inode
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -249,19 +251,19 @@ func (d *MusicDir) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
mode := fuse.S_IFREG | 0444
|
mode := fuse.S_IFREG | 0o444
|
||||||
if entry.IsDir() {
|
if entry.IsDir() {
|
||||||
mode = fuse.S_IFDIR | 0755
|
mode = fuse.S_IFDIR | 0o755
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert .flac to .m4a in directory listing
|
// Convert .flac to .m4a in directory listing
|
||||||
if strings.HasSuffix(strings.ToLower(name), ".flac") {
|
if strings.HasSuffix(strings.ToLower(name), ".flac") {
|
||||||
name = name[:len(name)-5] + ".m4a"
|
name = name[:len(name)-5] + ".m4a"
|
||||||
if !d.f.isiTunesMetadata(name) {
|
if !d.f.isiTunesMetadata(name) {
|
||||||
mode = fuse.S_IFREG | 0644
|
mode = fuse.S_IFREG | 0o644
|
||||||
}
|
}
|
||||||
} else if !d.f.isiTunesMetadata(name) {
|
} else if !d.f.isiTunesMetadata(name) {
|
||||||
mode = fuse.S_IFREG | 0644
|
mode = fuse.S_IFREG | 0o644
|
||||||
}
|
}
|
||||||
|
|
||||||
dirEntries = append(dirEntries, fuse.DirEntry{
|
dirEntries = append(dirEntries, fuse.DirEntry{
|
||||||
|
|||||||
@@ -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)
|
metaPath := filepath.Join(f.f.metadataDir, f.virtualName)
|
||||||
|
|
||||||
if info, err := os.Stat(metaPath); err == nil {
|
if info, err := os.Stat(metaPath); err == nil {
|
||||||
out.Mode = fuse.S_IFREG | 0644
|
out.Mode = fuse.S_IFREG | 0o644
|
||||||
out.Nlink = 1
|
out.Nlink = 1
|
||||||
out.Ino = f.StableAttr().Ino
|
out.Ino = f.StableAttr().Ino
|
||||||
out.Size = uint64(info.Size())
|
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.Ctime = out.Mtime
|
||||||
out.Blocks = (out.Size + 511) / 512
|
out.Blocks = (out.Size + 511) / 512
|
||||||
} else {
|
} else {
|
||||||
out.Mode = fuse.S_IFREG | 0644
|
out.Mode = fuse.S_IFREG | 0o644
|
||||||
out.Nlink = 1
|
out.Nlink = 1
|
||||||
out.Ino = f.StableAttr().Ino
|
out.Ino = f.StableAttr().Ino
|
||||||
out.Size = 0
|
out.Size = 0
|
||||||
@@ -53,7 +53,7 @@ func (f *MusicFile) Getattr(ctx context.Context, fh fs.FileHandle, out *fuse.Att
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
out.Mode = fuse.S_IFREG | 0444
|
out.Mode = fuse.S_IFREG | 0o444
|
||||||
out.Nlink = 1
|
out.Nlink = 1
|
||||||
out.Ino = f.StableAttr().Ino
|
out.Ino = f.StableAttr().Ino
|
||||||
out.Blocks = 1
|
out.Blocks = 1
|
||||||
@@ -76,7 +76,7 @@ func (f *MusicFile) Setattr(ctx context.Context, fh fs.FileHandle, in *fuse.SetA
|
|||||||
if f.isMetaFile {
|
if f.isMetaFile {
|
||||||
metaPath := filepath.Join(f.f.metadataDir, f.virtualName)
|
metaPath := filepath.Join(f.f.metadataDir, f.virtualName)
|
||||||
if info, err := os.Stat(metaPath); err == nil {
|
if info, err := os.Stat(metaPath); err == nil {
|
||||||
out.Mode = fuse.S_IFREG | 0644
|
out.Mode = fuse.S_IFREG | 0o644
|
||||||
out.Nlink = 1
|
out.Nlink = 1
|
||||||
out.Ino = f.StableAttr().Ino
|
out.Ino = f.StableAttr().Ino
|
||||||
out.Size = uint64(info.Size())
|
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.Ctime = out.Mtime
|
||||||
out.Blocks = (out.Size + 511) / 512
|
out.Blocks = (out.Size + 511) / 512
|
||||||
} else {
|
} else {
|
||||||
out.Mode = fuse.S_IFREG | 0644
|
out.Mode = fuse.S_IFREG | 0o644
|
||||||
out.Nlink = 1
|
out.Nlink = 1
|
||||||
out.Ino = f.StableAttr().Ino
|
out.Ino = f.StableAttr().Ino
|
||||||
out.Size = 0
|
out.Size = 0
|
||||||
@@ -105,10 +105,11 @@ func (f *MusicFile) Open(ctx context.Context, flags uint32) (fh fs.FileHandle, f
|
|||||||
if f.isMetaFile {
|
if f.isMetaFile {
|
||||||
metaPath := filepath.Join(f.f.metadataDir, f.virtualName)
|
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) {
|
if err != nil && os.IsNotExist(err) {
|
||||||
file, err = os.Create(metaPath)
|
file, err = os.Create(metaPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, syscall.EIO
|
return nil, 0, syscall.EIO
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ func (r *RootDirectory) Create(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
out.Mode = fuse.S_IFREG | 0644
|
out.Mode = fuse.S_IFREG | 0o644
|
||||||
out.Nlink = 1
|
out.Nlink = 1
|
||||||
out.Ino = ch.StableAttr().Ino
|
out.Ino = ch.StableAttr().Ino
|
||||||
out.Size = 0
|
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.Nlink = 1
|
||||||
out.Ino = ch.StableAttr().Ino
|
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.Nlink = 1
|
||||||
out.Ino = ch.StableAttr().Ino
|
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
|
// Check real file or directory
|
||||||
fullPath := filepath.Join(r.f.sourceDir, name)
|
fullPath := filepath.Join(r.f.sourceDir, name)
|
||||||
|
|
||||||
info, err := os.Stat(fullPath)
|
info, err := os.Stat(fullPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, syscall.ENOENT
|
return nil, syscall.ENOENT
|
||||||
@@ -146,7 +147,7 @@ func (r *RootDirectory) Lookup(ctx context.Context, name string, out *fuse.Entry
|
|||||||
Ino: r.f.nextInode(),
|
Ino: r.f.nextInode(),
|
||||||
})
|
})
|
||||||
|
|
||||||
out.Mode = fuse.S_IFDIR | 0755
|
out.Mode = fuse.S_IFDIR | 0o755
|
||||||
out.Nlink = 2 // Minimum . and ..
|
out.Nlink = 2 // Minimum . and ..
|
||||||
out.Ino = ch.StableAttr().Ino
|
out.Ino = ch.StableAttr().Ino
|
||||||
out.Size = 4096
|
out.Size = 4096
|
||||||
@@ -166,9 +167,9 @@ func (r *RootDirectory) Lookup(ctx context.Context, name string, out *fuse.Entry
|
|||||||
})
|
})
|
||||||
|
|
||||||
if isMeta {
|
if isMeta {
|
||||||
out.Mode = fuse.S_IFREG | 0644
|
out.Mode = fuse.S_IFREG | 0o644
|
||||||
} else {
|
} else {
|
||||||
out.Mode = fuse.S_IFREG | 0444
|
out.Mode = fuse.S_IFREG | 0o444
|
||||||
}
|
}
|
||||||
|
|
||||||
out.Nlink = 1
|
out.Nlink = 1
|
||||||
@@ -190,12 +191,12 @@ func (r *RootDirectory) Readdir(ctx context.Context) (fs.DirStream, syscall.Errn
|
|||||||
// Always include . and .. first
|
// Always include . and .. first
|
||||||
dirEntries = append(dirEntries, fuse.DirEntry{
|
dirEntries = append(dirEntries, fuse.DirEntry{
|
||||||
Name: ".",
|
Name: ".",
|
||||||
Mode: fuse.S_IFDIR | 0755,
|
Mode: fuse.S_IFDIR | 0o755,
|
||||||
Ino: 1, // Root inode
|
Ino: 1, // Root inode
|
||||||
})
|
})
|
||||||
dirEntries = append(dirEntries, fuse.DirEntry{
|
dirEntries = append(dirEntries, fuse.DirEntry{
|
||||||
Name: "..",
|
Name: "..",
|
||||||
Mode: fuse.S_IFDIR | 0755,
|
Mode: fuse.S_IFDIR | 0o755,
|
||||||
Ino: 1,
|
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(
|
r.f.app.Logger().WithError(err).WithField("path", r.f.sourceDir).Error(
|
||||||
"Error reading directory",
|
"Error reading directory",
|
||||||
)
|
)
|
||||||
|
|
||||||
return fs.NewListDirStream(dirEntries), 0
|
return fs.NewListDirStream(dirEntries), 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,9 +217,9 @@ func (r *RootDirectory) Readdir(ctx context.Context) (fs.DirStream, syscall.Errn
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
mode := fuse.S_IFREG | 0444
|
mode := fuse.S_IFREG | 0o444
|
||||||
if entry.IsDir() {
|
if entry.IsDir() {
|
||||||
mode = fuse.S_IFDIR | 0755
|
mode = fuse.S_IFDIR | 0o755
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert .flac to .m4a in directory listing
|
// 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"
|
name = name[:len(name)-5] + ".m4a"
|
||||||
}
|
}
|
||||||
|
|
||||||
mode = fuse.S_IFREG | 0644
|
mode = fuse.S_IFREG | 0o644
|
||||||
|
|
||||||
dirEntries = append(dirEntries, fuse.DirEntry{
|
dirEntries = append(dirEntries, fuse.DirEntry{
|
||||||
Name: name,
|
Name: name,
|
||||||
@@ -246,7 +248,7 @@ func (r *RootDirectory) Getattr(
|
|||||||
ctx context.Context, f fs.FileHandle, out *fuse.AttrOut,
|
ctx context.Context, f fs.FileHandle, out *fuse.AttrOut,
|
||||||
) syscall.Errno {
|
) syscall.Errno {
|
||||||
// Set basic directory attributes
|
// Set basic directory attributes
|
||||||
out.Mode = fuse.S_IFDIR | 0755
|
out.Mode = fuse.S_IFDIR | 0o755
|
||||||
|
|
||||||
// Set nlink to at least 2 (for . and ..)
|
// Set nlink to at least 2 (for . and ..)
|
||||||
out.Nlink = 2
|
out.Nlink = 2
|
||||||
|
|||||||
@@ -52,11 +52,11 @@ func (t *Transcoder) Convert(sourcePath, destinationPath string) (int64, error)
|
|||||||
|
|
||||||
analyzeOutput, err := sourceAnalyzeCmd.Output()
|
analyzeOutput, err := sourceAnalyzeCmd.Output()
|
||||||
if err == nil {
|
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
|
// We need that to make sure we don't oversample files that are lower
|
||||||
// than the default sample rate and bit depth.
|
// than the default sample rate and bit depth.
|
||||||
lines := strings.Split(strings.TrimSpace(string(analyzeOutput)), "\n")
|
lines := strings.SplitSeq(strings.TrimSpace(string(analyzeOutput)), "\n")
|
||||||
for _, line := range lines {
|
for line := range lines {
|
||||||
if strings.Contains(line, "audio") {
|
if strings.Contains(line, "audio") {
|
||||||
parts := strings.Split(line, ",")
|
parts := strings.Split(line, ",")
|
||||||
if len(parts) >= 6 {
|
if len(parts) >= 6 {
|
||||||
@@ -137,7 +137,7 @@ func (t *Transcoder) Convert(sourcePath, destinationPath string) (int64, error)
|
|||||||
"-af", "aresample=48000:resampler=soxr:precision=28",
|
"-af", "aresample=48000:resampler=soxr:precision=28",
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
ffmpegArgs = append(ffmpegArgs, "-ar", fmt.Sprintf("%d", sampleRate))
|
ffmpegArgs = append(ffmpegArgs, "-ar", strconv.Itoa(sampleRate))
|
||||||
}
|
}
|
||||||
|
|
||||||
if needsBitReduce {
|
if needsBitReduce {
|
||||||
@@ -151,7 +151,7 @@ func (t *Transcoder) Convert(sourcePath, destinationPath string) (int64, error)
|
|||||||
// Handle metadata copying and sort_artist filling
|
// Handle metadata copying and sort_artist filling
|
||||||
ffmpegArgs = append(ffmpegArgs,
|
ffmpegArgs = append(ffmpegArgs,
|
||||||
"-map_metadata", "0",
|
"-map_metadata", "0",
|
||||||
"-metadata", fmt.Sprintf("sort_artist=%s", t.escapeMetadata(sortArtist)),
|
"-metadata", "sort_artist="+t.escapeMetadata(sortArtist),
|
||||||
"-write_id3v2", "1",
|
"-write_id3v2", "1",
|
||||||
"-id3v2_version", "3",
|
"-id3v2_version", "3",
|
||||||
destinationPath,
|
destinationPath,
|
||||||
@@ -165,7 +165,9 @@ func (t *Transcoder) Convert(sourcePath, destinationPath string) (int64, error)
|
|||||||
).Debug("FFMpeg parameters")
|
).Debug("FFMpeg parameters")
|
||||||
|
|
||||||
ffmpeg := exec.Command("ffmpeg", ffmpegArgs...)
|
ffmpeg := exec.Command("ffmpeg", ffmpegArgs...)
|
||||||
|
|
||||||
var stderr bytes.Buffer
|
var stderr bytes.Buffer
|
||||||
|
|
||||||
ffmpeg.Stderr = &stderr
|
ffmpeg.Stderr = &stderr
|
||||||
|
|
||||||
if err := ffmpeg.Run(); err != nil {
|
if err := ffmpeg.Run(); err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user