From de0390064a88adb4b8dae555a012febfc7fc6fd3 Mon Sep 17 00:00:00 2001 From: Andre Hofmeister <9199345+HofmeisterAn@users.noreply.github.com> Date: Thu, 22 Dec 2022 12:31:30 +0100 Subject: [PATCH] feat: Include file path in TarException: Entry closed at [...] (Docker build) --- .../Images/DockerfileArchive.cs | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/Testcontainers/Images/DockerfileArchive.cs b/src/Testcontainers/Images/DockerfileArchive.cs index 5089f9926..3e69efb9e 100644 --- a/src/Testcontainers/Images/DockerfileArchive.cs +++ b/src/Testcontainers/Images/DockerfileArchive.cs @@ -82,18 +82,30 @@ public string Tar() { tarArchive.RootPath = dockerfileDirectoryPath; - foreach (var file in GetFiles(dockerfileDirectoryPath)) + foreach (var absoluteFilePath in GetFiles(dockerfileDirectoryPath)) { // SharpZipLib drops the root path: https://github.com/icsharpcode/SharpZipLib/pull/582. - var relativePath = file.Substring(dockerfileDirectoryPath.TrimEnd(Path.AltDirectorySeparatorChar).Length + 1); + var relativeFilePath = absoluteFilePath.Substring(dockerfileDirectoryPath.TrimEnd(Path.AltDirectorySeparatorChar).Length + 1); - if (dockerIgnoreFile.Denies(relativePath)) + if (dockerIgnoreFile.Denies(relativeFilePath)) { continue; } - var tarEntry = TarEntry.CreateEntryFromFile(file); - tarEntry.Name = relativePath; + // SharpZipLib's WriteEntry(TarEntry, bool) writes the entry, but without bytes if the file is used by another process. + // This results in a TarException on TarArchive.Dispose(): Entry closed at '0' before the 'x' bytes specified in the header were written. + try + { + var fileStream = File.Open(absoluteFilePath, FileMode.Open, FileAccess.Read, FileShare.Read); + fileStream.Dispose(); + } + catch (IOException e) + { + throw new IOException("Cannot create Docker image tar archive.", e); + } + + var tarEntry = TarEntry.CreateEntryFromFile(absoluteFilePath); + tarEntry.Name = relativeFilePath; tarArchive.WriteEntry(tarEntry, false); } }