Skip to content

Commit 31c8f4e

Browse files
committed
Pull lambdas out into separate functions.
Addresses feedback from PR #8188.
1 parent ab173b6 commit 31c8f4e

2 files changed

Lines changed: 141 additions & 121 deletions

File tree

view/sharedcache/core/SharedCacheView.cpp

Lines changed: 134 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,107 +1051,157 @@ void SharedCacheView::LogSecondaryFileName(std::string secondaryFileName)
10511051
GetParentView()->StoreMetadata(VIEW_METADATA_KEY, GetMetadata());
10521052
}
10531053

1054-
std::optional<std::string> SharedCacheView::GetPrimaryFilePath()
1054+
1055+
std::string SharedCacheView::StorePrimaryProjectFile(ProjectFile* projectFile)
10551056
{
1056-
auto viewFile = GetFile();
1057-
auto databaseDir = std::filesystem::path(viewFile->GetFilename()).parent_path().string();
1058-
auto currentProjectFile = viewFile->GetProjectFile();
1059-
Ref<Project> project = nullptr;
1060-
if (currentProjectFile)
1061-
project = currentProjectFile->GetProject();
1057+
SetPrimaryFileLocation(projectFile->GetPathInProject(), projectFile->GetName());
1058+
return projectFile->GetPathOnDisk();
1059+
}
10621060

1063-
auto storePrimaryProjectFile = [&](ProjectFile* projectFile) -> std::string {
1064-
SetPrimaryFileLocation(projectFile->GetPathInProject(), projectFile->GetName());
1065-
return projectFile->GetPathOnDisk();
1066-
};
10671061

1068-
auto storePrimaryFilePath = [&](const std::string& path) {
1069-
if (project)
1062+
void SharedCacheView::StorePrimaryFilePath(const std::string& path, Project* project, const std::string& databaseDir)
1063+
{
1064+
if (project)
1065+
{
1066+
if (auto projectFile = project->GetFileByPathOnDisk(path))
10701067
{
1071-
if (auto projectFile = project->GetFileByPathOnDisk(path))
1072-
{
1073-
SetPrimaryFileLocation(projectFile->GetPathInProject(), projectFile->GetName());
1074-
return;
1075-
}
1076-
1077-
m_logger->LogWarnF(
1078-
"Primary shared cache file '{}' is outside the current project. Add the shared cache files to the project to avoid selecting them on future opens.",
1079-
path);
1080-
SetPrimaryFileName(BaseFileName(path));
1068+
SetPrimaryFileLocation(projectFile->GetPathInProject(), projectFile->GetName());
10811069
return;
10821070
}
10831071

1084-
SetPrimaryFileLocation(PathRelativeTo(path, databaseDir), BaseFileName(path));
1085-
};
1072+
m_logger->LogWarnF(
1073+
"Primary shared cache file '{}' is outside the current project. Add the shared cache files to the project to avoid selecting them on future opens.",
1074+
path);
1075+
SetPrimaryFileName(BaseFileName(path));
1076+
return;
1077+
}
10861078

1087-
auto resolveProjectFilePath = [&](const std::string& projectPath) -> std::optional<std::string> {
1088-
if (!project || projectPath.empty())
1089-
return std::nullopt;
1079+
SetPrimaryFileLocation(PathRelativeTo(path, databaseDir), BaseFileName(path));
1080+
}
10901081

1091-
try
1082+
1083+
std::optional<std::string> SharedCacheView::ResolveProjectFilePath(Project* project, const std::string& projectPath)
1084+
{
1085+
if (!project || projectPath.empty())
1086+
return std::nullopt;
1087+
1088+
try
1089+
{
1090+
auto matches = project->GetFilesByPathInProject(projectPath);
1091+
if (matches.size() > 1)
10921092
{
1093-
auto matches = project->GetFilesByPathInProject(projectPath);
1094-
if (matches.size() > 1)
1095-
{
1096-
m_logger->LogErrorF(
1097-
"Multiple project files match primary shared cache path '{}'. Provide loader.dsc.primaryFilePath with an unambiguous project path.",
1098-
projectPath);
1099-
return std::string();
1100-
}
1101-
if (matches.size() == 1)
1102-
return storePrimaryProjectFile(matches[0]);
1093+
m_logger->LogErrorF(
1094+
"Multiple project files match primary shared cache path '{}'. Provide loader.dsc.primaryFilePath with an unambiguous project path.",
1095+
projectPath);
1096+
return std::string();
11031097
}
1104-
catch (const std::exception& e)
1098+
if (matches.size() == 1)
1099+
return StorePrimaryProjectFile(matches[0]);
1100+
}
1101+
catch (const std::exception& e)
1102+
{
1103+
m_logger->LogWarnForExceptionF(e, "Failed to resolve primary shared cache project path '{}': {}", projectPath,
1104+
e.what());
1105+
}
1106+
1107+
return std::nullopt;
1108+
}
1109+
1110+
1111+
std::optional<std::string> SharedCacheView::ResolveUniqueProjectFileName(Project* project)
1112+
{
1113+
if (!project || m_primaryFileName.empty())
1114+
return std::nullopt;
1115+
1116+
std::vector<Ref<ProjectFile>> matches;
1117+
for (const auto& projectFile : project->GetFiles())
1118+
if (projectFile->GetName() == m_primaryFileName)
1119+
matches.push_back(projectFile);
1120+
1121+
if (matches.empty())
1122+
return std::nullopt;
1123+
1124+
if (matches.size() > 1)
1125+
{
1126+
std::string paths;
1127+
for (const auto& match : matches)
11051128
{
1106-
m_logger->LogWarnForExceptionF(e, "Failed to resolve primary shared cache project path '{}': {}", projectPath,
1107-
e.what());
1129+
if (!paths.empty())
1130+
paths += ", ";
1131+
paths += match->GetPathInProject();
11081132
}
1133+
m_logger->LogErrorF(
1134+
"Multiple project files are named '{}': {}. Provide loader.dsc.primaryFilePath with the project path to the correct primary shared cache file.",
1135+
m_primaryFileName, paths);
1136+
return std::string();
1137+
}
1138+
1139+
return StorePrimaryProjectFile(matches[0]);
1140+
}
11091141

1142+
1143+
std::optional<std::string> SharedCacheView::ResolveMetadataPrimaryFilePath(Project* project, const std::string& databaseDir)
1144+
{
1145+
if (m_primaryFilePath.empty())
11101146
return std::nullopt;
1111-
};
11121147

1113-
auto resolveUniqueProjectFileName = [&]() -> std::optional<std::string> {
1114-
if (!project || m_primaryFileName.empty())
1115-
return std::nullopt;
1148+
if (project)
1149+
return ResolveProjectFilePath(project, m_primaryFilePath);
11161150

1117-
std::vector<Ref<ProjectFile>> matches;
1118-
for (const auto& projectFile : project->GetFiles())
1119-
if (projectFile->GetName() == m_primaryFileName)
1120-
matches.push_back(projectFile);
1151+
auto path = ResolveRelativePath(m_primaryFilePath, databaseDir);
1152+
if (IsUsablePrimaryCachePath(path))
1153+
return path;
1154+
return std::nullopt;
1155+
}
11211156

1122-
if (matches.empty())
1123-
return std::nullopt;
11241157

1125-
if (matches.size() > 1)
1126-
{
1127-
std::string paths;
1128-
for (const auto& match : matches)
1129-
{
1130-
if (!paths.empty())
1131-
paths += ", ";
1132-
paths += match->GetPathInProject();
1133-
}
1134-
m_logger->LogErrorF(
1135-
"Multiple project files are named '{}': {}. Provide loader.dsc.primaryFilePath with the project path to the correct primary shared cache file.",
1136-
m_primaryFileName, paths);
1137-
return std::string();
1138-
}
1158+
std::optional<std::string> SharedCacheView::PromptForPrimaryFile()
1159+
{
1160+
if (!IsUIEnabled())
1161+
{
1162+
m_logger->LogErrorF(
1163+
"Primary shared cache file '{}' could not be resolved. Provide loader.dsc.primaryFilePath when loading this database headlessly.",
1164+
m_primaryFileName);
1165+
return std::nullopt;
1166+
}
11391167

1140-
return storePrimaryProjectFile(matches[0]);
1141-
};
1168+
ShowMessageBox("Select Primary Shared Cache File",
1169+
"Binary Ninja needs the original primary dyld shared cache file to reopen this database. "
1170+
"Select the primary dyld_shared_cache file, not another .bndb database.", OKButtonSet, InformationIcon);
11421171

1143-
auto resolveMetadataPrimaryFilePath = [&]() -> std::optional<std::string> {
1144-
if (m_primaryFilePath.empty())
1145-
return std::nullopt;
1172+
std::string newPrimaryFilePath;
1173+
std::string prompt = "Select primary shared cache file";
1174+
if (!m_primaryFileName.empty())
1175+
prompt += " '" + m_primaryFileName + "'";
1176+
if (!GetOpenFileNameInput(newPrimaryFilePath, prompt))
1177+
return std::nullopt;
11461178

1147-
if (project)
1148-
return resolveProjectFilePath(m_primaryFilePath);
1179+
if (IsBndbPath(newPrimaryFilePath))
1180+
{
1181+
m_logger->LogAlertF(
1182+
"Selected primary shared cache path is a Binary Ninja database, not a dyld shared cache file: '{}'",
1183+
newPrimaryFilePath);
1184+
return std::nullopt;
1185+
}
11491186

1150-
auto path = ResolveRelativePath(m_primaryFilePath, databaseDir);
1151-
if (IsUsablePrimaryCachePath(path))
1152-
return path;
1187+
if (!IsUsablePrimaryCachePath(newPrimaryFilePath))
1188+
{
1189+
m_logger->LogAlertF("Selected primary shared cache path is not a usable file: '{}'", newPrimaryFilePath);
11531190
return std::nullopt;
1154-
};
1191+
}
1192+
1193+
return newPrimaryFilePath;
1194+
}
1195+
1196+
1197+
std::optional<std::string> SharedCacheView::GetPrimaryFilePath()
1198+
{
1199+
auto viewFile = GetFile();
1200+
auto databaseDir = std::filesystem::path(viewFile->GetFilename()).parent_path().string();
1201+
auto currentProjectFile = viewFile->GetProjectFile();
1202+
Ref<Project> project = nullptr;
1203+
if (currentProjectFile)
1204+
project = currentProjectFile->GetProject();
11551205

11561206
auto settings = GetLoadSettings(GetTypeName());
11571207
if (settings && settings->Contains("loader.dsc.primaryFilePath"))
@@ -1162,7 +1212,7 @@ std::optional<std::string> SharedCacheView::GetPrimaryFilePath()
11621212
settings->Reset("loader.dsc.primaryFilePath", this, SettingsResourceScope);
11631213
if (project)
11641214
{
1165-
auto projectPathResult = resolveProjectFilePath(configuredPrimaryFilePath);
1215+
auto projectPathResult = ResolveProjectFilePath(project, configuredPrimaryFilePath);
11661216
if (projectPathResult && projectPathResult->empty())
11671217
return std::nullopt;
11681218
if (projectPathResult)
@@ -1185,44 +1235,7 @@ std::optional<std::string> SharedCacheView::GetPrimaryFilePath()
11851235
}
11861236
}
11871237

1188-
auto promptForPrimaryFile = [&]() -> std::optional<std::string> {
1189-
if (!IsUIEnabled())
1190-
{
1191-
m_logger->LogErrorF(
1192-
"Primary shared cache file '{}' could not be resolved. Provide loader.dsc.primaryFilePath when loading this database headlessly.",
1193-
m_primaryFileName);
1194-
return std::nullopt;
1195-
}
1196-
1197-
ShowMessageBox("Select Primary Shared Cache File",
1198-
"Binary Ninja needs the original primary dyld shared cache file to reopen this database. "
1199-
"Select the primary dyld_shared_cache file, not another .bndb database.", OKButtonSet, InformationIcon);
1200-
1201-
std::string newPrimaryFilePath;
1202-
std::string prompt = "Select primary shared cache file";
1203-
if (!m_primaryFileName.empty())
1204-
prompt += " '" + m_primaryFileName + "'";
1205-
if (!GetOpenFileNameInput(newPrimaryFilePath, prompt))
1206-
return std::nullopt;
1207-
1208-
if (IsBndbPath(newPrimaryFilePath))
1209-
{
1210-
m_logger->LogAlertF(
1211-
"Selected primary shared cache path is a Binary Ninja database, not a dyld shared cache file: '{}'",
1212-
newPrimaryFilePath);
1213-
return std::nullopt;
1214-
}
1215-
1216-
if (!IsUsablePrimaryCachePath(newPrimaryFilePath))
1217-
{
1218-
m_logger->LogAlertF("Selected primary shared cache path is not a usable file: '{}'", newPrimaryFilePath);
1219-
return std::nullopt;
1220-
}
1221-
1222-
return newPrimaryFilePath;
1223-
};
1224-
1225-
if (auto metadataPrimaryPath = resolveMetadataPrimaryFilePath())
1238+
if (auto metadataPrimaryPath = ResolveMetadataPrimaryFilePath(project, databaseDir))
12261239
{
12271240
if (metadataPrimaryPath->empty())
12281241
return std::nullopt;
@@ -1254,7 +1267,7 @@ std::optional<std::string> SharedCacheView::GetPrimaryFilePath()
12541267

12551268
if (!IsUsablePrimaryCachePath(primaryFilePath))
12561269
{
1257-
auto promptedPrimaryFilePath = promptForPrimaryFile();
1270+
auto promptedPrimaryFilePath = PromptForPrimaryFile();
12581271
if (!promptedPrimaryFilePath)
12591272
return std::nullopt;
12601273
primaryFilePath = *promptedPrimaryFilePath;
@@ -1268,7 +1281,7 @@ std::optional<std::string> SharedCacheView::GetPrimaryFilePath()
12681281
return std::nullopt;
12691282
}
12701283

1271-
storePrimaryFilePath(primaryFilePath);
1284+
StorePrimaryFilePath(primaryFilePath, project, databaseDir);
12721285
}
12731286

12741287
// 3. If we are not in a project, the filesystem path is ready to use.
@@ -1295,10 +1308,10 @@ std::optional<std::string> SharedCacheView::GetPrimaryFilePath()
12951308
// We are looking for the file with file name we stored in metadata.
12961309
if (pj->GetName() != m_primaryFileName)
12971310
continue;
1298-
return storePrimaryProjectFile(pj);
1311+
return StorePrimaryProjectFile(pj);
12991312
}
13001313

1301-
if (auto uniqueProjectPath = resolveUniqueProjectFileName())
1314+
if (auto uniqueProjectPath = ResolveUniqueProjectFileName(project))
13021315
{
13031316
if (uniqueProjectPath->empty())
13041317
return std::nullopt;
@@ -1310,7 +1323,7 @@ std::optional<std::string> SharedCacheView::GetPrimaryFilePath()
13101323

13111324
// 6. If automatic project resolution failed, ask the user in UI mode. Headless callers must provide
13121325
// loader.dsc.primaryFilePath or arrange files so one of the automatic resolution paths works.
1313-
auto promptedPrimaryFilePath = promptForPrimaryFile();
1326+
auto promptedPrimaryFilePath = PromptForPrimaryFile();
13141327
if (!promptedPrimaryFilePath)
13151328
return std::nullopt;
13161329
std::string newPrimaryFilePath = *promptedPrimaryFilePath;

view/sharedcache/core/SharedCacheView.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ class SharedCacheView : public BinaryNinja::BinaryView
2121
// NOTE: Currently this is just used to alert the user to supposed missing files.
2222
std::set<std::string> m_secondaryFileNames;
2323

24+
std::string StorePrimaryProjectFile(BinaryNinja::ProjectFile* projectFile);
25+
void StorePrimaryFilePath(const std::string& path, BinaryNinja::Project* project, const std::string& databaseDir);
26+
std::optional<std::string> ResolveProjectFilePath(BinaryNinja::Project* project, const std::string& projectPath);
27+
std::optional<std::string> ResolveUniqueProjectFileName(BinaryNinja::Project* project);
28+
std::optional<std::string> ResolveMetadataPrimaryFilePath(BinaryNinja::Project* project, const std::string& databaseDir);
29+
std::optional<std::string> PromptForPrimaryFile();
30+
2431
public:
2532
SharedCacheView(const std::string& typeName, BinaryView* data, bool parseOnly = false);
2633

0 commit comments

Comments
 (0)