报错信息添加FAQ链接

Signed-off-by: liduo <liduo29@huawei.com>
This commit is contained in:
liduo
2025-06-03 11:27:35 +08:00
parent 9810f49809
commit 9456855ea7
8 changed files with 227 additions and 10 deletions
+13
View File
@@ -82,6 +82,12 @@ ohos_executable("restool") {
"-lshlwapi",
]
}
if (is_linux) {
defines = [ "__LINUX__" ]
}
if (is_mac) {
defines = [ "__MAC__" ]
}
subsystem_name = "developtools"
part_name = "global_resource_tool"
}
@@ -104,3 +110,10 @@ ohos_prebuilt_etc("restool_systemres") {
subsystem_name = "developtools"
part_name = "global_resource_tool"
}
ohos_prebuilt_etc("restool_faq") {
source = "${restool_faq_path}"
subsystem_name = "developtools"
part_name = "global_resource_tool"
install_enable = false
}
+2 -1
View File
@@ -67,9 +67,10 @@ public:
* @brief open json file.
* @param path: json file path.
* @param root: json root node
* @param printError: if true, print error message.
* @return true if open success, other false.
*/
static bool OpenJsonFile(const std::string &path, cJSON **root);
static bool OpenJsonFile(const std::string &path, cJSON **root, const bool &printError = true);
/**
* @brief save json file.
+7
View File
@@ -29,6 +29,7 @@ namespace Restool {
constexpr uint32_t RESTOOL_SUCCESS = 0;
constexpr uint32_t RESTOOL_ERROR = -1;
constexpr uint16_t BUFFER_SIZE = 4096;
const std::string ERROR_MORE_INFO_FILE = "restool_faq.json";
// 11200xxx unknown error
constexpr uint32_t ERR_CODE_UNDEFINED_ERROR = 11200000;
@@ -122,6 +123,11 @@ constexpr uint32_t ERR_CODE_INVALID_RESOURCE_INDEX = 11211124;
const std::string ERR_TYPE_RESOURCE_DUMP = "Resource Dump Error";
constexpr uint32_t ERR_CODE_PARSE_HAP_ERROR = 11212001;
enum class Language {
CN,
EN
};
struct MoreInfo {
std::string cn;
std::string en;
@@ -176,6 +182,7 @@ private:
}
};
void InitFaq(const std::string &restoolPath);
ErrorInfo GetError(const uint32_t &errCode);
void PrintError(const uint32_t &errCode);
void PrintError(const ErrorInfo &error);
+1
View File
@@ -12,3 +12,4 @@
# limitations under the License.
id_defined_path = "//base/global/system_resources/systemres/main/resources/base/element/id_defined.json"
restool_faq_path = "//developtools/global_resource_tool/restool_faq.json"
+13
View File
@@ -0,0 +1,13 @@
{
"default": {
"cn": "https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/restool",
"en": "https://developer.huawei.com/consumer/en/doc/harmonyos-guides/restool"
},
"faqs": [
{
"code": 11201001,
"cn": "https://developer.huawei.com/consumer/cn/doc/harmonyos-faqs/faqs-compiling-and-building-181",
"en": "https://developer.huawei.com/consumer/en/doc/harmonyos-faqs/faqs-compiling-and-building-181"
}
]
}
+7 -3
View File
@@ -81,18 +81,22 @@ bool ResourceUtil::RmoveFile(const string &path)
return FileEntry::RemoveFile(path);
}
bool ResourceUtil::OpenJsonFile(const string &path, cJSON **root)
bool ResourceUtil::OpenJsonFile(const string &path, cJSON **root, const bool &printError)
{
ifstream ifs(FileEntry::AdaptLongPath(path), ios::binary);
if (!ifs.is_open()) {
PrintError(GetError(ERR_CODE_OPEN_JSON_FAIL).FormatCause(path.c_str(), strerror(errno)));
if (printError) {
PrintError(GetError(ERR_CODE_OPEN_JSON_FAIL).FormatCause(path.c_str(), strerror(errno)));
}
return false;
}
string jsonString((istreambuf_iterator<char>(ifs)), istreambuf_iterator<char>());
*root = cJSON_Parse(jsonString.c_str());
if (!*root) {
PrintError(GetError(ERR_CODE_JSON_FORMAT_ERROR).SetPosition(path));
if (printError) {
PrintError(GetError(ERR_CODE_JSON_FORMAT_ERROR).SetPosition(path));
}
ifs.close();
return false;
}
+1
View File
@@ -30,6 +30,7 @@ int main(int argc, char *argv[])
PrintError(GetError(ERR_CODE_UNKNOWN_COMMAND_ERROR).FormatCause("argv null"));
return RESTOOL_ERROR;
}
InitFaq(std::string(argv[0]));
auto &parser = CmdParser::GetInstance();
return parser.Parse(argc, argv, 1);
}
+183 -6
View File
@@ -14,7 +14,9 @@
*/
#include <iostream>
#include <sstream>
#include "resource_util.h"
#include "restool_errors.h"
namespace OHOS {
@@ -520,15 +522,176 @@ const std::map<uint32_t, ErrorInfo> ERRORS_MAP = {
{ ERR_CODE_PARSE_HAP_ERROR, ERR_TYPE_RESOURCE_DUMP, "Failed to parse the HAP, %s.", "", {}, {} } },
};
#ifdef __WIN32
constexpr int WIN_LOCALE_CN = 2052;
#endif
const std::string LOCALE_CN = "zh_CN";
std::map<uint32_t, MoreInfo> faqInfos;
MoreInfo defaultMoreInfo = {};
Language osLanguage = Language::EN;
std::string ExecuteCommand(const std::string &cmd)
{
std::string result;
FILE *pipe = popen(cmd.c_str(), "r");
if (!pipe) {
return result;
}
char buffer[BUFFER_SIZE];
while (!feof(pipe)) {
if (fgets(buffer, BUFFER_SIZE, pipe) != NULL) {
result += buffer;
}
}
pclose(pipe);
return result;
}
#ifdef __WIN32
Language GetWinLanguage()
{
std::string result = ExecuteCommand("wmic os get locale");
size_t pos = 0;
std::string locale = "Locale";
if ((pos = result.find(locale)) != std::string::npos) {
result.replace(pos, locale.length(), "");
}
if (result.empty()) {
return Language::CN;
}
char *end;
errno = 0;
int localeCode = static_cast<int>(strtol(result.c_str(), &end, 16));
if (end == result.c_str() || errno == ERANGE || localeCode == INT_MIN || localeCode == INT_MAX) {
return Language::CN;
}
if (localeCode == WIN_LOCALE_CN) {
return Language::CN;
}
return Language::EN;
}
#endif
#ifdef __LINUX__
std::vector<std::string> split(const std::string &s, const char &delimiter)
{
std::vector<std::string> tokens;
std::string token;
std::stringstream tokenStream(s);
while (std::getline(tokenStream, token, delimiter)) { tokens.push_back(token); }
return tokens;
}
Language GetLinuxLanguage()
{
std::string result = ExecuteCommand("locale");
if (result.empty()) {
return Language::CN;
}
std::vector<std::string> localeLines = split(result, '\n');
for (const std::string &line : localeLines) {
std::vector<std::string> keyValue = split(line, '=');
if (keyValue.size() <= 1) {
continue;
}
std::string key = keyValue[0];
std::string value = keyValue[1];
if ((key == "LC_ALL" || key == "LC_MESSAGES" || key == "LANG" || key == "LANGUAGE")
&& value.find(LOCALE_CN) != std::string::npos) {
return Language::CN;
}
}
return Language::EN;
}
#endif
#ifdef __MAC__
Language GetMacLanguage()
{
std::string result = ExecuteCommand("defaults read -globalDomain AppleLocale");
if (result.empty()) {
return Language::CN;
}
if (result.find(LOCALE_CN) != std::string::npos) {
return Language::CN;
}
return Language::EN;
}
#endif
Language GetOsLanguage()
{
#ifdef __WIN32
return GetWinLanguage();
#endif
#ifdef __LINUX__
return GetLinuxLanguage();
#endif
#ifdef __MAC__
return GetMacLanguage();
#endif
return Language::CN;
}
void GetMoreInfo(cJSON *node, MoreInfo &info)
{
if (node && cJSON_IsObject(node)) {
cJSON *cn = cJSON_GetObjectItem(node, "cn");
if (cn && cJSON_IsString(cn)) {
info.cn = cn->valuestring;
}
cJSON *en = cJSON_GetObjectItem(node, "en");
if (en && cJSON_IsString(en)) {
info.en = en->valuestring;
}
}
}
void InitFaq(const std::string &restoolPath)
{
osLanguage = GetOsLanguage();
cJSON *root;
std::string moreInfoPath = FileEntry::FilePath(restoolPath).GetParent().Append(ERROR_MORE_INFO_FILE).GetPath();
if (!ResourceUtil::OpenJsonFile(moreInfoPath, &root, false)) {
return;
}
if (!root || !cJSON_IsObject(root)) {
cJSON_Delete(root);
return;
}
cJSON *defaultNode = cJSON_GetObjectItem(root, "default");
GetMoreInfo(defaultNode, defaultMoreInfo);
cJSON *faqsNode = cJSON_GetObjectItem(root, "faqs");
if (!faqsNode || !cJSON_IsArray(faqsNode) || cJSON_GetArraySize(faqsNode) == 0) {
cJSON_Delete(root);
return;
}
for (cJSON *infoNode = faqsNode->child; infoNode; infoNode = faqsNode->next) {
cJSON *codeNode = cJSON_GetObjectItem(infoNode, "code");
if (!codeNode || !cJSON_IsNumber(codeNode)) {
continue;
}
uint32_t code = static_cast<uint32_t>(codeNode->valueint);
MoreInfo info = {};
GetMoreInfo(infoNode, info);
faqInfos[code] = info;
}
cJSON_Delete(root);
}
ErrorInfo GetError(const uint32_t &errCode)
{
ErrorInfo error;
if (ERRORS_MAP.count(errCode) == 0) {
return error;
}
auto it = ERRORS_MAP.find(errCode);
if (it != ERRORS_MAP.end()) {
return it->second;
error = it->second;
}
auto faq = faqInfos.find(errCode);
if (faq != faqInfos.end()) {
error.moreInfo_ = faq->second;
}
return error;
}
@@ -551,8 +714,22 @@ void PrintError(const ErrorInfo &error)
if (!error.solutions_.empty()) {
errMsg.append("* Try the following:").append("\n");
for (const auto &solution : error.solutions_) { errMsg.append(" > ").append(solution).append("\n"); }
if (!error.moreInfo_.cn.empty()) {
errMsg.append("> More info: ").append(error.moreInfo_.cn).append("\n");
std::string moreInfo;
if (osLanguage == Language::CN) {
if (!error.moreInfo_.cn.empty()) {
moreInfo = error.moreInfo_.cn;
} else {
moreInfo = defaultMoreInfo.cn;
}
} else {
if (!error.moreInfo_.en.empty()) {
moreInfo = error.moreInfo_.en;
} else {
moreInfo = defaultMoreInfo.en;
}
}
if (!moreInfo.empty()) {
errMsg.append("> More info: ").append(moreInfo).append("\n");
}
}
std::cerr << errMsg;