diff options
author | 2017-04-25 03:31:15 +0200 | |
---|---|---|
committer | 2017-04-25 14:46:32 +0200 | |
commit | d054592cae57073f4bcfd49d542764d46b888c6e (patch) | |
tree | 77002a9acee159aa7f28e1b1f54f1ad3978e98fc /src/tools/singlejar/combiners.cc | |
parent | e996428e1c262d1ac8bf0812c8bf11a7f77f3de4 (diff) |
Make singlejar's flag.xml merging idempotent
Previously running singlejar over the same flags.xml multiple
times would add start/end tags each time, resulting in repeated
top-level tags.
PiperOrigin-RevId: 154126431
Diffstat (limited to 'src/tools/singlejar/combiners.cc')
-rw-r--r-- | src/tools/singlejar/combiners.cc | 44 |
1 files changed, 37 insertions, 7 deletions
diff --git a/src/tools/singlejar/combiners.cc b/src/tools/singlejar/combiners.cc index ca2e224c7e..ce08549d40 100644 --- a/src/tools/singlejar/combiners.cc +++ b/src/tools/singlejar/combiners.cc @@ -122,20 +122,50 @@ XmlCombiner::~XmlCombiner() {} bool XmlCombiner::Merge(const CDH *cdh, const LH *lh) { if (!concatenator_.get()) { concatenator_.reset(new Concatenator(filename_, false)); - concatenator_->Append("<"); - concatenator_->Append(xml_tag_); - concatenator_->Append(">\n"); + concatenator_->Append(start_tag_); + concatenator_->Append("\n"); } - return concatenator_->Merge(cdh, lh); + // To ensure xml concatentation is idempotent, read in the entry being added + // and remove the start and end tags if they are present. + TransientBytes bytes_; + if (Z_NO_COMPRESSION == lh->compression_method()) { + bytes_.ReadEntryContents(lh); + } else if (Z_DEFLATED == lh->compression_method()) { + if (!inflater_.get()) { + inflater_.reset(new Inflater()); + } + bytes_.DecompressEntryContents(cdh, lh, inflater_.get()); + } else { + errx(2, "%s is neither stored nor deflated", filename_.c_str()); + } + uint32_t checksum; + char *buf = reinterpret_cast<char *>(malloc(bytes_.data_size())); + // TODO(b/37631490): optimize this to avoid copying the bytes twice + bytes_.CopyOut(reinterpret_cast<uint8_t *>(buf), &checksum); + int start_offset = 0; + if (strncmp(buf, start_tag_.c_str(), start_tag_.length()) == 0) { + start_offset = start_tag_.length(); + } + int end = bytes_.data_size(); + while (end >= end_tag_.length() && std::isspace(buf[end - 1])) end--; + if (strncmp(buf + end - end_tag_.length(), end_tag_.c_str(), + end_tag_.length()) == 0) { + end -= end_tag_.length(); + } else { + // Leave trailing whitespace alone if we didn't find a match. + end = bytes_.data_size(); + } + concatenator_->Append(buf + start_offset, end - start_offset); + free(buf); + return true; } void *XmlCombiner::OutputEntry(bool compress) { if (!concatenator_.get()) { return nullptr; } - concatenator_->Append("</"); - concatenator_->Append(xml_tag_); - concatenator_->Append(">\n"); + concatenator_->Append(end_tag_); + concatenator_->Append("\n"); return concatenator_->OutputEntry(compress); } |