diff --git a/BUILD.gn b/BUILD.gn index 532a37f..2a014a4 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -23,6 +23,7 @@ ohos_executable("restool") { "src/compression_parser.cpp", "src/config_parser.cpp", "src/factory_resource_compiler.cpp", + "src/factory_resource_packer.cpp", "src/file_entry.cpp", "src/file_manager.cpp", "src/generic_compiler.cpp", @@ -32,6 +33,8 @@ ohos_executable("restool") { "src/id_worker.cpp", "src/json_compiler.cpp", "src/key_parser.cpp", + "src/overlap_binary_file_packer.cpp", + "src/overlap_compiler.cpp", "src/reference_parser.cpp", "src/resconfig_parser.cpp", "src/resource_append.cpp", @@ -40,12 +43,12 @@ ohos_executable("restool") { "src/resource_item.cpp", "src/resource_merge.cpp", "src/resource_module.cpp", + "src/resource_overlap.cpp", "src/resource_pack.cpp", "src/resource_table.cpp", "src/resource_util.cpp", "src/restool.cpp", "src/select_compile_parse.cpp", - "src/task_handle.cpp", "src/thread_pool.cpp", "src/translatable_parser.cpp", ] diff --git a/include/binary_file_packer.h b/include/binary_file_packer.h index b01f9ee..38f9cf1 100644 --- a/include/binary_file_packer.h +++ b/include/binary_file_packer.h @@ -30,16 +30,22 @@ public: std::future CopyBinaryFileAsync(const std::vector &inputs); void StopCopy(); -private: - uint32_t CopyBinaryFile(const std::vector &inputs); - uint32_t CopyBinaryFile(const std::string &filePath, const std::string &fileType); - uint32_t CopyBinaryFileImpl(const std::string &src, const std::string &dst); - uint32_t CopySingleFile(const std::string &path, std::string &subPath); +protected: + virtual uint32_t CopyBinaryFile(const std::vector &inputs); + uint32_t CheckCopyResults(); + uint32_t CopyBinaryFile(const std::string &input); + virtual bool IsDuplicated(const std::unique_ptr &entry, std::string subPath); PackageParser packageParser_; std::string moduleName_; ThreadPool threadPool_; std::vector> copyResults_; std::atomic stopCopy_{false}; + std::mutex mutex_; + +private: + uint32_t CopyBinaryFile(const std::string &filePath, const std::string &fileType); + uint32_t CopyBinaryFileImpl(const std::string &src, const std::string &dst); + uint32_t CopySingleFile(const std::string &path, std::string &subPath); }; } // namespace Restool } // namespace Global diff --git a/include/cmd_parser.h b/include/cmd_parser.h index 7f3772c..83ad3d2 100644 --- a/include/cmd_parser.h +++ b/include/cmd_parser.h @@ -57,6 +57,7 @@ public: bool IsTargetConfig() const; const std::vector &GetSysIdDefinedPaths() const; const std::string &GetCompressionPath() const; + bool IsOverlap() const; private: void InitCommand(); diff --git a/include/factory_resource_compiler.h b/include/factory_resource_compiler.h index 638a429..7a55736 100644 --- a/include/factory_resource_compiler.h +++ b/include/factory_resource_compiler.h @@ -24,7 +24,7 @@ namespace Global { namespace Restool { class FactoryResourceCompiler { public: - static std::unique_ptr CreateCompiler(ResType type, const std::string &output); + static std::unique_ptr CreateCompiler(ResType type, const std::string &output, bool isHap); static std::unique_ptr CreateCompilerForAppend(ResType type, const std::string &output); }; } diff --git a/src/task_handle.cpp b/include/factory_resource_packer.h similarity index 67% rename from src/task_handle.cpp rename to include/factory_resource_packer.h index 9067917..c54ab28 100644 --- a/src/task_handle.cpp +++ b/include/factory_resource_packer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,17 +13,20 @@ * limitations under the License. */ -#include "task_handle.h" +#ifndef OHOS_RESTOOL_FACTORY_RESOURCE_PACKER_H +#define OHOS_RESTOOL_FACTORY_RESOURCE_PACKER_H + +#include #include "resource_pack.h" namespace OHOS { namespace Global { namespace Restool { -uint32_t TaskHandle::HandlePackage(const PackageParser &packageParser) -{ - ResourcePack pack(packageParser); - return pack.Package(); +class FactoryResourcePacker { +public: + static std::unique_ptr CreatePacker(PackType type, const PackageParser &packageParser); +}; } } } -} \ No newline at end of file +#endif \ No newline at end of file diff --git a/include/file_manager.h b/include/file_manager.h index 5d19a4a..655dfdf 100644 --- a/include/file_manager.h +++ b/include/file_manager.h @@ -37,6 +37,7 @@ public: }; uint32_t MergeResourceItem(const std::map> &resourceInfos); bool ScaleIcons(const std::string &output, const std::map> &iconMap); + void SetScanHap(bool state); private: uint32_t ScanModule(const std::string &input, const std::string &output); @@ -47,6 +48,7 @@ private: // id, resource items std::map> items_; std::string moduleName_; + bool scanHap_ = false; }; } } diff --git a/include/generic_compiler.h b/include/generic_compiler.h index 1476143..d5a6af3 100644 --- a/include/generic_compiler.h +++ b/include/generic_compiler.h @@ -24,17 +24,19 @@ namespace Global { namespace Restool { class GenericCompiler : public IResourceCompiler { public: - GenericCompiler(ResType type, const std::string &output); + GenericCompiler(ResType type, const std::string &output, bool isOverlap = false); virtual ~GenericCompiler(); + protected: + std::string GetOutputFilePath(const FileInfo &fileInfo) const; + virtual bool IsIgnore(const FileInfo &fileInfo); uint32_t CompileSingleFile(const FileInfo &fileInfo) override; uint32_t CompileFiles(const std::vector &fileInfos) override; bool PostMediaFile(const FileInfo &fileInfo, const std::string &output); -private: - std::string GetOutputFilePath(const FileInfo &fileInfo) const; - bool IsIgnore(const FileInfo &fileInfo); - bool CopyMediaFile(const FileInfo &fileInfo, std::string &output); std::mutex mutex_; + +private: + bool CopyMediaFile(const FileInfo &fileInfo, std::string &output); }; } } diff --git a/include/i_resource_compiler.h b/include/i_resource_compiler.h index ad7c69b..be9842b 100644 --- a/include/i_resource_compiler.h +++ b/include/i_resource_compiler.h @@ -25,7 +25,7 @@ namespace Global { namespace Restool { class IResourceCompiler { public: - IResourceCompiler(ResType type, const std::string &output); + IResourceCompiler(ResType type, const std::string &output, bool isOverlap = false); virtual ~IResourceCompiler(); uint32_t Compile(const std::vector &directoryInfos); const std::map> &GetResult() const; @@ -42,6 +42,7 @@ protected: ResType type_; std::string output_; std::string moduleName_; + bool isOverlap_; // id, resource items std::map> resourceInfos_; diff --git a/include/id_worker.h b/include/id_worker.h index d080ac0..3fe29e2 100644 --- a/include/id_worker.h +++ b/include/id_worker.h @@ -19,6 +19,7 @@ #include #include "id_defined_parser.h" #include "resource_data.h" +#include "resource_item.h" #include "resource_util.h" #include "singleton.h" @@ -32,6 +33,7 @@ public: std::vector GetHeaderId() const; int64_t GetId(ResType resType, const std::string &name) const; int64_t GetSystemId(ResType resType, const std::string &name) const; + void LoadIdFromHap(const std::map> &items); private: int64_t GenerateAppId(ResType resType, const std::string &name); diff --git a/include/json_compiler.h b/include/json_compiler.h index f14ad9f..5b6d77f 100644 --- a/include/json_compiler.h +++ b/include/json_compiler.h @@ -26,7 +26,7 @@ namespace Global { namespace Restool { class JsonCompiler : public IResourceCompiler { public: - JsonCompiler(ResType type, const std::string &output); + JsonCompiler(ResType type, const std::string &output, bool isOverlap = false); virtual ~JsonCompiler(); protected: uint32_t CompileSingleFile(const FileInfo &fileInfo) override; diff --git a/include/overlap_binary_file_packer.h b/include/overlap_binary_file_packer.h new file mode 100644 index 0000000..8a99b87 --- /dev/null +++ b/include/overlap_binary_file_packer.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_RESTOOL_OVERLAP_BINARY_FILE_PACKER_H +#define OHOS_RESTOOL_OVERLAP_BINARY_FILE_PACKER_H + +#include "binary_file_packer.h" + +namespace OHOS { +namespace Global { +namespace Restool { +class OverlapBinaryFilePacker : public BinaryFilePacker { +public: + OverlapBinaryFilePacker(const PackageParser &packageParser, const std::string &moduleName); + +protected: + uint32_t CopyBinaryFile(const std::vector &inputs); + bool IsDuplicated(const std::unique_ptr &entry, std::string subPath); +}; +} +} +} +#endif diff --git a/include/task_handle.h b/include/overlap_compiler.h similarity index 64% rename from include/task_handle.h rename to include/overlap_compiler.h index 72daadf..63b3ec1 100644 --- a/include/task_handle.h +++ b/include/overlap_compiler.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,19 +13,20 @@ * limitations under the License. */ -#ifndef OHOS_RESTOOL_TASK_HANDLE_H -#define OHOS_RESTOOL_TASK_HANDLE_H +#ifndef OHOS_RESTOOL_OVERLAP_COMPILER_H +#define OHOS_RESTOOL_OVERLAP_COMPILER_H -#include "cmd_parser.h" +#include "generic_compiler.h" namespace OHOS { namespace Global { namespace Restool { -class TaskHandle { +class OverlapCompiler : public GenericCompiler { public: - TaskHandle() {}; - ~TaskHandle() {}; - uint32_t HandlePackage(const PackageParser &packageParser); + OverlapCompiler(ResType type, const std::string &output, bool isOverlap = false); + +protected: + bool IsIgnore(const FileInfo &fileInfo); }; } } diff --git a/include/resource_data.h b/include/resource_data.h index c7c34c6..f51d640 100644 --- a/include/resource_data.h +++ b/include/resource_data.h @@ -49,9 +49,10 @@ const static std::string SOLUTIONS_ARROW = "> "; const static std::string LONG_PATH_HEAD = "\\\\?\\"; const static int32_t VERSION_MAX_LEN = 128; const static int32_t INT_TO_BYTES = sizeof(uint32_t); -static const int8_t RESTOOL_VERSION[VERSION_MAX_LEN] = { "Restool 5.1.0.001" }; +static const int8_t RESTOOL_VERSION[VERSION_MAX_LEN] = { "Restool 5.1.0.002" }; const static int32_t TAG_LEN = 4; static std::set g_resourceSet; +static std::set g_hapResourceSet; const static int8_t THREAD_POOL_SIZE = 2; const static int8_t INVALID_ID = -1; @@ -92,6 +93,11 @@ enum class ResType { INVALID_RES_TYPE = -1, }; +enum class PackType { + NORMAL = 1, + OVERLAP +}; + enum class OrientationType { VERTICAL = 0, HORIZONTAL = 1, diff --git a/include/resource_item.h b/include/resource_item.h index e6699e9..870f3ff 100644 --- a/include/resource_item.h +++ b/include/resource_item.h @@ -34,6 +34,7 @@ public: void SetFilePath(const std::string &filePath); void SetLimitKey(const std::string &limitKey); void SetName(const std::string &name); + void MarkCoverable(); const int8_t *GetData() const; uint32_t GetDataLength() const; @@ -42,6 +43,7 @@ public: const std::vector &GetKeyParam() const; const std::string &GetFilePath() const; const std::string &GetLimitKey() const; + bool IsCoverable() const; ResourceItem &operator=(const ResourceItem &other); private: @@ -54,6 +56,7 @@ private: ResType type_; std::string filePath_; std::string limitKey_; + bool coverable_ = false; }; } } diff --git a/include/resource_merge.h b/include/resource_merge.h index a58e1a5..7a2c3a0 100644 --- a/include/resource_merge.h +++ b/include/resource_merge.h @@ -20,6 +20,7 @@ #include #include "config_parser.h" #include "restool_errors.h" +#include "cmd_parser.h" namespace OHOS { namespace Global { @@ -28,7 +29,7 @@ class ResourceMerge { public: ResourceMerge(); virtual ~ResourceMerge(); - uint32_t Init(); + uint32_t Init(const PackageParser &packageParser = CmdParser::GetInstance().GetCmdParser()); const std::vector &GetInputs() const; private: std::vector inputsOrder_; diff --git a/include/resource_module.h b/include/resource_module.h index 3e13805..0839466 100644 --- a/include/resource_module.h +++ b/include/resource_module.h @@ -27,7 +27,7 @@ class ResourceModule { public: ResourceModule(const std::string &modulePath, const std::string &moduleOutput, const std::string &moduleName); virtual ~ResourceModule() {}; - uint32_t ScanResource(); + uint32_t ScanResource(bool isHap = false); const std::map> &GetOwner() const; const std::map> &GetScanDirectorys() const; static uint32_t MergeResourceItem(std::map> &alls, diff --git a/include/resource_overlap.h b/include/resource_overlap.h new file mode 100644 index 0000000..b0bba33 --- /dev/null +++ b/include/resource_overlap.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_RESTOOL_RESOURCE_OVERLAP_H +#define OHOS_RESTOOL_RESOURCE_OVERLAP_H + +#include "cmd_parser.h" +#include "resource_pack.h" + +namespace OHOS { +namespace Global { +namespace Restool { +class ResourceOverlap : public ResourcePack { +public: + ResourceOverlap(const PackageParser &packageParser); + uint32_t Pack(); + +protected: + uint32_t ScanResources(const std::vector &inputs, const std::string &output); + +private: + uint32_t LoadHapResources(); +}; +} +} +} +#endif \ No newline at end of file diff --git a/include/resource_pack.h b/include/resource_pack.h index 9f566fe..87a82ed 100644 --- a/include/resource_pack.h +++ b/include/resource_pack.h @@ -32,9 +32,17 @@ public: explicit ResourcePack(const PackageParser &packageParser); virtual ~ResourcePack() = default; uint32_t Package(); + virtual uint32_t Pack(); + +protected: + uint32_t InitResourcePack(); + uint32_t PackResources(const ResourceMerge &resourceMerge); + virtual uint32_t ScanResources(const std::vector &inputs, const std::string &output); + PackageParser packageParser_; + std::string moduleName_; + ConfigParser configJson_; private: - uint32_t Init(); uint32_t InitModule(); void InitHeaderCreater(); uint32_t InitOutput() const; @@ -45,12 +53,9 @@ private: uint32_t GenerateCplusHeader(const std::string &headerPath) const; uint32_t GenerateJsHeader(const std::string &headerPath) const; uint32_t GenerateConfigJson(); - uint32_t ScanResources(const std::vector &inputs, const std::string &output); - uint32_t PackNormal(); uint32_t PackPreview(); uint32_t PackAppend(); uint32_t PackCombine(); - uint32_t PackQualifierResources(const ResourceMerge &resourceMerge); uint32_t HandleFeature(); uint32_t FindResourceItems(const std::map> &resInfoLocal, std::vector &items, int64_t id) const; @@ -60,11 +65,9 @@ private: void CheckConfigJson(); void CheckConfigJsonForCombine(ResourceAppend &resourceAppend); bool CopyIcon(std::string &dataPath, const std::string &idName, std::string &fileName) const; - PackageParser packageParser_; - std::string moduleName_; using HeaderCreater = std::function; std::map headerCreaters_; - ConfigParser configJson_; + PackType packType_ = PackType::NORMAL; }; } } diff --git a/src/binary_file_packer.cpp b/src/binary_file_packer.cpp index 75cf11b..dc4c3a1 100644 --- a/src/binary_file_packer.cpp +++ b/src/binary_file_packer.cpp @@ -41,7 +41,7 @@ void BinaryFilePacker::StopCopy() std::future BinaryFilePacker::CopyBinaryFileAsync(const std::vector &inputs) { - auto func = [this](const std::vector &inputs) { return this->CopyBinaryFile(inputs); }; + auto func = [this](const vector &inputs) { return this->CopyBinaryFile(inputs); }; std::future res = threadPool_.Enqueue(func, inputs); return res; } @@ -49,26 +49,25 @@ std::future BinaryFilePacker::CopyBinaryFileAsync(const std::vector &inputs) { for (const auto &input : inputs) { - string rawfilePath = FileEntry::FilePath(input).Append(RAW_FILE_DIR).GetPath(); - if (CopyBinaryFile(rawfilePath, RAW_FILE_DIR) == RESTOOL_ERROR) { - cerr << "Error: copy raw file failed." << NEW_LINE_PATH << rawfilePath << endl; - return RESTOOL_ERROR; - } - string resfilePath = FileEntry::FilePath(input).Append(RES_FILE_DIR).GetPath(); - if (CopyBinaryFile(resfilePath, RES_FILE_DIR) == RESTOOL_ERROR) { - cerr << "Error: copy res file failed." << NEW_LINE_PATH << resfilePath << endl; - return RESTOOL_ERROR; - } + CopyBinaryFile(input); } - for (auto &res : copyResults_) { - if (stopCopy_.load()) { - cout << "Info: CopyBinaryFile: stop copy binary file." << endl; - return RESTOOL_ERROR; - } - uint32_t ret = res.get(); - if (ret != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; - } + if (CheckCopyResults() != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + return RESTOOL_SUCCESS; +} + +uint32_t BinaryFilePacker::CopyBinaryFile(const string &input) +{ + string rawfilePath = FileEntry::FilePath(input).Append(RAW_FILE_DIR).GetPath(); + if (CopyBinaryFile(rawfilePath, RAW_FILE_DIR) == RESTOOL_ERROR) { + cerr << "Error: copy raw file failed." << NEW_LINE_PATH << rawfilePath << endl; + return RESTOOL_ERROR; + } + string resfilePath = FileEntry::FilePath(input).Append(RES_FILE_DIR).GetPath(); + if (CopyBinaryFile(resfilePath, RES_FILE_DIR) == RESTOOL_ERROR) { + cerr << "Error: copy res file failed." << NEW_LINE_PATH << resfilePath << endl; + return RESTOOL_ERROR; } return RESTOOL_SUCCESS; } @@ -116,14 +115,15 @@ uint32_t BinaryFilePacker::CopyBinaryFileImpl(const string &src, const string &d continue; } - if (!g_resourceSet.emplace(subPath).second) { - cerr << "Warning: '" << entry->GetFilePath().GetPath() << "' is defined repeatedly." << endl; + if (IsDuplicated(entry, subPath)) { continue; } + if (stopCopy_.load()) { cout << "Info: CopyBinaryFileImpl: stop copy binary file." << endl; return RESTOOL_ERROR; } + string path = entry->GetFilePath().GetPath(); auto copyFunc = [this](const string path, string subPath) { return this->CopySingleFile(path, subPath); }; std::future res = threadPool_.Enqueue(copyFunc, path, subPath); @@ -132,6 +132,18 @@ uint32_t BinaryFilePacker::CopyBinaryFileImpl(const string &src, const string &d return RESTOOL_SUCCESS; } +bool BinaryFilePacker::IsDuplicated(const unique_ptr &entry, string subPath) +{ + lock_guard lock(mutex_); + if (g_hapResourceSet.count(subPath)) { + g_hapResourceSet.erase(subPath); + } else if (!g_resourceSet.emplace(subPath).second) { + cerr << "Warning: '" << entry->GetFilePath().GetPath() << "' is defined repeatedly." << endl; + return true; + } + return false; +} + uint32_t BinaryFilePacker::CopySingleFile(const std::string &path, std::string &subPath) { if (moduleName_ == "har" || CompressionParser::GetCompressionParser()->GetDefaultCompress()) { @@ -147,6 +159,22 @@ uint32_t BinaryFilePacker::CopySingleFile(const std::string &path, std::string & } return RESTOOL_SUCCESS; } + +uint32_t BinaryFilePacker::CheckCopyResults() +{ + for (auto &res : copyResults_) { + if (stopCopy_.load()) { + cout << "Info: CopyBinaryFile: stop copy binary file." << endl; + return RESTOOL_ERROR; + } + uint32_t ret = res.get(); + if (ret != RESTOOL_SUCCESS) { + cerr << "Error: copy binary file failed." << endl; + return RESTOOL_ERROR; + } + } + return RESTOOL_SUCCESS; +} } // namespace Restool } // namespace Global } // namespace OHOS diff --git a/src/cmd_parser.cpp b/src/cmd_parser.cpp index 8c09d3a..d3888b7 100644 --- a/src/cmd_parser.cpp +++ b/src/cmd_parser.cpp @@ -18,6 +18,7 @@ #include "resconfig_parser.h" #include "resource_util.h" #include "select_compile_parse.h" +#include "file_entry.h" namespace OHOS { namespace Global { @@ -134,7 +135,13 @@ uint32_t PackageParser::AddInput(const string& argValue) if (!IsAscii(inputPath)) { return RESTOOL_ERROR; } - inputs_.push_back(inputPath); + + string indexPath = ResourceUtil::GetMainPath(inputPath).Append(RESOURCE_INDEX_FILE).GetPath(); + if (ResourceUtil::FileExist(indexPath)) { + inputs_.emplace(inputs_.begin(), inputPath); + } else { + inputs_.push_back(inputPath); + } return RESTOOL_SUCCESS; } @@ -443,6 +450,15 @@ const std::string &PackageParser::GetCompressionPath() const return compressionPath_; } +bool PackageParser::IsOverlap() const +{ + string indexPath = ResourceUtil::GetMainPath(inputs_[0]).Append(RESOURCE_INDEX_FILE).GetPath(); + if (ResourceUtil::FileExist(indexPath)) { + return true; + } + return false; +} + void PackageParser::InitCommand() { using namespace placeholders; diff --git a/src/factory_resource_compiler.cpp b/src/factory_resource_compiler.cpp index e4e8fc5..3cd1d2b 100644 --- a/src/factory_resource_compiler.cpp +++ b/src/factory_resource_compiler.cpp @@ -17,17 +17,21 @@ #include "append_compiler.h" #include "generic_compiler.h" #include "json_compiler.h" +#include "overlap_compiler.h" namespace OHOS { namespace Global { namespace Restool { using namespace std; -unique_ptr FactoryResourceCompiler::CreateCompiler(ResType type, const string &output) +unique_ptr FactoryResourceCompiler::CreateCompiler(ResType type, + const string &output, bool isOverlap) { if (type == ResType::ELEMENT) { - return make_unique(type, output); + return make_unique(type, output, isOverlap); + } else if (isOverlap) { + return make_unique(type, output, isOverlap); } else { - return make_unique(type, output); + return make_unique(type, output, isOverlap); } } diff --git a/src/factory_resource_packer.cpp b/src/factory_resource_packer.cpp new file mode 100644 index 0000000..9204709 --- /dev/null +++ b/src/factory_resource_packer.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "factory_resource_packer.h" +#include "resource_overlap.h" + +namespace OHOS { +namespace Global { +namespace Restool { +using namespace std; + +unique_ptr FactoryResourcePacker::CreatePacker(PackType type, const PackageParser &packageParser) +{ + if (type == PackType::NORMAL) { + return make_unique(packageParser); + } else if (type == PackType::OVERLAP) { + return make_unique(packageParser); + } else { + cerr << "Error: FactoryResourcePacker: Unknown input PackType." << endl; + return nullptr; + } +} +} +} +} \ No newline at end of file diff --git a/src/file_manager.cpp b/src/file_manager.cpp index 125d01a..1141c35 100644 --- a/src/file_manager.cpp +++ b/src/file_manager.cpp @@ -42,7 +42,7 @@ uint32_t FileManager::ScanModules(const vector &inputs, const string &ou if (!noBaseResource.empty()) { ResourceUtil::PrintWarningMsg(noBaseResource); } - return isHar ? RESTOOL_SUCCESS : ParseReference(output); + return isHar || scanHap_ ? RESTOOL_SUCCESS : ParseReference(output); } uint32_t FileManager::MergeResourceItem(const map> &resourceInfos) @@ -54,7 +54,7 @@ uint32_t FileManager::MergeResourceItem(const map> uint32_t FileManager::ScanModule(const string &input, const string &output) { ResourceModule resourceModule(input, output, moduleName_); - if (resourceModule.ScanResource() != RESTOOL_SUCCESS) { + if (resourceModule.ScanResource(scanHap_) != RESTOOL_SUCCESS) { return RESTOOL_ERROR; } MergeResourceItem(resourceModule.GetOwner()); @@ -120,6 +120,11 @@ bool FileManager::ScaleIcons(const string &output, const std::map lock(mutex_); + lock_guard lock(mutex_); string output = GetOutputFilePath(fileInfo); - if (!g_resourceSet.emplace(output).second) { + if (g_hapResourceSet.count(output)) { + g_hapResourceSet.erase(output); + } else if (!g_resourceSet.emplace(output).second) { cerr << "Warning: '" << fileInfo.filePath << "' is defined repeatedly." << endl; return true; } diff --git a/src/i_resource_compiler.cpp b/src/i_resource_compiler.cpp index e964fe3..ac75925 100644 --- a/src/i_resource_compiler.cpp +++ b/src/i_resource_compiler.cpp @@ -25,8 +25,8 @@ namespace OHOS { namespace Global { namespace Restool { using namespace std; -IResourceCompiler::IResourceCompiler(ResType type, const string &output) - :type_(type), output_(output) +IResourceCompiler::IResourceCompiler(ResType type, const string &output, bool isOverlap) + :type_(type), output_(output), isOverlap_(isOverlap) { } @@ -152,7 +152,6 @@ bool IResourceCompiler::MergeResourceItem(const ResourceItem &resourceItem) cerr << "but declare again." << NEW_LINE_PATH << resourceItem.GetFilePath() << endl; return false; } - nameInfos_[make_pair(resourceItem.GetResType(), idName)].push_back(resourceItem); return true; } diff --git a/src/id_worker.cpp b/src/id_worker.cpp index af0e76e..c97031c 100644 --- a/src/id_worker.cpp +++ b/src/id_worker.cpp @@ -84,6 +84,21 @@ int64_t IdWorker::GetSystemId(ResType resType, const string &name) const return result->second.id; } +void IdWorker::LoadIdFromHap(const map> &items) +{ + int64_t minId = 0xffffffff; + int64_t maxId = 0x01000000; + for (const auto &item : items) { + for (const auto &resourceItem : item.second) { + ids_.emplace(make_pair(resourceItem.GetResType(), resourceItem.GetName()), item.first); + } + minId = min(minId, item.first); + maxId = max(maxId, item.first); + } + maxId_ = GetMaxId(minId); + appId_ = maxId + 1; +} + int64_t IdWorker::GenerateAppId(ResType resType, const string &name) { auto result = ids_.find(make_pair(resType, name)); diff --git a/src/json_compiler.cpp b/src/json_compiler.cpp index c400815..046c266 100644 --- a/src/json_compiler.cpp +++ b/src/json_compiler.cpp @@ -31,8 +31,8 @@ const string TAG_QUANTITY = "quantity"; const vector QUANTITY_ATTRS = { "zero", "one", "two", "few", "many", "other" }; const vector TRANSLATION_TYPE = { "string", "strarray", "plural" }; -JsonCompiler::JsonCompiler(ResType type, const string &output) - : IResourceCompiler(type, output), isBaseString_(false), root_(nullptr) +JsonCompiler::JsonCompiler(ResType type, const string &output, bool isOverlap) + : IResourceCompiler(type, output, isOverlap), isBaseString_(false), root_(nullptr) { InitParser(); } @@ -157,6 +157,10 @@ bool JsonCompiler::ParseJsonObjectLevel(cJSON *objectNode, const FileInfo &fileI return false; } + if (isOverlap_) { + resourceItem.MarkCoverable(); + } + return MergeResourceItem(resourceItem); } diff --git a/src/overlap_binary_file_packer.cpp b/src/overlap_binary_file_packer.cpp new file mode 100644 index 0000000..e6f84e6 --- /dev/null +++ b/src/overlap_binary_file_packer.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "overlap_binary_file_packer.h" + +namespace OHOS { +namespace Global { +namespace Restool { +using namespace std; + +OverlapBinaryFilePacker::OverlapBinaryFilePacker(const PackageParser &packageParser, const std::string &moduleName) + : BinaryFilePacker(packageParser, moduleName) +{ +} + +uint32_t OverlapBinaryFilePacker::CopyBinaryFile(const vector &inputs) +{ + string hapPath = inputs[0]; + BinaryFilePacker::CopyBinaryFile(hapPath); + if (CheckCopyResults() != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + + vector resource(inputs.begin() + 1, inputs.end()); + BinaryFilePacker rawFilePacker(packageParser_, moduleName_); + std::future copyFuture = rawFilePacker.CopyBinaryFileAsync(resource); + if (copyFuture.get() != RESTOOL_SUCCESS) { + cerr << "Error: copy binary file failed." << endl; + return RESTOOL_ERROR; + } + return RESTOOL_SUCCESS; +} + +bool OverlapBinaryFilePacker::IsDuplicated(const unique_ptr &entry, string subPath) +{ + lock_guard lock(mutex_); + if (!g_hapResourceSet.emplace(subPath).second || !g_resourceSet.emplace(subPath).second) { + cerr << "Warning: '" << entry->GetFilePath().GetPath() << "' is defined repeatedly in hap." << endl; + return true; + } + return false; +} +} +} +} \ No newline at end of file diff --git a/src/overlap_compiler.cpp b/src/overlap_compiler.cpp new file mode 100644 index 0000000..6ed0c64 --- /dev/null +++ b/src/overlap_compiler.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "overlap_compiler.h" +#include + +namespace OHOS { +namespace Global { +namespace Restool { +using namespace std; + +OverlapCompiler::OverlapCompiler(ResType type, const std::string &output, bool isOverlap) + : GenericCompiler(type, output, isOverlap) +{ +} + +bool OverlapCompiler::IsIgnore(const FileInfo &fileInfo) +{ + lock_guard lock(mutex_); + string output = GetOutputFilePath(fileInfo); + if (!g_hapResourceSet.emplace(output).second || !g_resourceSet.emplace(output).second) { + cerr << "Warning: '" << fileInfo.filePath << "' is defined repeatedly." << endl; + return true; + } + return false; +} +} +} +} \ No newline at end of file diff --git a/src/resource_item.cpp b/src/resource_item.cpp index e45c1cd..f059c3a 100644 --- a/src/resource_item.cpp +++ b/src/resource_item.cpp @@ -85,6 +85,11 @@ void ResourceItem::SetName(const string &name) name_ = name; } +void ResourceItem::MarkCoverable() +{ + coverable_ = true; +} + const int8_t *ResourceItem::GetData() const { return data_; @@ -120,6 +125,11 @@ const string &ResourceItem::GetLimitKey() const return limitKey_; } +bool ResourceItem::IsCoverable() const +{ + return coverable_; +} + ResourceItem &ResourceItem::operator=(const ResourceItem &other) { if (this == &other) { @@ -147,6 +157,7 @@ void ResourceItem::CopyFrom(const ResourceItem &other) dataLen_ = other.dataLen_; filePath_ = other.filePath_; limitKey_ = other.limitKey_; + coverable_ = other.coverable_; if (!SetData(other.data_, other.dataLen_)) { ReleaseData(); } diff --git a/src/resource_merge.cpp b/src/resource_merge.cpp index 884e9fb..eb6336b 100644 --- a/src/resource_merge.cpp +++ b/src/resource_merge.cpp @@ -14,7 +14,6 @@ */ #include "resource_merge.h" -#include "cmd_parser.h" #include "file_entry.h" namespace OHOS { @@ -37,19 +36,24 @@ ResourceMerge::~ResourceMerge() { } -uint32_t ResourceMerge::Init() +uint32_t ResourceMerge::Init(const PackageParser &packageParser) { - auto &cmdParser = CmdParser::GetInstance().GetCmdParser(); - const vector &inputs = cmdParser.GetInputs(); - if (cmdParser.IsFileList()) { + const vector &inputs = packageParser.GetInputs(); + if (packageParser.IsFileList()) { inputsOrder_ = inputs; return RESTOOL_SUCCESS; } map> inputTypes; + string hapDir = ""; for (auto it = inputs.crbegin(); it != inputs.crend(); it++) { string configPath = ResourceUtil::GetMainPath(*it).Append(ConfigParser::GetConfigName()).GetPath(); string resourceDir = FileEntry::FilePath(*it).GetPath(); + string indexPath = ResourceUtil::GetMainPath(*it).Append(RESOURCE_INDEX_FILE).GetPath(); + if (ResourceUtil::FileExist(indexPath)) { + hapDir = resourceDir; + continue; + } ConfigParser::ModuleType moduleType = ConfigParser::ModuleType::NONE; if (!ResourceUtil::FileExist(configPath)) { inputTypes[moduleType].push_back(resourceDir); @@ -69,6 +73,9 @@ uint32_t ResourceMerge::Init() } inputsOrder_.insert(inputsOrder_.end(), inputTypes[type].begin(), inputTypes[type].end()); } + if (hapDir != "") { + inputsOrder_.insert(inputsOrder_.begin(), hapDir); + } return RESTOOL_SUCCESS; } diff --git a/src/resource_module.cpp b/src/resource_module.cpp index 726c5d9..796fddb 100644 --- a/src/resource_module.cpp +++ b/src/resource_module.cpp @@ -33,7 +33,7 @@ ResourceModule::ResourceModule(const string &modulePath, const string &moduleOut { } -uint32_t ResourceModule::ScanResource() +uint32_t ResourceModule::ScanResource(bool isHap) { if (!ResourceUtil::FileExist(modulePath_)) { return RESTOOL_SUCCESS; @@ -54,7 +54,7 @@ uint32_t ResourceModule::ScanResource() } unique_ptr resourceCompiler = - FactoryResourceCompiler::CreateCompiler(type, moduleOutput_); + FactoryResourceCompiler::CreateCompiler(type, moduleOutput_, isHap); resourceCompiler->SetModuleName(moduleName_); if (resourceCompiler->Compile(item->second) != RESTOOL_SUCCESS) { return RESTOOL_ERROR; @@ -91,6 +91,10 @@ uint32_t ResourceModule::MergeResourceItem(map> &a result.first->second.push_back(resourceItem); continue; } + if (ret->IsCoverable()) { // overlap the hap resource by new resource + *ret = resourceItem; + continue; + } if (tipError) { cerr << "Error: '"<< resourceItem.GetName() <<"' conflict, first declared."; cerr << NEW_LINE_PATH << ret->GetFilePath() << endl; diff --git a/src/resource_overlap.cpp b/src/resource_overlap.cpp new file mode 100644 index 0000000..108b2b2 --- /dev/null +++ b/src/resource_overlap.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "resource_overlap.h" +#include "overlap_binary_file_packer.h" +#include "file_manager.h" +#include "resource_table.h" +#include "id_worker.h" + +namespace OHOS { +namespace Global { +namespace Restool { +using namespace std; + +ResourceOverlap::ResourceOverlap(const PackageParser &packageParser) : ResourcePack(packageParser) +{ +} + +uint32_t ResourceOverlap::Pack() +{ + cout << "Info: Pack: overlap pack mode" << endl; + + if (InitResourcePack() != RESTOOL_SUCCESS) { + cerr << "Error: ResourcePack init failed." << endl; + return RESTOOL_ERROR; + } + + ResourceMerge resourceMerge; + if (resourceMerge.Init(packageParser_) != RESTOOL_SUCCESS) { + cerr << "Error: resourceMerge init failed." << endl; + return RESTOOL_ERROR; + } + + OverlapBinaryFilePacker rawFilePacker(packageParser_, moduleName_); + future copyFuture = rawFilePacker.CopyBinaryFileAsync(resourceMerge.GetInputs()); + + if (LoadHapResources() != RESTOOL_SUCCESS) { + rawFilePacker.StopCopy(); + cerr << "Error: load hap resources failed." << endl; + return RESTOOL_ERROR; + } + + if (PackResources(resourceMerge) != RESTOOL_SUCCESS) { + rawFilePacker.StopCopy(); + cerr << "Error: pack resources failed." << endl; + return RESTOOL_ERROR; + } + + if (copyFuture.get() != RESTOOL_SUCCESS) { + cerr << "Error: copy binary file failed." << endl; + return RESTOOL_ERROR; + } + return RESTOOL_SUCCESS; +} + +uint32_t ResourceOverlap::ScanResources(const std::vector &inputs, const std::string &output) +{ + auto &fileManager = FileManager::GetInstance(); + fileManager.SetModuleName(moduleName_); + vector hapResInput{inputs[0]}; + if (fileManager.ScanModules(hapResInput, output, configJson_.IsHar()) != RESTOOL_SUCCESS) { + cerr << "Error: scan hap error" << endl; + return RESTOOL_ERROR; + } + fileManager.SetScanHap(false); + + vector resInputs(inputs.begin() + 1, inputs.end()); + if (fileManager.ScanModules(resInputs, output, configJson_.IsHar()) != RESTOOL_SUCCESS) { + cerr << "Error: scan resources error" << endl; + return RESTOOL_ERROR; + } + return RESTOOL_SUCCESS; +} + +uint32_t ResourceOverlap::LoadHapResources() +{ + ResourceTable resourceTabel; + map> items; + string resourceIndexPath = + FileEntry::FilePath(packageParser_.GetInputs()[0]).GetParent().Append(RESOURCE_INDEX_FILE).GetPath(); + if (resourceTabel.LoadResTable(resourceIndexPath, items) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + + IdWorker::GetInstance().LoadIdFromHap(items); + + FileManager &fileManager = FileManager::GetInstance(); + fileManager.SetModuleName(moduleName_); + if (fileManager.MergeResourceItem(items) != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + fileManager.SetScanHap(true); + return RESTOOL_SUCCESS; +} +} +} +} \ No newline at end of file diff --git a/src/resource_pack.cpp b/src/resource_pack.cpp index 7a45297..f0260ec 100644 --- a/src/resource_pack.cpp +++ b/src/resource_pack.cpp @@ -24,6 +24,7 @@ #include "resource_table.h" #include "compression_parser.h" #include "binary_file_packer.h" +#include "factory_resource_packer.h" namespace OHOS { namespace Global { @@ -42,7 +43,14 @@ uint32_t ResourcePack::Package() if (packageParser_.GetCombine()) { return PackCombine(); } - return PackNormal(); + + if (packageParser_.IsOverlap()) { + packType_ = PackType::OVERLAP; + } + + unique_ptr resourcePacker = + FactoryResourcePacker::CreatePacker(packType_, packageParser_); + return resourcePacker->Pack(); } uint32_t ResourcePack::InitCompression() @@ -58,9 +66,13 @@ uint32_t ResourcePack::InitCompression() } // below private founction -uint32_t ResourcePack::Init() +uint32_t ResourcePack::InitResourcePack() { InitHeaderCreater(); + if (InitCompression() != RESTOOL_SUCCESS) { + return RESTOOL_ERROR; + } + if (InitOutput() != RESTOOL_SUCCESS) { return RESTOOL_ERROR; } @@ -278,32 +290,38 @@ uint32_t ResourcePack::ScanResources(const vector &inputs, const string return RESTOOL_SUCCESS; } -uint32_t ResourcePack::PackNormal() +uint32_t ResourcePack::Pack() { - if (InitCompression() != RESTOOL_SUCCESS) { - return RESTOOL_ERROR; - } + cout << "Info: Pack: normal pack mode" << endl; - if (Init() != RESTOOL_SUCCESS) { + if (InitResourcePack() != RESTOOL_SUCCESS) { + cerr << "Error: ResourcePack init failed." << endl; return RESTOOL_ERROR; } ResourceMerge resourceMerge; - if (resourceMerge.Init() != RESTOOL_SUCCESS) { + if (resourceMerge.Init(packageParser_) != RESTOOL_SUCCESS) { + cerr << "Error: resourceMerge init failed." << endl; return RESTOOL_ERROR; } BinaryFilePacker rawFilePacker(packageParser_, moduleName_); std::future copyFuture = rawFilePacker.CopyBinaryFileAsync(resourceMerge.GetInputs()); - uint32_t packQualifierRet = PackQualifierResources(resourceMerge); - if (packQualifierRet != RESTOOL_SUCCESS) { + + if (PackResources(resourceMerge) != RESTOOL_SUCCESS) { rawFilePacker.StopCopy(); + cerr << "Error: pack resources failed." << endl; + return RESTOOL_ERROR; } - uint32_t copyRet = copyFuture.get(); - return packQualifierRet == RESTOOL_SUCCESS && copyRet == RESTOOL_SUCCESS ? RESTOOL_SUCCESS : RESTOOL_ERROR; + + if (copyFuture.get() != RESTOOL_SUCCESS) { + cerr << "Error: copy binary file failed." << endl; + return RESTOOL_ERROR; + } + return RESTOOL_SUCCESS; } -uint32_t ResourcePack::PackQualifierResources(const ResourceMerge &resourceMerge) +uint32_t ResourcePack::PackResources(const ResourceMerge &resourceMerge) { if (ScanResources(resourceMerge.GetInputs(), packageParser_.GetOutput()) != RESTOOL_SUCCESS) { return RESTOOL_ERROR; @@ -532,7 +550,7 @@ uint32_t ResourcePack::PackAppend() uint32_t ResourcePack::PackCombine() { - if (Init() != RESTOOL_SUCCESS) { + if (InitResourcePack() != RESTOOL_SUCCESS) { return RESTOOL_ERROR; } @@ -560,7 +578,6 @@ void ResourcePack::CheckConfigJsonForCombine(ResourceAppend &resourceAppend) ResourceCheck resourceCheck(configJson_.GetCheckNode(), make_shared(resourceAppend)); resourceCheck.CheckConfigJsonForCombine(); } - } } } diff --git a/src/resource_table.cpp b/src/resource_table.cpp index 856c5e5..24ae7af 100644 --- a/src/resource_table.cpp +++ b/src/resource_table.cpp @@ -111,6 +111,7 @@ uint32_t ResourceTable::LoadResTable(const string path, map &keyparams = limitKeys.find(datas.find(offset)->second.second)->second; ResourceItem resourceitem(filename, keyparams, g_resTypeMap.find(record.resType)->second); resourceitem.SetLimitKey(ResourceUtil::PaserKeyParam(keyparams)); + if (values[value_size - 1] == '\0') { + value_size--; + } resourceitem.SetData(values, value_size); + resourceitem.MarkCoverable(); resInfos[record.id].push_back(resourceitem); return true; } diff --git a/src/restool.cpp b/src/restool.cpp index e26fdbb..0e229f5 100644 --- a/src/restool.cpp +++ b/src/restool.cpp @@ -14,7 +14,7 @@ */ #include "cmd_parser.h" -#include "task_handle.h" +#include "resource_pack.h" #include "compression_parser.h" using namespace std; @@ -22,8 +22,8 @@ using namespace OHOS::Global::Restool; namespace { uint32_t ProccssHap(PackageParser &packageParser) { - TaskHandle taskHandle; - return taskHandle.HandlePackage(packageParser); + ResourcePack pack(packageParser); + return pack.Package(); } }