131 lines
2.8 KiB
Go
131 lines
2.8 KiB
Go
package library
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
"sync/atomic"
|
|
)
|
|
|
|
import _ "github.com/ncruces/go-sqlite3/driver"
|
|
import _ "github.com/ncruces/go-sqlite3/embed"
|
|
|
|
type LibraryManager struct {
|
|
Libraries map[string]string
|
|
Mutex sync.Mutex
|
|
db *sql.DB
|
|
}
|
|
|
|
func NewLibraryManager(dbPath string) (*LibraryManager, error) {
|
|
db, err := sql.Open("sqlite3", dbPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := initializeDatabase(db); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &LibraryManager{
|
|
Libraries: make(map[string]string),
|
|
db: db,
|
|
}, nil
|
|
}
|
|
|
|
func (lm *LibraryManager) AddLibrary(name, directory string) error {
|
|
lm.Mutex.Lock()
|
|
defer lm.Mutex.Unlock()
|
|
|
|
if _, exists := lm.Libraries[name]; exists {
|
|
return fmt.Errorf("Library %s already exists", name)
|
|
}
|
|
|
|
lm.Libraries[name] = directory
|
|
|
|
_, err := lm.db.Exec("INSERT OR IGNORE INTO libraries (name, directory) VALUES (?, ?)", name, directory)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Printf("Library %s added.\n", name)
|
|
return nil
|
|
}
|
|
|
|
func (lm *LibraryManager) ScanLibrary(name string) error {
|
|
dir, exists := lm.Libraries[name]
|
|
if !exists {
|
|
return fmt.Errorf("Library %s does not exist", name)
|
|
}
|
|
|
|
var fileCount int64
|
|
|
|
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !info.Mode().IsRegular() {
|
|
return nil
|
|
}
|
|
|
|
checksum, err := calculateChecksum(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = lm.db.Exec("INSERT OR REPLACE INTO files (library_name, file_path, checksum, failed) VALUES (?, ?, ?, FALSE)", name, path, checksum)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
atomic.AddInt64(&fileCount, 1)
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Printf("Scanned %d files in library %s\n", fileCount, name)
|
|
return nil
|
|
}
|
|
|
|
func (lm *LibraryManager) CompareLibrary(name string) error {
|
|
rows, err := lm.db.Query("SELECT file_path, checksum FROM files WHERE library_name = ?", name)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var mismatches int
|
|
|
|
for rows.Next() {
|
|
var filePath, storedChecksum string
|
|
if err := rows.Scan(&filePath, &storedChecksum); err != nil {
|
|
return err
|
|
}
|
|
|
|
currentChecksum, err := calculateChecksum(filePath)
|
|
if err != nil {
|
|
// Mark the file as failed if it cannot be read
|
|
_, updateErr := lm.db.Exec("UPDATE files SET failed = TRUE WHERE library_name = ? AND file_path = ?", name, filePath)
|
|
if updateErr != nil {
|
|
return fmt.Errorf("error marking file as failed: %v", updateErr)
|
|
}
|
|
continue
|
|
}
|
|
|
|
if currentChecksum != storedChecksum {
|
|
mismatches++
|
|
_, err := lm.db.Exec("UPDATE files SET failed = TRUE WHERE library_name = ? AND file_path = ?", name, filePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
fmt.Printf("Comparison completed. %d mismatches found in library %s\n", mismatches, name)
|
|
return nil
|
|
}
|