package library import ( "errors" "io/fs" "path" "path/filepath" "strconv" "strings" "sync" "syscall" "time" "velvettear/badger/internal/config" "velvettear/badger/internal/database" "velvettear/badger/internal/log" "velvettear/badger/internal/tools" ) func Import() { timestamp := tools.LogTimestamp() importDirectory := config.ImportDirectory() log.Info("import of directory '" + importDirectory + "' started...") // find files in import directory files := findFiles(importDirectory) if len(files) == 0 { log.InfoTimed("import of directory '"+importDirectory+"' finished, no files were detected", timestamp) return } // setup waitgroup and communication channels ipcMove := make(chan wrapper) ipcStore := make(chan wrapper) wait := new(sync.WaitGroup) wait.Add(3) // parse the files and store the generated metadata asynchronously go parseFiles(files, ipcMove, wait) go moveFiles(ipcMove, ipcStore, wait) go storeMetadata(ipcStore, wait) wait.Wait() close(ipcStore) // persist the in memory database to the filesystem database.Persist() // clean up empty directories deletionErrors := tools.DeleteEmpty(importDirectory) for _, error := range deletionErrors { dirNotEmptyError, ok := error.(*fs.PathError) if !ok || !errors.Is(dirNotEmptyError, syscall.ENOTEMPTY) { log.Error("encountered an error deleting directory", error.Error()) continue } log.Warning("could not delete directy '" + dirNotEmptyError.Path + "' because it's not empty") } log.InfoTimed("import of directory '"+importDirectory+"' finished", timestamp) } func moveFiles(ipcInput chan wrapper, ipcOutput chan wrapper, wait *sync.WaitGroup) { timestamp := tools.LogTimestamp() log.Debug("starting loop to move files according to their metadata...") moved := 0 for { wrapper := <-ipcInput target := path.Join(wrapper.metadata.GenerateTargetPath(), wrapper.metadata.GenerateFileName()) if tools.Exists(target) { log.Warning("file '" + wrapper.metadata.Path + "' should be moved to already existing location '" + target + "', appending timestamp") extension := filepath.Ext("." + wrapper.metadata.Path) target = strings.Replace(target, extension, " [badger "+strconv.FormatInt(time.Now().UnixMilli(), 10)+"]"+extension, -1) } // if !wrapper.metadata.ShouldBeMoved(target) { // continue // } // TODO: uncomment for "real usage" error := tools.MoveFile(wrapper.metadata.Path, target) if error != nil { log.Error("encountered an error moving file '"+wrapper.metadata.Path+"' to '"+target+"'", error.Error()) continue } moved++ wrapper.metadata.Path = target ipcOutput <- wrapper if wrapper.last { break } } log.InfoTimed("successfully moved "+strconv.Itoa(moved)+" files according to their metadata", timestamp) wait.Done() }