//this is a buffered manual copy rather than File.Copy, so that we can get progress callbacks //for a smoother progress bar protected virtual void CopyFile(string source, string target, CopyReportCallback report) { FileStream inStream = null; FileStream outStream = null; try{ inStream = File.Open(source, FileMode.Open, FileAccess.Read); outStream = File.Open(target, FileMode.Create, FileAccess.Write); int bytesPerLoop = 1024; byte[] buffer = new byte [bytesPerLoop]; int count = 0; do { count = inStream.Read(buffer, 0, bytesPerLoop); outStream.Write(buffer, 0, count); //outStream.Flush (); //? buffer likely to flush every 4kb anyway report(count); } while (count > 0); } finally { if (inStream != null) { inStream.Close(); } if (outStream != null) { outStream.Close(); } } }
//this is a buffered manual copy rather than File.Copy, so that we can get progress callbacks //for a smoother progress bar protected virtual void CopyFile (string source, string target, CopyReportCallback report) { FileStream inStream = null; FileStream outStream = null; try{ inStream = File.Open (source, FileMode.Open, FileAccess.Read); outStream = File.Open (target, FileMode.Create, FileAccess.Write); int bytesPerLoop = 1024; byte[] buffer = new byte [bytesPerLoop]; int count = 0; do { count = inStream.Read (buffer, 0, bytesPerLoop); outStream.Write (buffer, 0, count); //outStream.Flush (); //? buffer likely to flush every 4kb anyway report (count); } while (count > 0); } finally { if (inStream != null) inStream.Close (); if (outStream != null) outStream.Close (); } }
internal void InternalCopyFiles(IProgressMonitor monitor, IFileReplacePolicy replacePolicy, FileCopyConfiguration copyConfig, DeployFileCollection deployFiles, DeployContext context, string realPrefix) { string targetDirectory = ((LocalFileCopyConfiguration)copyConfig).TargetDirectory; if (string.IsNullOrEmpty(copyConfig.FriendlyLocation) || string.IsNullOrEmpty(targetDirectory)) { throw new InvalidOperationException("Cannot deploy to unconfigured location."); } List <DeployFileConf> files = new List <DeployFileConf> (); long totalFileSize = 0; //pre-scan: ask all copy/replace questions first so user doesn't have to wait, and get foreach (DeployFile df in deployFiles) { if (!context.IncludeFile(df)) { continue; } DeployFileConf dfc = new DeployFileConf(); files.Add(dfc); dfc.SourceFile = df.SourcePath; dfc.FileSize = FileSize(dfc.SourceFile); totalFileSize += dfc.FileSize; string relativeTarget = context.GetResolvedPath(df.TargetDirectoryID, df.RelativeTargetPath); if (relativeTarget == null) { throw new InvalidOperationException(GettextCatalog.GetString("Could not resolve target directory ID \"{0}\"", df.TargetDirectoryID)); } dfc.TargetFile = Path.Combine(targetDirectory, relativeTarget); //this is a bit hacky; it's an internal hook to the BaseFuseFileCopyHandler implementation a level up the inheritance heirarchy //Essentailly we are aliasing the path so that BaseFuseFileCopyHandler can use LocalFileCopyHandler to do the local copying //after the temp FUSE directory is mounted if (!string.IsNullOrEmpty(realPrefix)) { dfc.InternalTargetFile = Path.Combine(realPrefix, context.GetResolvedPath(df.TargetDirectoryID, df.RelativeTargetPath)); } else { dfc.InternalTargetFile = dfc.TargetFile; } if (FileExists(dfc.InternalTargetFile)) { dfc.SourceModified = File.GetLastWriteTime(dfc.SourceFile); dfc.TargetModified = GetTargetModificationTime(dfc.InternalTargetFile); dfc.ReplaceMode = replacePolicy.GetReplaceAction(dfc.SourceFile, dfc.SourceModified, dfc.TargetFile, dfc.TargetModified); if (dfc.ReplaceMode == FileReplaceMode.Abort) { monitor.Log.WriteLine(GettextCatalog.GetString("Deployment aborted: target file {0} already exists.", dfc.TargetFile)); throw new OperationCanceledException(); } } } //PROBLEM: monitor takes ints, file sizes are longs //HOWEVER: longs are excessively long for a progress bar //SOLUTION: assume total task has a length of 1000 (longer than this is probably unnecessary for a progress bar), // and set up a callback system for translating the actual long number of bytes into a portion of this const int progressBarLength = 1000; long stepSize = totalFileSize / progressBarLength; long carry = 0; monitor.BeginTask(copyConfig.FriendlyLocation, progressBarLength); CopyReportCallback copyCallback = delegate(long bytes) { if (monitor.IsCancelRequested) { return(false); } int steps = (int)(bytes / stepSize); carry += bytes % stepSize; if (carry > stepSize) { steps += 1; carry -= stepSize; } if (steps > 0) { monitor.Step(steps); } return(true); }; //now the actual copy foreach (DeployFileConf file in files) { //abort the copy if cancelling if (monitor.IsCancelRequested) { break; } EnsureDirectoryExists(Path.GetDirectoryName(file.InternalTargetFile)); if (file.ReplaceMode != FileReplaceMode.NotSet) { switch (file.ReplaceMode) { case FileReplaceMode.Skip: monitor.Log.WriteLine(GettextCatalog.GetString("Skipped {0}: file exists.", file.TargetFile)); copyCallback(file.FileSize); continue; //next file case FileReplaceMode.Replace: monitor.Log.WriteLine(GettextCatalog.GetString("Replaced {0}.", file.TargetFile)); break; case FileReplaceMode.ReplaceOlder: if (file.SourceModified > file.TargetModified) { monitor.Log.WriteLine(GettextCatalog.GetString("Replacing {0}: existing file is older.", file.TargetFile)); } else { if (file.SourceModified == file.TargetModified) { monitor.Log.WriteLine(GettextCatalog.GetString("Skipped {0}: existing file is the same age.", file.TargetFile)); } else { monitor.Log.WriteLine(GettextCatalog.GetString("Skipped {0}: existing file is newer.", file.TargetFile)); } copyCallback(file.FileSize); continue; //next file } break; } } else { monitor.Log.WriteLine(GettextCatalog.GetString("Deployed file {0}.", file.TargetFile)); } CopyFile(file.SourceFile, file.InternalTargetFile, copyCallback); } monitor.EndTask(); }