Merge "AAPT2: Improve diff command"

This commit is contained in:
TreeHugger Robot
2016-06-30 06:29:53 +00:00
committed by Android (Google) Code Review
5 changed files with 166 additions and 45 deletions

View File

@@ -21,6 +21,7 @@
#include "io/File.h"
#include "util/Util.h"
#include <algorithm>
#include <androidfw/ResourceTypes.h>
#include <limits>
@@ -302,18 +303,42 @@ Attribute::Attribute(bool w, uint32_t t) :
mWeak = w;
}
template <typename T>
T* addPointer(T& val) {
return &val;
}
bool Attribute::equals(const Value* value) const {
const Attribute* other = valueCast<Attribute>(value);
if (!other) {
return false;
}
return this->typeMask == other->typeMask && this->minInt == other->minInt &&
this->maxInt == other->maxInt &&
std::equal(this->symbols.begin(), this->symbols.end(),
other->symbols.begin(),
[](const Symbol& a, const Symbol& b) -> bool {
return a.symbol.equals(&b.symbol) && a.value == b.value;
if (symbols.size() != other->symbols.size()) {
return false;
}
if (typeMask != other->typeMask || minInt != other->minInt || maxInt != other->maxInt) {
return false;
}
std::vector<const Symbol*> sortedA;
std::transform(symbols.begin(), symbols.end(),
std::back_inserter(sortedA), addPointer<const Symbol>);
std::sort(sortedA.begin(), sortedA.end(), [](const Symbol* a, const Symbol* b) -> bool {
return a->symbol.name < b->symbol.name;
});
std::vector<const Symbol*> sortedB;
std::transform(other->symbols.begin(), other->symbols.end(),
std::back_inserter(sortedB), addPointer<const Symbol>);
std::sort(sortedB.begin(), sortedB.end(), [](const Symbol* a, const Symbol* b) -> bool {
return a->symbol.name < b->symbol.name;
});
return std::equal(sortedA.begin(), sortedA.end(), sortedB.begin(),
[](const Symbol* a, const Symbol* b) -> bool {
return a->symbol.equals(&b->symbol) && a->value == b->value;
});
}
@@ -526,9 +551,28 @@ bool Style::equals(const Value* value) const {
(parent && other->parent && !parent.value().equals(&other->parent.value()))) {
return false;
}
return std::equal(entries.begin(), entries.end(), other->entries.begin(),
[](const Entry& a, const Entry& b) -> bool {
return a.key.equals(&b.key) && a.value->equals(b.value.get());
if (entries.size() != other->entries.size()) {
return false;
}
std::vector<const Entry*> sortedA;
std::transform(entries.begin(), entries.end(),
std::back_inserter(sortedA), addPointer<const Entry>);
std::sort(sortedA.begin(), sortedA.end(), [](const Entry* a, const Entry* b) -> bool {
return a->key.name < b->key.name;
});
std::vector<const Entry*> sortedB;
std::transform(other->entries.begin(), other->entries.end(),
std::back_inserter(sortedB), addPointer<const Entry>);
std::sort(sortedB.begin(), sortedB.end(), [](const Entry* a, const Entry* b) -> bool {
return a->key.name < b->key.name;
});
return std::equal(sortedA.begin(), sortedA.end(), sortedB.begin(),
[](const Entry* a, const Entry* b) -> bool {
return a->key.equals(&b->key) && a->value->equals(b->value.get());
});
}
@@ -563,6 +607,8 @@ void Style::print(std::ostream* out) const {
static ::std::ostream& operator<<(::std::ostream& out, const Style::Entry& value) {
if (value.key.name) {
out << value.key.name.value();
} else if (value.key.id) {
out << value.key.id.value();
} else {
out << "???";
}
@@ -577,6 +623,10 @@ bool Array::equals(const Value* value) const {
return false;
}
if (items.size() != other->items.size()) {
return false;
}
return std::equal(items.begin(), items.end(), other->items.begin(),
[](const std::unique_ptr<Item>& a, const std::unique_ptr<Item>& b) -> bool {
return a->equals(b.get());
@@ -605,6 +655,10 @@ bool Plural::equals(const Value* value) const {
return false;
}
if (values.size() != other->values.size()) {
return false;
}
return std::equal(values.begin(), values.end(), other->values.begin(),
[](const std::unique_ptr<Item>& a, const std::unique_ptr<Item>& b) -> bool {
if (bool(a) != bool(b)) {
@@ -659,6 +713,11 @@ bool Styleable::equals(const Value* value) const {
if (!other) {
return false;
}
if (entries.size() != other->entries.size()) {
return false;
}
return std::equal(entries.begin(), entries.end(), other->entries.begin(),
[](const Reference& a, const Reference& b) -> bool {
return a.equals(&b);

View File

@@ -16,6 +16,7 @@
#include "Flags.h"
#include "ResourceTable.h"
#include "ValueVisitor.h"
#include "io/ZipArchive.h"
#include "process/IResourceTableConsumer.h"
#include "process/SymbolTable.h"
@@ -385,6 +386,24 @@ static bool emitResourceTableDiff(IAaptContext* context, LoadedApk* apkA, Loaded
return diff;
}
class ZeroingReferenceVisitor : public ValueVisitor {
public:
using ValueVisitor::visit;
void visit(Reference* ref) override {
if (ref->name && ref->id) {
if (ref->id.value().packageId() == 0x7f) {
ref->id = {};
}
}
}
};
static void zeroOutAppReferences(ResourceTable* table) {
ZeroingReferenceVisitor visitor;
visitAllValuesInTable(table, &visitor);
}
int diff(const std::vector<StringPiece>& args) {
DiffContext context;
@@ -405,6 +424,10 @@ int diff(const std::vector<StringPiece>& args) {
return 1;
}
// Zero out Application IDs in references.
zeroOutAppReferences(apkA->getResourceTable());
zeroOutAppReferences(apkB->getResourceTable());
if (emitResourceTableDiff(&context, apkA.get(), apkB.get())) {
// We emitted a diff, so return 1 (failure).
return 1;

View File

@@ -20,6 +20,7 @@
#include "io/ZipArchive.h"
#include "process/IResourceTableConsumer.h"
#include "proto/ProtoSerialize.h"
#include "unflatten/BinaryResourceParser.h"
#include "util/Files.h"
#include "util/StringPiece.h"
@@ -44,18 +45,9 @@ void dumpCompiledFile(const pb::CompiledFile& pbFile, const void* data, size_t l
<< "Source: " << file->source << "\n";
}
void dumpCompiledTable(const pb::ResourceTable& pbTable, const Source& source,
IAaptContext* context) {
std::unique_ptr<ResourceTable> table = deserializeTableFromPb(pbTable, source,
context->getDiagnostics());
if (!table) {
return;
}
Debug::printTable(table.get());
}
void tryDumpFile(IAaptContext* context, const std::string& filePath) {
std::unique_ptr<ResourceTable> table;
std::string err;
std::unique_ptr<io::ZipFileCollection> zip = io::ZipFileCollection::create(filePath, &err);
if (zip) {
@@ -75,37 +67,62 @@ void tryDumpFile(IAaptContext* context, const std::string& filePath) {
return;
}
std::unique_ptr<ResourceTable> table = deserializeTableFromPb(
table = deserializeTableFromPb(
pbTable, Source(filePath), context->getDiagnostics());
if (table) {
DebugPrintTableOptions debugPrintTableOptions;
debugPrintTableOptions.showSources = true;
Debug::printTable(table.get(), debugPrintTableOptions);
if (!table) {
return;
}
}
if (!table) {
file = zip->findFile("resources.arsc");
if (file) {
std::unique_ptr<io::IData> data = file->openAsData();
if (!data) {
context->getDiagnostics()->error(DiagMessage(filePath)
<< "failed to open resources.arsc");
return;
}
table = util::make_unique<ResourceTable>();
BinaryResourceParser parser(context, table.get(), Source(filePath),
data->data(), data->size());
if (!parser.parse()) {
return;
}
}
}
return;
}
Maybe<android::FileMap> file = file::mmapPath(filePath, &err);
if (!file) {
context->getDiagnostics()->error(DiagMessage(filePath) << err);
return;
if (!table) {
Maybe<android::FileMap> file = file::mmapPath(filePath, &err);
if (!file) {
context->getDiagnostics()->error(DiagMessage(filePath) << err);
return;
}
android::FileMap* fileMap = &file.value();
// Try as a compiled table.
pb::ResourceTable pbTable;
if (pbTable.ParseFromArray(fileMap->getDataPtr(), fileMap->getDataLength())) {
table = deserializeTableFromPb(pbTable, Source(filePath), context->getDiagnostics());
}
if (!table) {
// Try as a compiled file.
CompiledFileInputStream input(fileMap->getDataPtr(), fileMap->getDataLength());
if (const pb::CompiledFile* pbFile = input.CompiledFile()) {
dumpCompiledFile(*pbFile, input.data(), input.size(), Source(filePath), context);
return;
}
}
}
android::FileMap* fileMap = &file.value();
// Try as a compiled table.
pb::ResourceTable pbTable;
if (pbTable.ParseFromArray(fileMap->getDataPtr(), fileMap->getDataLength())) {
dumpCompiledTable(pbTable, Source(filePath), context);
return;
}
// Try as a compiled file.
CompiledFileInputStream input(fileMap->getDataPtr(), fileMap->getDataLength());
if (const pb::CompiledFile* pbFile = input.CompiledFile()) {
dumpCompiledFile(*pbFile, input.data(), input.size(), Source(filePath), context);
return;
if (table) {
DebugPrintTableOptions debugPrintTableOptions;
debugPrintTableOptions.showSources = true;
Debug::printTable(table.get(), debugPrintTableOptions);
}
}

View File

@@ -61,7 +61,6 @@ public:
auto cacheIter = mMapping->find(id);
if (cacheIter != mMapping->end()) {
reference->name = cacheIter->second;
reference->id = {};
}
}
};

View File

@@ -88,6 +88,8 @@ public:
*/
const T& value() const;
T valueOrDefault(const T& def) const;
private:
template <typename U>
friend class Maybe;
@@ -262,6 +264,14 @@ const T& Maybe<T>::value() const {
return reinterpret_cast<const T&>(mStorage);
}
template <typename T>
T Maybe<T>::valueOrDefault(const T& def) const {
if (mNothing) {
return def;
}
return reinterpret_cast<const T&>(mStorage);
}
template <typename T>
void Maybe<T>::destroy() {
reinterpret_cast<T&>(mStorage).~T();
@@ -306,6 +316,19 @@ typename std::enable_if<
return !(a == b);
}
template <typename T, typename U>
typename std::enable_if<
has_lt_op<T, U>::value,
bool
>::type operator<(const Maybe<T>& a, const Maybe<U>& b) {
if (a && b) {
return a.value() < b.value();
} else if (!a && !b) {
return false;
}
return !a;
}
} // namespace aapt
#endif // AAPT_MAYBE_H