From 67d91aebdc663fe84409468e7b9b37bc5f860404 Mon Sep 17 00:00:00 2001 From: Paul Hebble Date: Thu, 2 Jun 2022 17:14:06 +0000 Subject: [PATCH] Fix tracking of paths with trailing spaces on Windows --- Core/ModuleInstaller.cs | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/Core/ModuleInstaller.cs b/Core/ModuleInstaller.cs index 8f5ec4ea02..ce87aadc58 100644 --- a/Core/ModuleInstaller.cs +++ b/Core/ModuleInstaller.cs @@ -327,6 +327,7 @@ private static void CheckKindInstallationKraken(CkanModule module) private IEnumerable InstallModule(CkanModule module, string zip_filename, Registry registry, ref HashSet possibleConfigOnlyDirs) { CheckKindInstallationKraken(module); + var createdPaths = new List(); using (ZipFile zipfile = new ZipFile(zip_filename)) { @@ -387,7 +388,7 @@ private IEnumerable InstallModule(CkanModule module, string zip_filename foreach (InstallableFile file in files) { log.DebugFormat("Copying {0}", file.source.Name); - CopyZipEntry(zipfile, file.source, file.destination, file.makedir); + createdPaths.Add(CopyZipEntry(zipfile, file.source, file.destination, file.makedir)); if (file.source.IsDirectory && possibleConfigOnlyDirs != null) { possibleConfigOnlyDirs.Remove(file.destination); @@ -403,9 +404,8 @@ private IEnumerable InstallModule(CkanModule module, string zip_filename kraken.owningModule = registry.FileOwner(kraken.filename); throw; } - - return files.Select(x => x.destination); } + return createdPaths.Where(p => p != null); } /// @@ -561,7 +561,11 @@ public static List FindInstallableFiles(CkanModule module, stri /// /// Copy the entry from the opened zipfile to the path specified. /// - internal static void CopyZipEntry(ZipFile zipfile, ZipEntry entry, string fullPath, bool makeDirs) + /// + /// Path of file or directory that was created. + /// May differ from the input fullPath! + /// + internal static string CopyZipEntry(ZipFile zipfile, ZipEntry entry, string fullPath, bool makeDirs) { TxFileManager file_transaction = new TxFileManager(); @@ -570,30 +574,33 @@ internal static void CopyZipEntry(ZipFile zipfile, ZipEntry entry, string fullPa // Skip if we're not making directories for this install. if (!makeDirs) { - log.DebugFormat("Skipping {0}, we don't make directories for this path", fullPath); - return; + log.DebugFormat("Skipping '{0}', we don't make directories for this path", fullPath); + return null; } - log.DebugFormat("Making directory {0}", fullPath); + // Windows silently trims trailing spaces, get the path it will actually use + fullPath = CKANPathUtils.NormalizePath(Path.GetDirectoryName( + Path.Combine(fullPath, "DUMMY"))); + + log.DebugFormat("Making directory '{0}'", fullPath); file_transaction.CreateDirectory(fullPath); } else { - log.DebugFormat("Writing file {0}", fullPath); + log.DebugFormat("Writing file '{0}'", fullPath); - // Sometimes there are zipfiles that don't contain entries for the - // directories their files are in. No, I understand either, but - // the result is we have to make sure our directories exist, just in case. + // ZIP format does not require directory entries if (makeDirs) { string directory = Path.GetDirectoryName(fullPath); + log.DebugFormat("Making parent directory '{0}'", directory); file_transaction.CreateDirectory(directory); } // We don't allow for the overwriting of files. See #208. if (file_transaction.FileExists(fullPath)) { - throw new FileExistsKraken(fullPath, string.Format("Trying to write {0} but it already exists.", fullPath)); + throw new FileExistsKraken(fullPath, string.Format("Trying to write '{0}' but it already exists.", fullPath)); } // Snapshot whatever was there before. If there's nothing, this will just @@ -607,6 +614,8 @@ internal static void CopyZipEntry(ZipFile zipfile, ZipEntry entry, string fullPa using (Stream zipStream = zipfile.GetInputStream(entry)) using (FileStream writer = File.Create(fullPath)) { + // Windows silently changes paths ending with spaces, get the name it actually used + fullPath = CKANPathUtils.NormalizePath(writer.Name); // 4k is the block size on practically every disk and OS. byte[] buffer = new byte[4096]; StreamUtils.Copy(zipStream, writer, buffer); @@ -617,6 +626,9 @@ internal static void CopyZipEntry(ZipFile zipfile, ZipEntry entry, string fullPa throw new DirectoryNotFoundKraken("", ex.Message, ex); } } + // Usually, this is the path we're given. + // Sometimes it has trailing spaces trimmed by the OS. + return fullPath; } ///