Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions src/FuelClient.cc
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,60 @@ Result FuelClient::DownloadModel(const ModelIdentifier &_id,
if (!this->dataPtr->cache->SaveModel(newId, resp.data, true))
return Result(ResultType::FETCH_ERROR);

// Locate any dependencies from the input model and download them.
std::string path;
ignition::msgs::FuelMetadata meta;
if (this->CachedModel(ignition::common::URI(newId.UniqueName()), path))
{
std::string metadataPath =
ignition::common::joinPaths(path, "metadata.pbtxt");
std::string modelConfigPath =
ignition::common::joinPaths(path, "model.config");
if (ignition::common::exists(metadataPath))
{
// Read the pbtxt file.
std::ifstream inputFile(metadataPath);
std::string inputStr((std::istreambuf_iterator<char>(inputFile)),
std::istreambuf_iterator<char>());

// Parse the file into the fuel metadata message
google::protobuf::TextFormat::ParseFromString(inputStr, &meta);

for (int i = 0; i < meta.dependencies_size(); i++)
{
std::string dependencyPath;
ignition::common::URI dependencyURI(meta.dependencies(i).uri());

// If the model is not already cached, download it; this prevents
// any sort of cyclic dependencies fromo running infinitely
if (!this->CachedModel(dependencyURI, dependencyPath))
this->DownloadModel(dependencyURI, dependencyPath);
}
}
else if (ignition::common::exists(modelConfigPath))
{
std::ifstream inputFile(modelConfigPath);
std::string inputStr((std::istreambuf_iterator<char>(inputFile)),
std::istreambuf_iterator<char>());

if (!ignition::msgs::ConvertFuelMetadata(inputStr, meta))
{
return Result(ResultType::UPLOAD_ERROR);
}

for (int i = 0; i < meta.dependencies_size(); i++)
{
std::string dependencyPath;
ignition::common::URI dependencyURI(meta.dependencies(i).uri());

// If the model is not already cached, download it; this prevents
// any sort of cyclic dependencies fromo running infinitely
if (!this->CachedModel(dependencyURI, dependencyPath))
this->DownloadModel(dependencyURI, dependencyPath);
}
}
}

return Result(ResultType::FETCH);
}

Expand Down
70 changes: 70 additions & 0 deletions src/FuelClient_TEST.cc
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,76 @@ TEST_F(FuelClientTest, IGN_UTILS_TEST_DISABLED_ON_WIN32(DownloadModel))
EXPECT_NE(std::string::npos, modelSdf.find("<roughness_map>https://"));
}

// Download model with a dependency specified within its `metadata.pbtxt`
{
common::URI url{
"https://fuel.ignitionrobotics.org/1.0/JShep1/models/hatchback_red_1"};
common::URI depUrl{
"https://fuel.ignitionrobotics.org/1.0/JShep1/models/hatchback_1"};

// Check it is not cached
std::string cachedPath;
Result res1 = client.CachedModel(url, cachedPath);
EXPECT_FALSE(res1);
EXPECT_EQ(Result(ResultType::FETCH_ERROR), res1);

// Check the dependency is not cached
Result res2 = client.CachedModel(depUrl, cachedPath);
EXPECT_FALSE(res2);
EXPECT_EQ(Result(ResultType::FETCH_ERROR), res2);

// Download
std::string path;
Result res3 = client.DownloadModel(url, path);
EXPECT_TRUE(res3);
EXPECT_EQ(Result(ResultType::FETCH_ALREADY_EXISTS), res3);

// Check it is cached
Result res4 = client.CachedModel(url, cachedPath);
EXPECT_TRUE(res4);
EXPECT_EQ(Result(ResultType::FETCH_ALREADY_EXISTS), res4);

// Check the dependency is cached
Result res5 = client.CachedModel(depUrl, cachedPath);
EXPECT_TRUE(res5);
EXPECT_EQ(Result(ResultType::FETCH_ALREADY_EXISTS), res5);
}

// Download model with a dependency specified within its `model.config`
{
common::URI url{
"https://fuel.ignitionrobotics.org/1.0/JShep1/models/hatchback_red_2"};
common::URI depUrl{
"https://fuel.ignitionrobotics.org/1.0/JShep1/models/hatchback_2"};

// Check it is not cached
std::string cachedPath;
Result res1 = client.CachedModel(url, cachedPath);
EXPECT_FALSE(res1);
EXPECT_EQ(Result(ResultType::FETCH_ERROR), res1);

// Check the dependency is not cached
Result res2 = client.CachedModel(depUrl, cachedPath);
EXPECT_FALSE(res2);
EXPECT_EQ(Result(ResultType::FETCH_ERROR), res2);

// Download
std::string path;
Result res3 = client.DownloadModel(url, path);
EXPECT_TRUE(res3);
EXPECT_EQ(Result(ResultType::FETCH_ALREADY_EXISTS), res3);

// Check it is cached
Result res4 = client.CachedModel(url, cachedPath);
EXPECT_TRUE(res4);
EXPECT_EQ(Result(ResultType::FETCH_ALREADY_EXISTS), res4);

// Check the dependency is cached
Result res5 = client.CachedModel(depUrl, cachedPath);
EXPECT_TRUE(res5);
EXPECT_EQ(Result(ResultType::FETCH_ALREADY_EXISTS), res5);
}

// Try using nonexistent URL
{
std::string url{
Expand Down