using System; using System.Collections.Generic; using System.IO; namespace Oni { internal sealed class InstanceFileOperations { private InstanceFileManager fileManager; private string destinationDir; private readonly Dictionary fileNames = new Dictionary(StringComparer.OrdinalIgnoreCase); private Dictionary referencedFiles; private readonly Dictionary instances = new Dictionary(StringComparer.Ordinal); public void Copy(InstanceFileManager fileManager, List sourceFiles, string destinationDir) { Initialize(fileManager, sourceFiles, destinationDir); foreach (KeyValuePair pair in referencedFiles) { if (File.Exists(pair.Value)) { if (!Utils.AreFilesEqual(pair.Key, pair.Value)) Console.WriteLine("File {0} already exists at destination and it is different. File not copied.", pair.Value); } else { File.Copy(pair.Key, pair.Value); } } } public void Move(InstanceFileManager fileManager, List sourceFilePaths, string outputDirPath) { Initialize(fileManager, sourceFilePaths, outputDirPath); foreach (KeyValuePair pair in referencedFiles) { if (File.Exists(pair.Value)) { if (Utils.AreFilesEqual(pair.Key, pair.Value)) File.Delete(pair.Key); else Console.WriteLine("File {0} already exists at destination and it is different. Source file not moved.", pair.Value); } else { File.Move(pair.Key, pair.Value); } } } public void MoveOverwrite(InstanceFileManager fileManager, List sourceFilePaths, string outputDirPath) { Initialize(fileManager, sourceFilePaths, outputDirPath); foreach (KeyValuePair pair in referencedFiles) { if (File.Exists(pair.Value)) File.Delete(pair.Value); File.Move(pair.Key, pair.Value); } } public void MoveDelete(InstanceFileManager fileManager, List sourceFilePaths, string outputDirPath) { Initialize(fileManager, sourceFilePaths, outputDirPath); foreach (KeyValuePair pair in referencedFiles) { if (File.Exists(pair.Value)) File.Delete(pair.Key); else File.Move(pair.Key, pair.Value); } } public void GetDependencies(InstanceFileManager fileManager, List sourceFilePaths) { Initialize(fileManager, sourceFilePaths, null); foreach (string filePath in referencedFiles.Keys) { Console.WriteLine(filePath); } } private void Initialize(InstanceFileManager fileManager, List inputFiles, string destinationDir) { this.fileManager = fileManager; this.destinationDir = destinationDir; this.referencedFiles = new Dictionary(StringComparer.OrdinalIgnoreCase); if (destinationDir != null) { if (Directory.Exists(destinationDir)) { // // Get a list of existing files to avoid name conflicts due to instance names // that differ only in case. // foreach (string existingFilePath in Directory.GetFiles(destinationDir, "*.oni")) { string fileName = Path.GetFileNameWithoutExtension(existingFilePath); string instanceName = Importer.DecodeFileName(existingFilePath); fileNames[fileName] = fileName; instances[instanceName] = existingFilePath; } } else { Directory.CreateDirectory(destinationDir); } } var sourceFiles = new Dictionary(StringComparer.Ordinal); string lastSourceDir = null; foreach (string inputFile in inputFiles) { string sourceDir = Path.GetDirectoryName(inputFile); if (sourceDir != lastSourceDir) { lastSourceDir = sourceDir; sourceFiles.Clear(); foreach (string file in Directory.GetFiles(sourceDir, "*.oni")) sourceFiles[Importer.DecodeFileName(file)] = file; } GetReferencedFiles(inputFile, sourceFiles); } } private void GetReferencedFiles(string sourceFile, Dictionary sourceFiles) { AddReferencedFile(sourceFile); var instanceFile = fileManager.OpenFile(sourceFile); foreach (var descriptor in instanceFile.GetPlaceholders()) { string referencedSourceFile; if (!sourceFiles.TryGetValue(descriptor.FullName, out referencedSourceFile) || referencedFiles.ContainsKey(referencedSourceFile)) continue; GetReferencedFiles(referencedSourceFile, sourceFiles); } } private void AddReferencedFile(string filePath) { if (referencedFiles.ContainsKey(filePath)) return; string instanceName = Importer.DecodeFileName(filePath); string destinationFile; if (!instances.TryGetValue(instanceName, out destinationFile)) { if (destinationDir != null) destinationFile = Path.Combine(destinationDir, Importer.EncodeFileName(instanceName, fileNames) + ".oni"); } referencedFiles.Add(filePath, destinationFile); } } }