diff --git a/src/ICSharpCode.SharpZipLib/Tar/TarArchive.cs b/src/ICSharpCode.SharpZipLib/Tar/TarArchive.cs
index 878649017..a20ca2455 100644
--- a/src/ICSharpCode.SharpZipLib/Tar/TarArchive.cs
+++ b/src/ICSharpCode.SharpZipLib/Tar/TarArchive.cs
@@ -857,12 +857,34 @@ private void WriteEntryCore(TarEntry sourceEntry, bool recurse)
if (!String.IsNullOrEmpty(rootPath))
{
- if (entry.Name.StartsWith(rootPath, StringComparison.OrdinalIgnoreCase))
+ string newRootPath = rootPath;
+
+ // remove CurrentDirectory from RootPath to be consistent with TarEntry behavior
+ var currentDirectory = Directory.GetCurrentDirectory()
+ .ToTarArchivePath();
+ if (rootPath.StartsWith(currentDirectory, StringComparison.OrdinalIgnoreCase))
{
- newName = entry.Name.Substring(rootPath.Length + 1);
+ if (rootPath.Length == currentDirectory.Length)
+ {
+ // if they are the same, rootPath would be empty
+ // and so the entry name is not modified
+ newRootPath = string.Empty;
+ }
+ else
+ {
+ // TarEntry would have removed the current directory from the entry name, and so do the same here
+ newRootPath = rootPath.Substring(currentDirectory.Length + 1);
+ }
+ }
+
+ if (!string.IsNullOrEmpty(newRootPath) &&
+ entry.Name.StartsWith(newRootPath, StringComparison.OrdinalIgnoreCase))
+ {
+ newName = entry.Name.Substring(newRootPath.Length + 1);
}
}
+
if (pathPrefix != null)
{
newName = (newName == null) ? pathPrefix + "/" + entry.Name : pathPrefix + "/" + newName;
diff --git a/test/ICSharpCode.SharpZipLib.Tests/Tar/TarTests.cs b/test/ICSharpCode.SharpZipLib.Tests/Tar/TarTests.cs
index c6a35ff08..e6236d382 100644
--- a/test/ICSharpCode.SharpZipLib.Tests/Tar/TarTests.cs
+++ b/test/ICSharpCode.SharpZipLib.Tests/Tar/TarTests.cs
@@ -4,6 +4,7 @@
using NUnit.Framework;
using System;
using System.IO;
+using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -916,5 +917,113 @@ public void RootPathIsRespected()
}
}
}
+
+ ///
+ /// This tests the behavior of the property on
+ /// which are created under the .
+ ///
+ ///
+ /// The value to set to the property.
+ /// A value of will keep the property unset.
+ ///
+ ///
+ /// If true, prefixes the with the .
+ ///
+ ///
+ /// If true, changes the to point to the
+ /// temporary working directory where the test files are created.
+ ///
+ ///
+ /// The list of path segments to join, which represents the expeced path of
+ /// the file in the archive.
+ ///
+ [Test]
+ [Category("Tar")]
+ // {workingDirectory}/temp {workingDirectory}/temp/file.txt -> "file.txt"
+ [TestCase("temp", true, true, new string[] { "file.txt" })]
+ // (unset) {workingDirectory}/temp/file.txt -> "temp/file.txt"
+ [TestCase("", false, true, new string[] { "temp", "file.txt" })]
+ // "temp" {workingDirectory}/temp/file.txt -> "file.txt"
+ [TestCase("temp", false, true, new string[] { "file.txt" })]
+ // nonWorkDir/temp/ nonWorkDir/temp/file.txt -> "file.txt"
+ [TestCase("temp", true, false, new string[] { "file.txt" })]
+ // (unset) /nonWorkDir/temp/file.txt -> "/nonWorkDir/temp/file.txt"
+ // cannot test this case, it relies on the path of the temp dir
+ // [TestCase("", true, false, new string[] { "temp", "file.txt" })]
+ public void TestRootPathBehavior(string rootPath, bool setRootPathPrefix, bool setCurrentDirectory, string[] expectedFilePath)
+ {
+ // when overrideWorkingDirectory is false, assumption is that working directory is that of the assembly
+ // which is not the same as the temporary directory
+
+ using (var workDir = new TempDir())
+ using (var tarFileName = new TempFile())
+ using (var extractDirectory = new TempDir())
+ {
+ if (setCurrentDirectory)
+ {
+ Environment.CurrentDirectory = workDir;
+ }
+
+ if (setRootPathPrefix)
+ {
+ rootPath = Path.Combine(workDir, rootPath);
+ }
+
+ string testFilePath = Path.Combine(workDir, "temp", "file.txt");
+ Directory.CreateDirectory(Path.Combine(workDir, "temp"));
+ File.WriteAllText(testFilePath, Guid.NewGuid().ToString());
+
+ using (var tarFile = File.Open(tarFileName.FullName, FileMode.Create))
+ {
+ using (var tarOutputStream = TarArchive.CreateOutputTarArchive(tarFile))
+ {
+ if (rootPath != string.Empty)
+ {
+ tarOutputStream.RootPath = rootPath;
+ }
+
+ string assignedRootPath = tarOutputStream.RootPath;
+
+ var entry = TarEntry.CreateEntryFromFile(testFilePath);
+
+ // TarEntry.Name may be relative or absolute depending on if it
+ // was created under the CurrentDirectory
+ if (setCurrentDirectory)
+ {
+ Assert.AreEqual("temp/file.txt", entry.Name);
+ }
+ else
+ {
+ Assert.IsTrue(entry.Name.EndsWith("temp/file.txt"));
+ }
+
+ tarOutputStream.WriteEntry(entry, true);
+
+ // RootPath property does not change
+ Assert.AreEqual(assignedRootPath, tarOutputStream.RootPath);
+ }
+ }
+
+ using (var file = File.OpenRead(tarFileName.FullName))
+ {
+ using (var archive = TarArchive.CreateInputTarArchive(file, Encoding.UTF8))
+ {
+ archive.ExtractContents(extractDirectory.FullName);
+ }
+ }
+
+ var expectationDirectory = new DirectoryInfo(extractDirectory.FullName);
+ var expectedFile = expectationDirectory.GetFiles("", SearchOption.AllDirectories)
+ .First(); // should only contain a single file
+
+ var expected = Path.Combine(extractDirectory.FullName, Path.Combine(expectedFilePath));
+
+ // the extraced files must contain either "temp/file.txt" or "file.txt" based on test inputs
+ FileAssert.Exists(expected);
+
+ // contents of the input file must equal the extracted file
+ FileAssert.AreEqual(testFilePath, expected);
+ }
+ }
}
}