ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK);
ASSERT_TRUE(ValidatePackage(pkgid, {appid}));
bf::path root_path = ci::GetRootAppPath(false, kTestUserId);
- ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT")); // NOLINT
- ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "shared" / "res" / "SHARED-WGT")); // NOLINT
+ ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT")); // NOLINT
+ ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "shared" / "res" / "SHARED-WGT")); // NOLINT
}
TEST_F(SmokeTest, SharedRes30Delta) {
ASSERT_TRUE(ValidatePackage(pkgid, {appid}));
// Check delta modifications
bf::path root_path = ci::GetRootAppPath(false, kTestUserId);
- ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT-2")); // NOLINT
- ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "shared" / "res" / "SHARED-WGT-2")); // NOLINT
+ ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT-2")); // NOLINT
+ ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "shared" / "res" / "SHARED-WGT-2")); // NOLINT
ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT-1")); // NOLINT
ASSERT_FALSE(bf::exists(root_path / pkgid / "shared" / "res" / "SHARED-WGT-1")); // NOLINT
}
ASSERT_EQ(Install(path, PackageType::HYBRID), ci::AppInstaller::Result::OK);
ASSERT_TRUE(ValidatePackage(pkgid, {appid1, appid2}));
bf::path root_path = ci::GetRootAppPath(false, kTestUserId);
- ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT")); // NOLINT
- ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "shared" / "res" / "SHARED-WGT")); // NOLINT
+ ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT")); // NOLINT
+ ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "shared" / "res" / "SHARED-WGT")); // NOLINT
ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "shared" / "res" / "SHARED-TPK")); // NOLINT
- ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-TPK")); // NOLINT
}
TEST_F(SmokeTest, SharedRes30HybridDelta) {
ASSERT_TRUE(ValidatePackage(pkgid, {appid1, appid2}));
// Check delta modifications
bf::path root_path = ci::GetRootAppPath(false, kTestUserId);
- ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT-2")); // NOLINT
- ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "shared" / "res" / "SHARED-WGT-2")); // NOLINT
+ ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT-2")); // NOLINT
+ ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "shared" / "res" / "SHARED-WGT-2")); // NOLINT
ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "shared" / "res" / "SHARED-TPK-2")); // NOLINT
- ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-TPK-2")); // NOLINT
ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT-1")); // NOLINT
ASSERT_FALSE(bf::exists(root_path / pkgid / "shared" / "res" / "SHARED-WGT-1")); // NOLINT
}
namespace bf = boost::filesystem;
namespace bs = boost::system;
+namespace ci = common_installer;
namespace {
int version = std::stoi(context_->manifest_data.get()->api_version);
if (version >= 3) {
- LOG(DEBUG) << "Symlinking widget's shared/res directory content in "
+ LOG(DEBUG) <<
+ "Moving and linking widget's shared/res directory content in "
<< context_->pkg_path.get();
if (!ShareDirFor3x())
return Status::APP_DIR_ERROR;
return false;
}
}
- // link all ${pkg_path}/res/wgt/shared/res content to ${pkg_path}/shared/res
+
+ // move and link all contents of ${pkg_path}res/wgt/shared/res
+ // to ${pkg_path}shared/res
bf::directory_iterator end_itr;
for (bf::directory_iterator itr(wgt_shared_res_dir); itr != end_itr; ++itr) {
- bf::path link_target = itr->path();
- if (bf::is_symlink(link_target)) {
- continue;
- }
- bf::path link_file = shared_res_dir / link_target.filename();
- if (bf::exists(link_file)) {
- LOG(DEBUG) << "shared/res linking: skipping existing " << link_file;
- continue;
- }
- LOG(DEBUG) << "shared/res linking: creating link " << link_file;
- bs::error_code error;
- bf::create_symlink(link_target, link_file, error);
- if (error) {
- LOG(ERROR) << "shared/res linking: linking failed for " << link_file
- << ": " << boost::system::system_error(error).what();
- return false;
- }
- }
- // link all ${pkg_path}/shared/res content to ${pkg_path}/res/wgt/shared/res
- for (bf::directory_iterator itr(shared_res_dir); itr != end_itr; ++itr) {
- bf::path link_target = itr->path();
- if (bf::is_symlink(link_target)) {
+ bf::path current = itr->path();
+ if (bf::is_symlink(current)) {
continue;
}
- bf::path link_file = wgt_shared_res_dir / link_target.filename();
- if (bf::exists(link_file)) {
- LOG(DEBUG) << "shared/res linking: skipping existing " << link_file;
- continue;
+ bf::path dest = shared_res_dir / current.filename();
+ if (bf::is_directory(current)) {
+ if (!ci::MoveDir(current, dest, ci::FS_MERGE_OVERWRITE))
+ return false;
+ } else {
+ if (!ci::MoveFile(current, dest, true))
+ return false;
}
- LOG(DEBUG) << "shared/res linking: creating link " << link_file;
bs::error_code error;
- bf::create_symlink(link_target, link_file, error);
+ bf::create_symlink(dest, current, error);
if (error) {
- LOG(ERROR) << "shared/res linking: linking failed for " << link_file
+ LOG(ERROR) << "linking failed for " << dest
<< ": " << boost::system::system_error(error).what();
return false;
}
namespace bf = boost::filesystem;
namespace bs = boost::system;
+namespace ci = common_installer;
namespace {
namespace wgt {
namespace filesystem {
-common_installer::Step::Status StepWgtUndoPatchStorageDirectories::process() {
+ci::Step::Status StepWgtUndoPatchStorageDirectories::process() {
int version = std::stoi(context_->manifest_data.get()->api_version);
if (version >= 3) {
- LOG(DEBUG) << "Unlinking widget's shared/res directory content in "
+ LOG(DEBUG) <<
+ "Unlinking and moving widget's shared/res directory content back in "
<< context_->pkg_path.get();
if (!UndoShareDirFor3x())
return Status::APP_DIR_ERROR;
return Status::OK;
}
+ci::Step::Status StepWgtUndoPatchStorageDirectories::clean() {
+ if (!backup_dir_.empty())
+ ci::RemoveAll(backup_dir_);
+ return Status::OK;
+}
+
+ci::Step::Status StepWgtUndoPatchStorageDirectories::undo() {
+ if (!backup_dir_.empty()) {
+ LOG(DEBUG) << "Restore res/wgt/shared/res from backup dir";
+ // restore link
+ bf::path wgt_shared_res_dir =
+ context_->pkg_path.get() / kResWgtSubPath / kSharedResLocation;
+ bf::path backup_wgt_shared_res = backup_dir_ / "wgt_shared_res";
+ if (!backup_wgt_shared_res.empty()) {
+ if (!ci::RemoveAll(wgt_shared_res_dir)) {
+ LOG(ERROR) << "Failed to remove res/wgt/shared/res";
+ return Status::APP_DIR_ERROR;
+ }
+ if (!ci::CopyDir(backup_dir_, wgt_shared_res_dir,
+ ci::FS_MERGE_OVERWRITE, false)) {
+ LOG(ERROR) << "Failed to copy from backup";
+ return Status::APP_DIR_ERROR;
+ }
+ }
+ // restore original contents
+ bf::path shared_res_dir = context_->pkg_path.get() / kSharedResLocation;
+ bf::path backup_shared_res = backup_dir_ / "shared_res";
+ if (!backup_shared_res.empty()) {
+ if (!ci::CopyDir(backup_dir_, shared_res_dir,
+ ci::FS_MERGE_OVERWRITE, false)) {
+ LOG(ERROR) << "Failed to copy from backup";
+ return Status::APP_DIR_ERROR;
+ }
+ }
+ }
+ return Status::OK;
+}
+
bool StepWgtUndoPatchStorageDirectories::UndoShareDirFor3x() {
// check if ${pkg_path}/shared/res exists
bf::path shared_res_dir = context_->pkg_path.get() / kSharedResLocation;
+ if (!bf::exists(shared_res_dir))
+ return true;
bf::path wgt_shared_res_dir =
context_->pkg_path.get() / kResWgtSubPath / kSharedResLocation;
- if (!bf::exists(shared_res_dir))
+ if (!bf::exists(wgt_shared_res_dir))
return true;
- // delete symlinks in ${pkg_path}/shared/res
- if (bf::exists(shared_res_dir)) {
- bf::directory_iterator end_itr;
- for (bf::directory_iterator itr(shared_res_dir); itr != end_itr; ++itr) {
- bf::path link_file = itr->path();
- if (!bf::is_symlink(link_file)) {
- continue;
- }
- bf::path link_target = bf::read_symlink(link_file);
- if (link_target.native().substr(0, wgt_shared_res_dir.native().length()) !=
- wgt_shared_res_dir.native()) {
- continue;
- }
- LOG(DEBUG) << "shared/res linking: removing symlink " << link_file;
- bs::error_code error;
- bf::remove(link_file, error);
- if (error) {
- LOG(ERROR) << "Failed to remove symlink " << link_file;
- return false;
- }
- }
+
+ if (bf::is_symlink(wgt_shared_res_dir)) {
+ LOG(ERROR) << "Can't support this step, pkg should be fully updated";
+ return false;
}
- // delete symlinks in ${pkg_path}/res/wgt/shared/res
- if (bf::exists(wgt_shared_res_dir)) {
- bf::directory_iterator end_itr;
- for (bf::directory_iterator itr(wgt_shared_res_dir); itr != end_itr; ++itr) {
- bf::path link_file = itr->path();
- if (!bf::is_symlink(link_file)) {
- continue;
- }
- bf::path link_target = bf::read_symlink(link_file);
- if (link_target.native().substr(0, shared_res_dir.native().length()) !=
- shared_res_dir.native()) {
- continue;
- }
- LOG(DEBUG) << "shared/res linking: removing symlink " << link_file;
- bs::error_code error;
- bf::remove(link_file, error);
- if (error) {
- LOG(ERROR) << "Failed to remove symlink " << link_file;
+
+ // backup for undo
+ backup_dir_ = context_->unpacked_dir_path.get();
+ backup_dir_ += ".SharedRes";
+ bf::path backup_shared_res = backup_dir_ / "shared_res";
+ if (!ci::CreateDir(backup_shared_res))
+ return false;
+ bf::path backup_wgt_shared_res = backup_dir_ / "wgt_shared_res";
+ if (!ci::CopyDir(wgt_shared_res_dir, backup_wgt_shared_res,
+ ci::FS_MERGE_OVERWRITE, false)) {
+ backup_dir_.clear();
+ return false;
+ }
+
+ // unlink and move all linked contents from ${pkg_path}/shared/res
+ // to ${pkg_path}/res/wgt/shared/res
+ bf::directory_iterator end_itr;
+ for (bf::directory_iterator itr(wgt_shared_res_dir); itr != end_itr; ++itr) {
+ bf::path link_file = itr->path();
+ if (!bf::is_symlink(link_file)) {
+ continue;
+ }
+ bf::path link_target = bf::read_symlink(link_file);
+ if (link_target.native().substr(0, shared_res_dir.native().length()) !=
+ shared_res_dir.native()) {
+ continue;
+ }
+ if (!ci::Remove(link_file))
+ return false;
+ bf::path tmp_backup = backup_shared_res / link_target.filename();
+ if (bf::is_directory(link_target)) {
+ if (!ci::CopyDir(link_target, tmp_backup, ci::FS_MERGE_OVERWRITE, false))
+ return false;
+ if (!ci::MoveDir(link_target, link_file, ci::FS_MERGE_OVERWRITE))
+ return false;
+ } else {
+ if (!ci::CopyFile(link_target, tmp_backup))
+ return false;
+ if (!ci::MoveFile(link_target, link_file, true))
return false;
- }
}
}
+
return true;
}