Index: include/llvm/Support/TarWriter.h =================================================================== --- include/llvm/Support/TarWriter.h +++ include/llvm/Support/TarWriter.h @@ -11,6 +11,7 @@ #define LLVM_SUPPORT_TAR_WRITER_H #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Support/Error.h" #include "llvm/Support/raw_ostream.h" @@ -26,6 +27,7 @@ TarWriter(int FD, StringRef BaseDir); raw_fd_ostream OS; std::string BaseDir; + StringSet<> Files; }; } Index: lib/Support/TarWriter.cpp =================================================================== --- lib/Support/TarWriter.cpp +++ lib/Support/TarWriter.cpp @@ -173,6 +173,10 @@ // Write Path and Data. std::string Fullpath = BaseDir + "/" + sys::path::convert_to_slash(Path); + // We do not want to include the same file more than once. + if (!Files.insert(Fullpath).second) + return; + StringRef Prefix; StringRef Name; if (splitUstar(Fullpath, Prefix, Name)) { Index: unittests/Support/TarWriterTest.cpp =================================================================== --- unittests/Support/TarWriterTest.cpp +++ unittests/Support/TarWriterTest.cpp @@ -120,4 +120,61 @@ StringRef Pax = StringRef((char *)(Buf.data() + 512), 512); EXPECT_TRUE(Pax.startswith("211 path=/" + std::string(200, 'x'))); } + +TEST_F(TarWriterTest, MultipleFiles) { + SmallString<128> Path; + std::error_code EC = + sys::fs::createTemporaryFile("TarWriterTest", "tar", Path); + EXPECT_FALSE((bool)EC); + + size_t SingleFileTarSize; + { + Expected> TarOrErr = TarWriter::create(Path, ""); + EXPECT_TRUE((bool)TarOrErr); + std::unique_ptr Tar = std::move(*TarOrErr); + Tar->append("FooPath", "foo"); + Tar.reset(); + + ErrorOr> MBOrErr = + MemoryBuffer::getFile(Path); + EXPECT_TRUE((bool)MBOrErr); + SingleFileTarSize = (*MBOrErr)->getBufferSize(); + } + + size_t MultipleFilesTarSize; + { + Expected> TarOrErr = TarWriter::create(Path, ""); + EXPECT_TRUE((bool)TarOrErr); + std::unique_ptr Tar = std::move(*TarOrErr); + Tar->append("FooPath", "foo"); + Tar->append("BarPath", "bar"); + Tar.reset(); + + ErrorOr> MBOrErr = + MemoryBuffer::getFile(Path); + EXPECT_TRUE((bool)MBOrErr); + MultipleFilesTarSize = (*MBOrErr)->getBufferSize(); + } + + size_t SameFilesTarSize; + { + Expected> TarOrErr = TarWriter::create(Path, ""); + EXPECT_TRUE((bool)TarOrErr); + std::unique_ptr Tar = std::move(*TarOrErr); + Tar->append("FooPath", "foo"); + Tar->append("FooPath", "bar"); + Tar.reset(); + + ErrorOr> MBOrErr = + MemoryBuffer::getFile(Path); + EXPECT_TRUE((bool)MBOrErr); + SameFilesTarSize = (*MBOrErr)->getBufferSize(); + } + + // Each new file triggers increasing of tar file. At the same time tar + // file should prevent using the same path for multiple files and hence + // should not add them to archive. We check this logic here. + EXPECT_TRUE(MultipleFilesTarSize > SingleFileTarSize); + EXPECT_TRUE(SameFilesTarSize == SingleFileTarSize); +} }