aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/singlejar/combiners.cc
diff options
context:
space:
mode:
authorGravatar cushon <cushon@google.com>2017-04-25 03:31:15 +0200
committerGravatar Vladimir Moskva <vladmos@google.com>2017-04-25 14:46:32 +0200
commitd054592cae57073f4bcfd49d542764d46b888c6e (patch)
tree77002a9acee159aa7f28e1b1f54f1ad3978e98fc /src/tools/singlejar/combiners.cc
parente996428e1c262d1ac8bf0812c8bf11a7f77f3de4 (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.cc44
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);
}