diff --git a/src/chocolatey.console/chocolatey.console.csproj b/src/chocolatey.console/chocolatey.console.csproj index b7b24e8d89..bab31e2b48 100644 --- a/src/chocolatey.console/chocolatey.console.csproj +++ b/src/chocolatey.console/chocolatey.console.csproj @@ -78,6 +78,9 @@ app.manifest + + ..\packages\AlphaFS.2.0.1\lib\net40\AlphaFS.dll + ..\packages\log4net.2.0.3\lib\net40-client\log4net.dll @@ -101,6 +104,7 @@ ..\..\lib\PowerShell\System.Management.Automation.dll + diff --git a/src/chocolatey.console/packages.config b/src/chocolatey.console/packages.config index 09f71a5edb..586ded25fb 100644 --- a/src/chocolatey.console/packages.config +++ b/src/chocolatey.console/packages.config @@ -1,6 +1,7 @@  + diff --git a/src/chocolatey/chocolatey.csproj b/src/chocolatey/chocolatey.csproj index 0d497002cf..a617d80c2b 100644 --- a/src/chocolatey/chocolatey.csproj +++ b/src/chocolatey/chocolatey.csproj @@ -38,6 +38,9 @@ ..\..\docs\logo\chocolatey.ico + + ..\packages\AlphaFS.2.0.1\lib\net40\AlphaFS.dll + ..\packages\log4net.2.0.3\lib\net40-client\log4net.dll @@ -73,6 +76,7 @@ ..\packages\Rx-Linq.2.1.30214.0\lib\Net40\System.Reactive.Linq.dll + diff --git a/src/chocolatey/infrastructure.app/tasks/RemovePendingPackagesTask.cs b/src/chocolatey/infrastructure.app/tasks/RemovePendingPackagesTask.cs index c7e507063a..d8e5bfe795 100644 --- a/src/chocolatey/infrastructure.app/tasks/RemovePendingPackagesTask.cs +++ b/src/chocolatey/infrastructure.app/tasks/RemovePendingPackagesTask.cs @@ -63,7 +63,7 @@ private void handle_message(PreRunMessage message) foreach (var pendingFile in pendingFiles.or_empty_list_if_null()) { var packageFolder = _fileSystem.get_directory_name(pendingFile); - var packageFolderName = _fileSystem.get_directory_info_for(packageFolder).Name; + string packageFolderName = _fileSystem.get_directory_info_for(packageFolder).Name; var pendingSkipFiles = _fileSystem.get_files(packageFolder, PENDING_SKIP_FILE, SearchOption.AllDirectories).ToList(); if (pendingSkipFiles.Count != 0) diff --git a/src/chocolatey/infrastructure/filesystem/DotNetFileSystem.cs b/src/chocolatey/infrastructure/filesystem/DotNetFileSystem.cs index 3ce347118c..7c3e30fb36 100644 --- a/src/chocolatey/infrastructure/filesystem/DotNetFileSystem.cs +++ b/src/chocolatey/infrastructure/filesystem/DotNetFileSystem.cs @@ -40,6 +40,8 @@ public sealed class DotNetFileSystem : IFileSystem { private readonly int TIMES_TO_TRY_OPERATION = 3; private static Lazy environment_initializer = new Lazy(() => new Environment()); + private const int MAX_PATH_FILE = 255; + private const int MAX_PATH_DIRECTORY = 248; private void allow_retries(Action action, bool isSilent = false) { @@ -48,7 +50,7 @@ private void allow_retries(Action action, bool isSilent = false) action, waitDurationMilliseconds: 200, increaseRetryByMilliseconds: 100, - isSilent:isSilent); + isSilent: isSilent); } [EditorBrowsable(EditorBrowsableState.Never)] @@ -56,7 +58,7 @@ public void initialize_with(Lazy environment) { environment_initializer = environment; } - + private static IEnvironment Environment { get { return environment_initializer.Value; } @@ -71,14 +73,14 @@ public string combine_paths(string leftItem, params string[] rightItems) var methodName = string.Empty; var stackFrame = new System.Diagnostics.StackFrame(1); if (stackFrame != null) methodName = stackFrame.GetMethod().Name; - throw new ApplicationException("Path to combine cannot be empty. Tried to combine null with '{0}'.{1}".format_with(string.Join(",", rightItems),string.IsNullOrWhiteSpace(methodName) ? string.Empty : " Method called from '{0}'".format_with(methodName))); + throw new ApplicationException("Path to combine cannot be empty. Tried to combine null with '{0}'.{1}".format_with(string.Join(",", rightItems), string.IsNullOrWhiteSpace(methodName) ? string.Empty : " Method called from '{0}'".format_with(methodName))); } var combinedPath = Platform.get_platform() == PlatformType.Windows ? leftItem : leftItem.Replace('\\', '/'); foreach (var rightItem in rightItems) { if (rightItem.Contains(":")) throw new ApplicationException("Cannot combine a path with ':' attempted to combine '{0}' with '{1}'".format_with(rightItem, combinedPath)); - + var rightSide = Platform.get_platform() == PlatformType.Windows ? rightItem : rightItem.Replace('\\', '/'); if (rightSide.StartsWith(Path.DirectorySeparatorChar.to_string()) || rightSide.StartsWith(Path.AltDirectorySeparatorChar.to_string())) { @@ -97,7 +99,14 @@ public string get_full_path(string path) { if (string.IsNullOrWhiteSpace(path)) return path; - return Path.GetFullPath(path); + try + { + return Path.GetFullPath(path); + } + catch (IOException) + { + return Alphaleonis.Win32.Filesystem.Path.GetFullPath(path); + } } public string get_temp_path() @@ -105,7 +114,7 @@ public string get_temp_path() var path = Path.GetTempPath(); if (System.Environment.UserName.contains(ApplicationParameters.Environment.SystemUserName) || path.contains("config\\systemprofile\\appdata")) - { + { path = System.Environment.ExpandEnvironmentVariables(System.Environment.GetEnvironmentVariable(ApplicationParameters.Environment.Temp, EnvironmentVariableTarget.Machine).to_string()); } @@ -131,7 +140,7 @@ public string get_executable_path(string executableName) if (get_file_name_without_extension(executableName).is_equal_to(executableName) && isWindows) { - var pathExtensions = Environment.GetEnvironmentVariable(ApplicationParameters.Environment.PathExtensions).to_string().Split(new[] {ApplicationParameters.Environment.EnvironmentSeparator}, StringSplitOptions.RemoveEmptyEntries); + var pathExtensions = Environment.GetEnvironmentVariable(ApplicationParameters.Environment.PathExtensions).to_string().Split(new[] { ApplicationParameters.Environment.EnvironmentSeparator }, StringSplitOptions.RemoveEmptyEntries); foreach (var extension in pathExtensions.or_empty_list_if_null()) { extensions.Add(extension.StartsWith(".") ? extension : ".{0}".format_with(extension)); @@ -167,7 +176,7 @@ public string get_current_assembly_path() { return Assembly.GetExecutingAssembly().CodeBase.Replace("file:///", string.Empty); } - + #endregion #region File @@ -194,7 +203,14 @@ public IEnumerable get_files(string directoryPath, string[] extensions, public bool file_exists(string filePath) { - return File.Exists(filePath); + try + { + return File.Exists(filePath); + } + catch (IOException) + { + return Alphaleonis.Win32.Filesystem.File.Exists(filePath); + } } public string get_file_name(string filePath) @@ -216,9 +232,21 @@ public string get_file_extension(string filePath) return Path.GetExtension(filePath.Replace('\\', '/')); } - public FileInfo get_file_info_for(string filePath) + public dynamic get_file_info_for(string filePath) { - return new FileInfo(filePath); + try + { + if (!string.IsNullOrWhiteSpace(filePath) && filePath.Length >= MAX_PATH_FILE) + { + return new Alphaleonis.Win32.Filesystem.FileInfo(filePath); + } + + return new FileInfo(filePath); + } + catch (IOException) + { + return new Alphaleonis.Win32.Filesystem.FileInfo(filePath); + } } public System.DateTime get_file_modified_date(string filePath) @@ -236,65 +264,69 @@ public string get_file_version_for(string filePath) return FileVersionInfo.GetVersionInfo(get_full_path(filePath)).FileVersion; } - public bool is_system_file(FileInfo file) + public bool is_system_file(dynamic file) { bool isSystemFile = ((file.Attributes & FileAttributes.System) == FileAttributes.System); if (!isSystemFile) { //check the directory to be sure - DirectoryInfo directoryInfo = get_directory_info_for(file.DirectoryName); + var directoryInfo = get_directory_info_for(file.DirectoryName); isSystemFile = ((directoryInfo.Attributes & FileAttributes.System) == FileAttributes.System); } else { - this.Log().Debug(ChocolateyLoggers.Verbose, () => "File \"{0}\" is a system file.".format_with(file.FullName)); + string fullName = file.FullName; + this.Log().Debug(ChocolateyLoggers.Verbose, () => "File \"{0}\" is a system file.".format_with(fullName)); } return isSystemFile; } - public bool is_readonly_file(FileInfo file) + public bool is_readonly_file(dynamic file) { bool isReadOnlyFile = ((file.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly); if (!isReadOnlyFile) { //check the directory to be sure - DirectoryInfo directoryInfo = get_directory_info_for(file.DirectoryName); + dynamic directoryInfo = get_directory_info_for(file.DirectoryName); isReadOnlyFile = ((directoryInfo.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly); } else { - this.Log().Debug(ChocolateyLoggers.Verbose, () => "File \"{0}\" is a readonly file.".format_with(file.FullName)); + string fullName = file.FullName; + this.Log().Debug(ChocolateyLoggers.Verbose, () => "File \"{0}\" is a readonly file.".format_with(fullName)); } return isReadOnlyFile; } - public bool is_hidden_file(FileInfo file) + public bool is_hidden_file(dynamic file) { bool isHiddenFile = ((file.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden); if (!isHiddenFile) { //check the directory to be sure - DirectoryInfo directoryInfo = get_directory_info_for(file.DirectoryName); + var directoryInfo = get_directory_info_for(file.DirectoryName); isHiddenFile = ((directoryInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden); } else { - this.Log().Debug(ChocolateyLoggers.Verbose, () => "File \"{0}\" is a hidden file.".format_with(file.FullName)); + string fullName = file.FullName; + this.Log().Debug(ChocolateyLoggers.Verbose, () => "File \"{0}\" is a hidden file.".format_with(fullName)); } return isHiddenFile; } - public bool is_encrypted_file(FileInfo file) + public bool is_encrypted_file(dynamic file) { bool isEncrypted = ((file.Attributes & FileAttributes.Encrypted) == FileAttributes.Encrypted); - this.Log().Debug(ChocolateyLoggers.Verbose, () => "Is file \"{0}\" an encrypted file? {1}".format_with(file.FullName, isEncrypted.to_string())); + string fullName = file.FullName; + this.Log().Debug(ChocolateyLoggers.Verbose, () => "Is file \"{0}\" an encrypted file? {1}".format_with(fullName, isEncrypted.to_string())); return isEncrypted; } - public string get_file_date(FileInfo file) + public string get_file_date(dynamic file) { return file.CreationTime < file.LastWriteTime ? file.CreationTime.Date.ToString("yyyyMMdd") @@ -303,7 +335,18 @@ public string get_file_date(FileInfo file) public void move_file(string filePath, string newFilePath) { - allow_retries(() => File.Move(filePath, newFilePath)); + allow_retries( + () => + { + try + { + File.Move(filePath, newFilePath); + } + catch (IOException) + { + Alphaleonis.Win32.Filesystem.File.Move(filePath, newFilePath); + } + }); //Thread.Sleep(10); } @@ -312,7 +355,18 @@ public void copy_file(string sourceFilePath, string destinationFilePath, bool ov this.Log().Debug(ChocolateyLoggers.Verbose, () => "Attempting to copy \"{0}\"{1} to \"{2}\".".format_with(sourceFilePath, Environment.NewLine, destinationFilePath)); create_directory_if_not_exists(get_directory_name(destinationFilePath), ignoreError: true); - allow_retries(() => File.Copy(sourceFilePath, destinationFilePath, overwriteExisting)); + allow_retries( + () => + { + try + { + File.Copy(sourceFilePath, destinationFilePath, overwriteExisting); + } + catch (IOException) + { + Alphaleonis.Win32.Filesystem.File.Copy(sourceFilePath, destinationFilePath, overwriteExisting); + } + }); } public bool copy_file_unsafe(string sourceFilePath, string destinationFilePath, bool overwriteExisting) @@ -331,7 +385,7 @@ public bool copy_file_unsafe(string sourceFilePath, string destinationFilePath, //if (success == 0) //{ // var error = Marshal.GetLastWin32Error(); - + //} return success != 0; } @@ -358,7 +412,18 @@ public void delete_file(string filePath) this.Log().Debug(ChocolateyLoggers.Verbose, () => "Attempting to delete file \"{0}\".".format_with(filePath)); if (file_exists(filePath)) { - allow_retries(() => File.Delete(filePath)); + allow_retries( + () => + { + try + { + File.Delete(filePath); + } + catch (IOException) + { + Alphaleonis.Win32.Filesystem.File.Delete(filePath); + } + }); } } @@ -369,7 +434,14 @@ public FileStream create_file(string filePath) public string read_file(string filePath) { - return File.ReadAllText(filePath, get_file_encoding(filePath)); + try + { + return File.ReadAllText(filePath, get_file_encoding(filePath)); + } + catch (IOException) + { + return Alphaleonis.Win32.Filesystem.File.ReadAllText(filePath, get_file_encoding(filePath)); + } } public byte[] read_file_bytes(string filePath) @@ -384,7 +456,7 @@ public FileStream open_file_readonly(string filePath) public FileStream open_file_exclusive(string filePath) { - return File.Open(filePath,FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.None); + return File.Open(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); } public void write_file(string filePath, string fileText) @@ -447,36 +519,92 @@ public bool directory_exists(string directoryPath) public string get_directory_name(string filePath) { - if (Platform.get_platform() == PlatformType.Windows) return Path.GetDirectoryName(filePath); - - return Path.GetDirectoryName(filePath.Replace('\\', '/')); + if (Platform.get_platform() != PlatformType.Windows && !string.IsNullOrWhiteSpace(filePath)) + { + filePath = filePath.Replace('\\', '/'); + } + + try + { + return Path.GetDirectoryName(filePath); + } + catch (IOException) + { + return Alphaleonis.Win32.Filesystem.Path.GetDirectoryName(filePath); + } } - public DirectoryInfo get_directory_info_for(string directoryPath) + public dynamic get_directory_info_for(string directoryPath) { - return new DirectoryInfo(directoryPath); + try + { + if (!string.IsNullOrWhiteSpace(directoryPath) && directoryPath.Length >= MAX_PATH_DIRECTORY) + { + return new Alphaleonis.Win32.Filesystem.DirectoryInfo(directoryPath); + } + + return new DirectoryInfo(directoryPath); + } + catch (IOException) + { + return new Alphaleonis.Win32.Filesystem.DirectoryInfo(directoryPath); + } } - public DirectoryInfo get_directory_info_from_file_path(string filePath) + public dynamic get_directory_info_from_file_path(string filePath) { - return new DirectoryInfo(filePath).Parent; + try + { + if (!string.IsNullOrWhiteSpace(filePath) && filePath.Length >= MAX_PATH_FILE) + { + return new Alphaleonis.Win32.Filesystem.DirectoryInfo(filePath).Parent; + } + + return new DirectoryInfo(filePath).Parent; + } + catch (IOException) + { + return new Alphaleonis.Win32.Filesystem.DirectoryInfo(filePath).Parent; + } } public void create_directory(string directoryPath) { this.Log().Debug(ChocolateyLoggers.Verbose, () => "Attempting to create directory \"{0}\".".format_with(get_full_path(directoryPath))); - allow_retries(() => Directory.CreateDirectory(directoryPath)); + allow_retries( + () => + { + try + { + Directory.CreateDirectory(directoryPath); + } + catch (IOException) + { + Alphaleonis.Win32.Filesystem.Directory.CreateDirectory(directoryPath); + } + }); } public void move_directory(string directoryPath, string newDirectoryPath) { if (string.IsNullOrWhiteSpace(directoryPath) || string.IsNullOrWhiteSpace(newDirectoryPath)) throw new ApplicationException("You must provide a directory to move from or to."); - if (combine_paths(directoryPath,"").is_equal_to(combine_paths(Environment.GetEnvironmentVariable("SystemDrive"),""))) throw new ApplicationException("Cannot move or delete the root of the system drive"); + if (combine_paths(directoryPath, "").is_equal_to(combine_paths(Environment.GetEnvironmentVariable("SystemDrive"), ""))) throw new ApplicationException("Cannot move or delete the root of the system drive"); try { this.Log().Debug(ChocolateyLoggers.Verbose, "Moving '{0}'{1} to '{2}'".format_with(directoryPath, Environment.NewLine, newDirectoryPath)); - allow_retries(() => Directory.Move(directoryPath, newDirectoryPath)); + allow_retries( + () => + { + try + { + Directory.Move(directoryPath, newDirectoryPath); + } + catch (IOException) + { + Alphaleonis.Win32.Filesystem.Directory.Move(directoryPath, newDirectoryPath); + } + }); } catch (Exception ex) { @@ -568,9 +696,19 @@ public void delete_directory(string directoryPath, bool recursive, bool override } if (!isSilent) this.Log().Debug(ChocolateyLoggers.Verbose, () => "Attempting to delete directory \"{0}\".".format_with(get_full_path(directoryPath))); - allow_retries(() => Directory.Delete(directoryPath, recursive),isSilent: isSilent); + allow_retries( + () => + { + try + { + Directory.Delete(directoryPath, recursive); + } + catch (IOException) + { + Alphaleonis.Win32.Filesystem.Directory.Delete(directoryPath, recursive); + } + }, isSilent: isSilent); } - public void delete_directory_if_exists(string directoryPath, bool recursive) { diff --git a/src/chocolatey/infrastructure/filesystem/IFileSystem.cs b/src/chocolatey/infrastructure/filesystem/IFileSystem.cs index 1a525531c6..4d41005bcc 100644 --- a/src/chocolatey/infrastructure/filesystem/IFileSystem.cs +++ b/src/chocolatey/infrastructure/filesystem/IFileSystem.cs @@ -121,8 +121,8 @@ public interface IFileSystem /// Determines the file information given a path to an existing file /// /// Path to an existing file - /// FileInfo object - FileInfo get_file_info_for(string filePath); + /// FileInfo object or reimplementation of a FileInfo object that works with greater than 260 chars + dynamic get_file_info_for(string filePath); /// /// Gets the file mod date. @@ -148,37 +148,37 @@ public interface IFileSystem /// /// Determines if a file is a system file /// - /// File to check + /// File to check - FileInfo or some representation of FileInfo /// True if the file has the System attribute marked, otherwise false - bool is_system_file(FileInfo file); + bool is_system_file(dynamic file); /// /// Determines if a file is a read only file /// - /// File to check + /// File to check - FileInfo or some representation of FileInfo /// True if the file has the ReadOnly attribute marked, otherwise false - bool is_readonly_file(FileInfo file); + bool is_readonly_file(dynamic file); /// /// Determines if a file is a hidden file /// - /// File to check + /// File to check - FileInfo or some representation of FileInfo /// True if the file has the Hidden attribute marked, otherwise false - bool is_hidden_file(FileInfo file); + bool is_hidden_file(dynamic file); /// /// Determines if a file is encrypted or not /// - /// File to check + /// File to check - FileInfo or some representation of FileInfo /// True if the file has the Encrypted attribute marked, otherwise false - bool is_encrypted_file(FileInfo file); + bool is_encrypted_file(dynamic file); /// /// Determines the older of the file dates, Creation Date or Modified Date /// - /// File to analyze + /// File to analyze - FileInfo or some representation of FileInfo /// The oldest date on the file - string get_file_date(FileInfo file); + string get_file_date(dynamic file); /// /// Moves a specified file to a new location, providing the option to specify a new file name. @@ -311,15 +311,15 @@ public interface IFileSystem /// Returns a DirectoryInfo object from a string /// /// Full path to the directory you want the directory information for - /// DirectoryInfo object - DirectoryInfo get_directory_info_for(string directoryPath); + /// DirectoryInfo object or reimplementation of a DirectoryInfo object that works with greater than 248 chars + dynamic get_directory_info_for(string directoryPath); /// /// Returns a DirectoryInfo object from a string to a filepath /// /// Full path to the file you want directory information for - /// DirectoryInfo object - DirectoryInfo get_directory_info_from_file_path(string filePath); + /// DirectoryInfo object or reimplementation of a DirectoryInfo object that works with greater than 248 chars + dynamic get_directory_info_from_file_path(string filePath); /// /// Creates all directories and subdirectories in the specified path. diff --git a/src/chocolatey/packages.config b/src/chocolatey/packages.config index e3e550ac83..8ad4ed34c2 100644 --- a/src/chocolatey/packages.config +++ b/src/chocolatey/packages.config @@ -1,6 +1,7 @@  +