private CopyItem ParseItem(PatternPathParser parser, string destinationPath, MetaData meta)
        {
            string sourcePath = meta.Path;

            CopyItem item = new CopyItem();

            item.sourceInfo      = new FileInfo(sourcePath);
            item.sourcePath      = sourcePath;
            item.destinationPath = CalculateDestinationPath(parser, destinationPath, meta);
            item.meta            = meta.Data;
            return(item);
        }
        private void CopySourceToDestination(CopyItem item, OrganizeSummary summary)
        {
            string destinationDirectory = Path.GetDirectoryName(item.destinationPath);

            if (!Directory.Exists(destinationDirectory))
            {
                try
                {
                    Directory.CreateDirectory(destinationDirectory);
                }
                catch (Exception ex)
                {
                    if (ExceptionHandling == ExceptionHandling.Throw)
                    {
                        throw new MediaOrganizerException($"Failed to create directory: {destinationDirectory}", ex);
                    }

                    Trace.WriteLine($"[{nameof(MediaOrganizer)}] Ignored exception: {ex.Message}");
                    return;
                }
            }

            summary.sources.Add(item.sourcePath);
            summary.destinations.Add(item.destinationPath);

            bool   overwrite             = false;
            string targetDestinationPath = item.destinationPath; // Note: path may be altered later on to resolve conflicts
            bool   fileExists            = File.Exists(targetDestinationPath);

            switch (CopyMode)
            {
            case CopyMode.OverwriteExisting:
                overwrite = true;
                if (fileExists)
                {
                    summary.overwritten[item.sourcePath] = targetDestinationPath;
                    Trace.WriteLine($"[{nameof(MediaOrganizer)}] Force overwrite file: {targetDestinationPath}");
                }
                break;

            case CopyMode.KeepExisting:
                if (fileExists)
                {
                    summary.skipped[item.sourcePath] = targetDestinationPath;
                    Trace.WriteLine($"[{nameof(MediaOrganizer)}] Keep existing file: {targetDestinationPath}");
                    return;
                }
                break;

            case CopyMode.KeepUnique:
                FileInfo sourceInfo      = item.sourceInfo;
                FileInfo destinationInfo = new FileInfo(targetDestinationPath);
                if (fileExists)
                {
                    // Potentially slow, therefore previous optimizations
                    if (sourceInfo.AreFilesIdentical(destinationInfo, FileComparator))
                    {
                        summary.duplicates[item.sourcePath] = targetDestinationPath;
                        Trace.WriteLine($"[{nameof(MediaOrganizer)}] Duplicate file ignored: {item.sourcePath} (duplicate of {targetDestinationPath})");
                        return;
                    }
                }

                if (sourceInfo.FileExistsInDirectory(destinationInfo.Directory, FileComparator))
                {
                    summary.duplicates[item.sourcePath] = destinationInfo.Directory.FullName;
                    Trace.WriteLine($"[{nameof(MediaOrganizer)}] Duplicate file ignored: {item.sourcePath} (exists in {destinationInfo.Directory})");
                    return;     // Source file already exists in target directory
                }

                // Find next unused filename
                string originalDestinationPath = targetDestinationPath;
                int    index = 1;
                while (fileExists)
                {
                    targetDestinationPath = destinationInfo.SuffixFileName(index++);
                    fileExists            = File.Exists(targetDestinationPath);
                }
                if (targetDestinationPath != originalDestinationPath)
                {
                    summary.renamed[originalDestinationPath] = targetDestinationPath;
                    Trace.WriteLine($"[{nameof(MediaOrganizer)}] Renamed to prevent conflict: {targetDestinationPath} (original: {originalDestinationPath})");
                }
                break;

            default:
                throw new NotImplementedException($"CopyMode: {CopyMode}");
            }

            try
            {
                File.Copy(item.sourcePath, targetDestinationPath, overwrite);
                summary.modified.Add(targetDestinationPath);
                if (FileVerification != FileComparator.None)
                {
                    if (!item.sourceInfo.AreFilesIdentical(new FileInfo(targetDestinationPath), FileVerification))
                    {
                        throw new MediaOrganizerException("File verification failed. Source: {0}. Destination: {1}", item.sourcePath, targetDestinationPath);
                    }
                }
            }
            catch (Exception ex)
            {
                if (ExceptionHandling == ExceptionHandling.Throw)
                {
                    throw new MediaOrganizerException($"Failed to copy file. Mode: {CopyMode}. Overwrite: {overwrite}. Source: {item.sourcePath}. Destination: {targetDestinationPath}", ex);
                }

                Trace.WriteLine($"[{nameof(MediaOrganizer)}] Ignored exception: {ex.Message}");
            }
        }
        private async Task <CopyItems> ParseItemsAsync(string sourcePath, string destinationPath, ParseSummary summary)
        {
            List <string> ignore = new List <string>();

            if (IgnorePaths != null)
            {
                ignore.AddRange(IgnorePaths);
            }
            if (!sourcePath.DirectoryAreSame(destinationPath))
            {
                ignore.Add(destinationPath);
            }

            IEnumerable <MetaData> data;

            try
            {
                MetaParserConfig config = new MetaParserConfig()
                {
                    Recursive = Recursive, IgnorePaths = ignore
                };
                data = await MetaParser.ParseAsync(sourcePath, config);
            }
            catch (MetaParseException ex)
            {
                throw new MediaOrganizerException("Failed to parse meta data", ex);
            }

            PatternPathParser parser = new PatternPathParser(Locale);

            parser.Preload(data);

            CopyItems items = new CopyItems();

            items.sourcePath      = sourcePath;
            items.destinationPath = destinationPath;

            foreach (MetaData meta in data)
            {
                if (workerAborted)
                {
                    break;
                }

                string path = meta.Path;

                switch (meta.Type)
                {
                case MetaType.Directory:
                    summary.totalDirectories.Add(path);
                    continue;

                case MetaType.File:
                    summary.totalFiles.Add(path);
                    summary.ignored.Add(path);
                    continue;

                default:
                    summary.totalFiles.Add(path);
                    break;
                }

                CopyItem item = ParseItem(parser, destinationPath, meta);
                items.Add(item);
                summary.parsed.Add(path);
            }

            return(items);
        }
Example #4
0
        private CopyItem ParseItem(PatternPathParser parser, string destinationPath, MetaData meta)
        {
            string sourcePath = meta.Path;

            CopyItem item = new CopyItem();
            item.sourceInfo = new FileInfo(sourcePath);
            item.sourcePath = sourcePath;
            item.destinationPath = CalculateDestinationPath(parser, destinationPath, meta);
            item.meta = meta.Data;
            return item;
        }