/// <summary> /// Moves a file filtering its content through the filter chain. /// </summary> /// <param name="sourceFileName"> /// The file to move. /// </param> /// <param name="destFileName"> /// The file to move move to. /// </param> /// <param name="filterChain"> /// Chain of filters to apply when moving, or <see langword="null" /> is no /// filters should be applied. /// </param> /// <param name="inputEncoding"> /// The encoding used to read the soure file. /// </param> /// <param name="outputEncoding"> /// The encoding used to write the destination file. /// </param> public static void MoveFile( string sourceFileName, string destFileName, FilterChain filterChain, Encoding inputEncoding, Encoding outputEncoding) { // If the source file does not exist, throw an exception. if (!File.Exists(sourceFileName)) { throw new BuildException( String.Format("Cannot move file: Source File {0} does not exist", sourceFileName)); } // if no filters have been defined, and no input or output encoding // is set, we can just use the File.Move method if (FilterChain.IsNullOrEmpty(filterChain) && inputEncoding == null && outputEncoding == null) { File.Move(sourceFileName, destFileName); } else { CopyFile(sourceFileName, destFileName, filterChain, inputEncoding, outputEncoding); File.Delete(sourceFileName); } }
/// <summary> /// Executes the Copy task. /// </summary> /// <exception cref="BuildException">A file that has to be copied does not exist or could not be copied.</exception> protected override void ExecuteTask() { // ensure base directory is set, even if fileset was not initialized // from XML if (CopyFileSet.BaseDirectory == null) { CopyFileSet.BaseDirectory = new DirectoryInfo(Project.BaseDirectory); } // Clear previous copied files _fileCopyMap.Clear(); // if the source file is specified, check to see whether it is a file or directory before proceeding if (SourceFile != null) { // copy a single file. if (SourceFile.Exists) { FileInfo dstInfo = null; if (ToFile != null) { dstInfo = ToFile; } else { string dstFilePath = Path.Combine(ToDirectory.FullName, SourceFile.Name); dstInfo = new FileInfo(dstFilePath); } // do the outdated check bool outdated = (!dstInfo.Exists) || (SourceFile.LastWriteTime > dstInfo.LastWriteTime); if (Overwrite || outdated) { // add to a copy map of absolute verified paths FileCopyMap.Add(dstInfo.FullName, new FileDateInfo(SourceFile.FullName, SourceFile.LastWriteTime)); _fileCount++; if (dstInfo.Exists && dstInfo.Attributes != FileAttributes.Normal) { File.SetAttributes(dstInfo.FullName, FileAttributes.Normal); } } } // If SourceFile exists as a directory, proceed with moving the specified directory else if (!SourceFile.Exists && Directory.Exists(SourceFile.FullName)) { // Stage the directory names string sourceDirName = SourceFile.FullName; string destDirName; // If ToFile was specified, make sure the specified filename does not exist // as a file or a directory. if (ToFile != null) { if (ToFile.Exists) { throw new BuildException(String.Format(CultureInfo.InvariantCulture, "Cannot move directory '{0}' to an existing file '{1}'", SourceFile.FullName, ToFile.FullName), Location); } if (Directory.Exists(ToFile.FullName)) { throw new BuildException(String.Format(CultureInfo.InvariantCulture, "Cannot move directory '{0}' to an existing directory '{1}'", SourceFile.FullName, ToFile.FullName), Location); } destDirName = ToFile.FullName; } // If ToDirectory was specified, make sure the specified directory does not // exist. else if (ToDirectory != null) { if (ToDirectory.Exists) { throw new BuildException(String.Format(CultureInfo.InvariantCulture, "Cannot move directory '{0}' to an existing directory '{1}'", SourceFile.FullName, ToDirectory.FullName), Location); } destDirName = ToDirectory.FullName; } // Else, throw an exception else { throw new BuildException("Target directory name not specified", Location); } FileCopyMap.Add(destDirName, new FileDateInfo(sourceDirName, SourceFile.LastWriteTime, true)); _dirCount++; } else { throw CreateSourceFileNotFoundException(SourceFile.FullName); } } // copy file set contents. else { // get the complete path of the base directory of the fileset, ie, c:\work\nant\src DirectoryInfo srcBaseInfo = CopyFileSet.BaseDirectory; // Check to see if the file operation is a straight pass through (ie: no file or // directory modifications) before proceeding. bool completeDir = true; // completeDir criteria bool[] dirCheck = new bool[8]; dirCheck[0] = CopyFileSet.IsEverythingIncluded; dirCheck[1] = !Flatten; dirCheck[2] = IncludeEmptyDirs || !CopyFileSet.HasEmptyDirectories; dirCheck[3] = FilterChain.IsNullOrEmpty(Filters); dirCheck[4] = _inputEncoding == null; dirCheck[5] = _outputEncoding == null; dirCheck[6] = srcBaseInfo != null && srcBaseInfo.Exists; dirCheck[7] = !ToDirectory.Exists || srcBaseInfo.FullName.Equals(ToDirectory.FullName, StringComparison.InvariantCultureIgnoreCase); for (int b = 0; b < dirCheck.Length; b++) { completeDir &= dirCheck[b]; } if (completeDir) { FileCopyMap.Add(ToDirectory.FullName, new FileDateInfo(srcBaseInfo.FullName, srcBaseInfo.LastWriteTime, true)); _dirCount++; } else { // if source file not specified use fileset foreach (string pathname in CopyFileSet.FileNames) { FileInfo srcInfo = new FileInfo(pathname); if (srcInfo.Exists) { // will holds the full path to the destination file string dstFilePath; if (Flatten) { dstFilePath = Path.Combine(ToDirectory.FullName, srcInfo.Name); } else { // Gets the relative path and file info from the full // source filepath // pathname = C:\f2\f3\file1, srcBaseInfo=C:\f2, then // dstRelFilePath=f3\file1 string dstRelFilePath = ""; if (srcInfo.FullName.IndexOf(srcBaseInfo.FullName, 0) != -1) { dstRelFilePath = srcInfo.FullName.Substring( srcBaseInfo.FullName.Length); } else { dstRelFilePath = srcInfo.Name; } if (dstRelFilePath[0] == Path.DirectorySeparatorChar) { dstRelFilePath = dstRelFilePath.Substring(1); } // The full filepath to copy to. dstFilePath = Path.Combine(ToDirectory.FullName, dstRelFilePath); } // do the outdated check FileInfo dstInfo = new FileInfo(dstFilePath); bool outdated = (!dstInfo.Exists) || (srcInfo.LastWriteTime > dstInfo.LastWriteTime); if (Overwrite || outdated) { // construct FileDateInfo for current file FileDateInfo newFile = new FileDateInfo(srcInfo.FullName, srcInfo.LastWriteTime); // if multiple source files are selected to be copied // to the same destination file, then only the last // updated source should actually be copied FileDateInfo oldFile = (FileDateInfo)FileCopyMap[dstInfo.FullName]; if (oldFile != null) { // if current file was updated after scheduled file, // then replace it if (newFile.LastWriteTime > oldFile.LastWriteTime) { FileCopyMap[dstInfo.FullName] = newFile; } } else { FileCopyMap.Add(dstInfo.FullName, newFile); _fileCount++; if (dstInfo.Exists && dstInfo.Attributes != FileAttributes.Normal) { File.SetAttributes(dstInfo.FullName, FileAttributes.Normal); } } } } else { throw CreateSourceFileNotFoundException(srcInfo.FullName); } } if (IncludeEmptyDirs && !Flatten) { // create any specified directories that weren't created during the copy (ie: empty directories) foreach (string pathname in CopyFileSet.DirectoryNames) { DirectoryInfo srcInfo = new DirectoryInfo(pathname); // skip directory if not relative to base dir of fileset if (srcInfo.FullName.IndexOf(srcBaseInfo.FullName) == -1) { continue; } string dstRelPath = srcInfo.FullName.Substring(srcBaseInfo.FullName.Length); if (dstRelPath.Length > 0 && dstRelPath[0] == Path.DirectorySeparatorChar) { dstRelPath = dstRelPath.Substring(1); } // The full filepath to copy to. string destinationDirectory = Path.Combine(ToDirectory.FullName, dstRelPath); if (!Directory.Exists(destinationDirectory)) { try { Directory.CreateDirectory(destinationDirectory); } catch (Exception ex) { throw new BuildException(string.Format(CultureInfo.InvariantCulture, "Failed to create directory '{0}'.", destinationDirectory), Location, ex); } Log(Level.Verbose, "Created directory '{0}'.", destinationDirectory); } } } } } // do all the actual copy operations now DoFileOperations(); }
/// <summary> /// Copies a file filtering its content through the filter chain. /// </summary> /// <param name="sourceFileName"> /// The file to copy /// </param> /// <param name="destFileName"> /// The file to copy to /// </param> /// <param name="filterChain"> /// Chain of filters to apply when copying, or <see langword="null" /> is no /// filters should be applied. /// </param> /// <param name="inputEncoding"> /// The encoding used to read the soure file. /// </param> /// <param name="outputEncoding"> /// The encoding used to write the destination file. /// </param> public static void CopyFile( string sourceFileName, string destFileName, FilterChain filterChain, Encoding inputEncoding, Encoding outputEncoding) { // If the source file does not exist, throw an exception. if (!File.Exists(sourceFileName)) { throw new BuildException( String.Format("Cannot copy file: Source File {0} does not exist", sourceFileName)); } // determine if filters are available bool filtersAvailable = !FilterChain.IsNullOrEmpty(filterChain); // if no filters have been defined, and no input or output encoding // is set, we can just use the File.Copy method if (!filtersAvailable && inputEncoding == null && outputEncoding == null) { File.Copy(sourceFileName, destFileName, true); } else { // determine actual input encoding to use. if no explicit input // encoding is specified, we'll use the system's current ANSI // code page Encoding actualInputEncoding = (inputEncoding != null) ? inputEncoding : Encoding.Default; // get base filter built on the file's reader. // Use the value of _bufferSize as the buffer size. using (StreamReader sourceFileReader = new StreamReader(sourceFileName, actualInputEncoding, true, _bufferSize)) { Encoding actualOutputEncoding = outputEncoding; if (actualOutputEncoding == null) { // if no explicit output encoding is specified, we'll // just use the encoding of the input file as determined // by the runtime // // Note : the input encoding as specified on the filterchain // might not match the current encoding of the streamreader // // eg. when specifing an ANSI encoding, the runtime might // still detect the file is using UTF-8 encoding, because // we use BOM detection actualOutputEncoding = sourceFileReader.CurrentEncoding; } // writer for destination file using (StreamWriter destFileWriter = new StreamWriter(destFileName, false, actualOutputEncoding, _bufferSize)) { if (filtersAvailable) { Filter baseFilter = filterChain.GetBaseFilter(new PhysicalTextReader(sourceFileReader)); bool atEnd = false; int character; while (!atEnd) { character = baseFilter.Read(); if (character > -1) { destFileWriter.Write((char)character); } else { atEnd = true; } } } else { char[] buffer = new char[_bufferSize]; while (true) { int charsRead = sourceFileReader.Read(buffer, 0, buffer.Length); if (charsRead == 0) { break; } destFileWriter.Write(buffer, 0, charsRead); } } } } } }
/// <summary> /// Moves a directory while filtering its file content through the filter chain. /// </summary> /// <param name="sourceDirectory"> /// Source directory to move from. /// </param> /// <param name="destDirectory"> /// Destination directory to move to. /// </param> /// <param name="filterChain"> /// Chain of filters to apply when copying, or <see langword="null" /> is no /// filters should be applied. /// </param> /// <param name="inputEncoding"> /// The encoding used to read the soure file. /// </param> /// <param name="outputEncoding"> /// The encoding used to write the destination file. /// </param> internal static void MoveDirectory( string sourceDirectory, string destDirectory, FilterChain filterChain, Encoding inputEncoding, Encoding outputEncoding) { // If the source directory does not exist, throw an exception. if (!Directory.Exists(sourceDirectory)) { throw new BuildException( String.Format("Cannot move directory: Source Directory {0} does not exist", sourceDirectory)); } // if no filters have been defined, and no input or output encoding // is set, proceed with a straight directory move. if (FilterChain.IsNullOrEmpty(filterChain) && inputEncoding == null && outputEncoding == null) { // If the source & target paths are completely the same, including // case, throw an exception. if (sourceDirectory.Equals(destDirectory, StringComparison.InvariantCulture)) { throw new BuildException("Source and Target paths are identical"); } try { // wants to rename a directory with the same name but different casing // (ie: C:\nant to C:\NAnt), then the move needs to be staged. if (PlatformHelper.IsWindows) { // If the directory names are the same but different casing, stage // the move by moving the source directory to a temp location // before moving it to the destination. if (sourceDirectory.Equals(destDirectory, StringComparison.InvariantCultureIgnoreCase)) { // Since the directory is being renamed with different // casing, the temp directory should be in the same // location as the destination directory to avoid // possible different volume errors. string rootPath = Directory.GetParent(destDirectory).FullName; string stagePath = Path.Combine(rootPath, Path.GetRandomFileName()); try { // Move the source dir to the stage path // before moving everything to the destination // path. Directory.Move(sourceDirectory, stagePath); Directory.Move(stagePath, destDirectory); } catch { // If an error occurred during the staged directory // move, check to see if the stage path exists. If // the source directory successfully moved to the // stage path, move the stage path back to the // source path and rethrow the exception. if (Directory.Exists(stagePath)) { if (!Directory.Exists(sourceDirectory)) { Directory.Move(stagePath, sourceDirectory); } } throw; } } // If the directory source and destination names are // different, use Directory.Move. else { Directory.Move(sourceDirectory, destDirectory); } } // Non-Windows systems, such as Linux/Unix, filenames and directories // are case-sensitive. So as long as the directory names are not // identical, with the check above, the Directory.Move method // can be used. else { Directory.Move(sourceDirectory, destDirectory); } } // Catch and rethrow any IO exceptions that may arise during // the directory move. catch (IOException ioEx) { // If the error occurred because the destination directory // exists, throw a build exception to tell the user that the // destination directory already exists. if (Directory.Exists(destDirectory)) { throw new BuildException( string.Format(CultureInfo.InvariantCulture, "Failed to move directory {0}." + "Directory '{1}' already exists.", sourceDirectory, destDirectory)); } // Any other IOExceptions should be displayed to the user // via build exception. else { throw new BuildException( String.Format("Unhandled IOException when trying to move directory '{0}' to '{1}'", sourceDirectory, destDirectory), ioEx); } } } else { // Otherwise, use the copy directory method and directory.delete // method to move the directory over. CopyDirectory(sourceDirectory, destDirectory, filterChain, inputEncoding, outputEncoding); Directory.Delete(sourceDirectory, true); } }