Reworked sharing of widget's shared/res directory. 72/98672/4 accepted/tizen/3.0/common/20170331.151949 accepted/tizen/3.0/ivi/20170331.044306 accepted/tizen/3.0/mobile/20170331.044040 accepted/tizen/3.0/tv/20170331.044159 accepted/tizen/3.0/wearable/20170331.044233 submit/tizen_3.0/20170329.045543
authorPiotr Dabrowski <p.dabrowski2@samsung.com>
Mon, 19 Sep 2016 13:43:16 +0000 (15:43 +0200)
committerDamian Pietruchowski <d.pietruchow@samsung.com>
Thu, 9 Mar 2017 15:52:31 +0000 (16:52 +0100)
./res/wgt/shared/res directory content was moved to ./shared/res
and then ./res/wgt/shared/res was symlinked to ./shared/res

This broke signatures check for delta update.

Now all items (files and directories) under ./res/wgt/shared/res
are symlinked into ./shared/res, and vice versa.
During delta update these symlinks are removed, so that the
signatures check can complete successfully, and later the symlinks
are recreated again.

Added smoke tests for symlinking shared/res contents in Tizen 3.0

Change-Id: I9423d78aba5cb338b14a9f8853754e0fa8980e0c

16 files changed:
src/hybrid/hybrid_installer.cc
src/unit_tests/smoke_test.cc
src/unit_tests/test_samples/smoke/SharedRes24.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/SharedRes30.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/SharedRes30Delta.delta [new file with mode: 0644]
src/unit_tests/test_samples/smoke/SharedRes30Delta.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/SharedRes30Delta_2.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/SharedRes30Hybrid.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/SharedRes30HybridDelta.delta [new file with mode: 0644]
src/unit_tests/test_samples/smoke/SharedRes30HybridDelta.wgt [new file with mode: 0644]
src/unit_tests/test_samples/smoke/SharedRes30HybridDelta_2.wgt [new file with mode: 0644]
src/wgt/step/filesystem/step_wgt_patch_storage_directories.cc
src/wgt/step/filesystem/step_wgt_patch_storage_directories.h
src/wgt/step/filesystem/step_wgt_undo_patch_storage_directories.cc [new file with mode: 0644]
src/wgt/step/filesystem/step_wgt_undo_patch_storage_directories.h [new file with mode: 0644]
src/wgt/wgt_installer.cc

index a38edf1..a999f4a 100644 (file)
@@ -88,6 +88,7 @@
 #include "wgt/step/filesystem/step_create_symbolic_link.h"
 #include "wgt/step/filesystem/step_wgt_patch_icons.h"
 #include "wgt/step/filesystem/step_wgt_patch_storage_directories.h"
+#include "wgt/step/filesystem/step_wgt_undo_patch_storage_directories.h"
 #include "wgt/step/pkgmgr/step_generate_xml.h"
 #include "wgt/step/security/step_check_settings_level.h"
 #include "wgt/step/security/step_check_wgt_background_category.h"
@@ -235,6 +236,7 @@ HybridInstaller::HybridInstaller(common_installer::PkgMgrPtr pkgmgr)
       AddStep<ci::configuration::StepParseManifest>(
           ci::configuration::StepParseManifest::ManifestLocation::PACKAGE,
           ci::configuration::StepParseManifest::StoreLocation::NORMAL);
+      AddStep<wgt::filesystem::StepWgtUndoPatchStorageDirectories>();
       AddStep<hybrid::configuration::StepStashTpkConfig>();
       AddStep<ci::configuration::StepParseManifest>(
           ci::configuration::StepParseManifest::ManifestLocation::INSTALLED,
index b3b8475..1ee6037 100644 (file)
@@ -1162,6 +1162,77 @@ TEST_F(SmokeTest, MigrateLegacyExternalImageMode) {
   ValidateExternalPackage(pkgid, {appid});
 }
 
+TEST_F(SmokeTest, SharedRes24) {
+  bf::path path = kSmokePackagesDirectory / "SharedRes24.wgt";
+  std::string pkgid = "smokeSh2xx";
+  std::string appid = "smokeSh2xx.SharedRes24";
+  ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK);
+  ValidatePackage(pkgid, {appid});
+  bf::path root_path = ci::GetRootAppPath(false, kTestUserId);
+  ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "NOT-SHARED-WGT"));  // NOLINT
+  ASSERT_FALSE(bf::exists(root_path / pkgid / "shared" / "res" / "NOT-SHARED-WGT"));  // NOLINT
+}
+
+TEST_F(SmokeTest, SharedRes30) {
+  bf::path path = kSmokePackagesDirectory / "SharedRes30.wgt";
+  std::string pkgid = "smokeSh3xx";
+  std::string appid = "smokeSh3xx.SharedRes30";
+  ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK);
+  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
+}
+
+TEST_F(SmokeTest, SharedRes30Delta) {
+  bf::path path = kSmokePackagesDirectory / "SharedRes30Delta.wgt";
+  bf::path delta_package = kSmokePackagesDirectory / "SharedRes30Delta.delta";
+  std::string pkgid = "smokeSh3De";
+  std::string appid = "smokeSh3De.SharedRes30Delta";
+  ASSERT_EQ(DeltaInstall(path, delta_package, PackageType::WGT),
+            ci::AppInstaller::Result::OK);
+  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_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
+}
+
+TEST_F(SmokeTest, SharedRes30Hybrid) {
+  bf::path path = kSmokePackagesDirectory / "SharedRes30Hybrid.wgt";
+  std::string pkgid = "smokeSh3Hy";
+  std::string appid1 = "smokeSh3Hy.SharedRes30Hybrid";
+  std::string appid2 = "smokeSh3Hy.sharedres30hybridserivce";
+  ASSERT_EQ(Install(path, PackageType::HYBRID), ci::AppInstaller::Result::OK);
+  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_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) {
+  bf::path path = kSmokePackagesDirectory / "SharedRes30HybridDelta.wgt";
+  bf::path delta_package = kSmokePackagesDirectory / "SharedRes30HybridDelta.delta";
+  std::string pkgid = "smokeSh3HD";
+  std::string appid1 = "smokeSh3HD.SharedRes30HybridDelta";
+  std::string appid2 = "smokeSh3HD.sharedres30hybriddeltaserivce";
+  ASSERT_EQ(DeltaInstall(path, delta_package, PackageType::HYBRID),
+            ci::AppInstaller::Result::OK);
+  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_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 common_installer
 
 int main(int argc,  char** argv) {
diff --git a/src/unit_tests/test_samples/smoke/SharedRes24.wgt b/src/unit_tests/test_samples/smoke/SharedRes24.wgt
new file mode 100644 (file)
index 0000000..782e7e9
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/SharedRes24.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/SharedRes30.wgt b/src/unit_tests/test_samples/smoke/SharedRes30.wgt
new file mode 100644 (file)
index 0000000..e235841
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/SharedRes30.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/SharedRes30Delta.delta b/src/unit_tests/test_samples/smoke/SharedRes30Delta.delta
new file mode 100644 (file)
index 0000000..26e28bf
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/SharedRes30Delta.delta differ
diff --git a/src/unit_tests/test_samples/smoke/SharedRes30Delta.wgt b/src/unit_tests/test_samples/smoke/SharedRes30Delta.wgt
new file mode 100644 (file)
index 0000000..f73d723
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/SharedRes30Delta.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/SharedRes30Delta_2.wgt b/src/unit_tests/test_samples/smoke/SharedRes30Delta_2.wgt
new file mode 100644 (file)
index 0000000..6f52919
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/SharedRes30Delta_2.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/SharedRes30Hybrid.wgt b/src/unit_tests/test_samples/smoke/SharedRes30Hybrid.wgt
new file mode 100644 (file)
index 0000000..2aa90d3
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/SharedRes30Hybrid.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/SharedRes30HybridDelta.delta b/src/unit_tests/test_samples/smoke/SharedRes30HybridDelta.delta
new file mode 100644 (file)
index 0000000..93d0374
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/SharedRes30HybridDelta.delta differ
diff --git a/src/unit_tests/test_samples/smoke/SharedRes30HybridDelta.wgt b/src/unit_tests/test_samples/smoke/SharedRes30HybridDelta.wgt
new file mode 100644 (file)
index 0000000..b60b43c
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/SharedRes30HybridDelta.wgt differ
diff --git a/src/unit_tests/test_samples/smoke/SharedRes30HybridDelta_2.wgt b/src/unit_tests/test_samples/smoke/SharedRes30HybridDelta_2.wgt
new file mode 100644 (file)
index 0000000..6399c85
Binary files /dev/null and b/src/unit_tests/test_samples/smoke/SharedRes30HybridDelta_2.wgt differ
index 2e897b8..cb8a221 100644 (file)
@@ -29,9 +29,10 @@ common_installer::Step::Status StepWgtPatchStorageDirectories::process() {
   if (!CreatePrivateTmpDir())
     return Status::APP_DIR_ERROR;
 
-  char version = context_->manifest_data.get()->api_version[0];
-  if ((version-'0') >= 3) {
-    LOG(DEBUG) << "Copying widget's shared/ directory";
+  int version = std::stoi(context_->manifest_data.get()->api_version);
+  if (version >= 3) {
+    LOG(DEBUG) << "Symlinking widget's shared/res directory content in "
+        << context_->pkg_path.get();
     if (!ShareDirFor3x())
       return Status::APP_DIR_ERROR;
   }
@@ -40,6 +41,12 @@ common_installer::Step::Status StepWgtPatchStorageDirectories::process() {
 }
 
 bool StepWgtPatchStorageDirectories::ShareDirFor3x() {
+  // check if ${pkg_path}/res/wgt/shared/res exists
+  bf::path wgt_shared_res_dir =
+      context_->pkg_path.get() / kResWgtSubPath / kSharedResLocation;
+  if (!bf::exists(wgt_shared_res_dir))
+    return true;
+  // create ${pkg_path}/shared/res
   bf::path shared_dir = context_->pkg_path.get() / kSharedLocation;
   if (!bf::exists(shared_dir)) {
     bs::error_code error;
@@ -49,35 +56,67 @@ bool StepWgtPatchStorageDirectories::ShareDirFor3x() {
       return false;
     }
   }
-  bf::path src = context_->pkg_path.get() / kResWgtSubPath / kSharedResLocation;
-  if (!bf::exists(src))
-    return true;
-  if (!bf::is_directory(src)) {
-    LOG(WARNING) << "Widget's shared/res/ is not directory";
-    return true;
+  bf::path shared_res_dir = context_->pkg_path.get() / kSharedResLocation;
+  if (!bf::exists(shared_res_dir)) {
+    bs::error_code error;
+    bf::create_directory(shared_res_dir, error);
+    if (error) {
+      LOG(ERROR) << "Failed to create directory: " << shared_res_dir;
+      return false;
+    }
   }
-  bf::path dst = context_->pkg_path.get() / kSharedResLocation;
-  if (!common_installer::MoveDir(src, dst,
-                                 common_installer::FS_MERGE_SKIP)) {
-    LOG(ERROR) << "Failed to move shared data from res/wgt to shared";
-    return false;
+  // link all ${pkg_path}/res/wgt/shared/res content 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;
+    }
   }
-
-  bs::error_code error_code;
-  bf::create_symlink(dst, src, error_code);
-  if (error_code) {
-    LOG(ERROR) << "Failed to create symbolic link for shared dir"
-               << boost::system::system_error(error_code).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)) {
+      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;
+    }
+    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;
+    }
   }
   return true;
 }
 
 bool StepWgtPatchStorageDirectories::CreatePrivateTmpDir() {
-  bs::error_code error_code;
   bf::path tmp_path = context_->pkg_path.get() / kTemporaryData;
-  bf::create_directory(tmp_path, error_code);
-  if (error_code) {
+  if (bf::exists(tmp_path) && bf::is_directory(tmp_path)) {
+    return true;
+  }
+  bs::error_code error;
+  bf::create_directory(tmp_path, error);
+  if (error) {
     LOG(ERROR) << "Failed to create private temporary directory for package";
     return false;
   }
index 035936b..96c5da6 100644 (file)
@@ -13,8 +13,9 @@ namespace filesystem {
 
 /**
  * \brief Installation (WGT).
- *        Responsible for copying widgets shared/ directory into package's
- *        shared/ directory for tizen widget with api version >= 3.0
+ *        Responsible for linking the content of widget's shared/res directory
+ *        into package's shared/res directory and vice versa for Tizen widget
+ *        with API version >= 3.0
  */
 class StepWgtPatchStorageDirectories :
     public common_installer::Step {
diff --git a/src/wgt/step/filesystem/step_wgt_undo_patch_storage_directories.cc b/src/wgt/step/filesystem/step_wgt_undo_patch_storage_directories.cc
new file mode 100644 (file)
index 0000000..241b2ca
--- /dev/null
@@ -0,0 +1,94 @@
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "wgt/step/filesystem/step_wgt_undo_patch_storage_directories.h"
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+#include <boost/system/error_code.hpp>
+
+#include <common/utils/file_util.h>
+
+namespace bf = boost::filesystem;
+namespace bs = boost::system;
+
+namespace {
+
+const char kSharedLocation[] = "shared";
+const char kSharedResLocation[] = "shared/res";
+const char kResWgtSubPath[] = "res/wgt";
+
+}  // namespace
+
+namespace wgt {
+namespace filesystem {
+
+common_installer::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 "
+        << context_->pkg_path.get();
+    if (!UndoShareDirFor3x())
+      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;
+  bf::path wgt_shared_res_dir =
+      context_->pkg_path.get() / kResWgtSubPath / kSharedResLocation;
+  if (!bf::exists(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;
+      }
+    }
+  }
+  // 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;
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+}  // namespace filesystem
+}  // namespace wgt
diff --git a/src/wgt/step/filesystem/step_wgt_undo_patch_storage_directories.h b/src/wgt/step/filesystem/step_wgt_undo_patch_storage_directories.h
new file mode 100644 (file)
index 0000000..382ab72
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef WGT_STEP_FILESYSTEM_STEP_WGT_UNDO_PATCH_STORAGE_DIRECTORIES_H_
+#define WGT_STEP_FILESYSTEM_STEP_WGT_UNDO_PATCH_STORAGE_DIRECTORIES_H_
+
+#include <common/step/step.h>
+#include <manifest_parser/utils/logging.h>
+
+namespace wgt {
+namespace filesystem {
+
+/**
+ * \brief Installation (WGT).
+ *        Responsible for unlinking the content of widget's shared/res directory
+ *        into package's shared/res directory and vice versa for Tizen widget
+ *        with API version >= 3.0
+ */
+class StepWgtUndoPatchStorageDirectories :
+    public common_installer::Step {
+ public:
+  using Step::Step;
+
+  Status process() override;
+  Status clean() override { return Status::OK; }
+  Status undo() override { return Status::OK; }
+  Status precheck() override { return Status::OK; }
+
+ private:
+  bool UndoShareDirFor3x();
+
+  STEP_NAME(UndoPatchWgtStorageDirectories)
+};
+
+}  // namespace filesystem
+}  // namespace wgt
+
+#endif  // WGT_STEP_FILESYSTEM_STEP_WGT_UNDO_PATCH_STORAGE_DIRECTORIES_H_
index 0590038..3fe6b24 100755 (executable)
@@ -91,6 +91,7 @@
 #include "wgt/step/filesystem/step_wgt_patch_storage_directories.h"
 #include "wgt/step/filesystem/step_wgt_prepare_package_directory.h"
 #include "wgt/step/filesystem/step_wgt_resource_directory.h"
+#include "wgt/step/filesystem/step_wgt_undo_patch_storage_directories.h"
 #include "wgt/step/filesystem/step_wgt_update_package_directory.h"
 #include "wgt/step/pkgmgr/step_generate_xml.h"
 #include "wgt/step/security/step_add_default_privileges.h"
@@ -257,6 +258,7 @@ WgtInstaller::WgtInstaller(ci::PkgMgrPtr pkgrmgr)
       AddStep<ci::configuration::StepParsePreload>();
       AddStep<ci::configuration::StepCheckTizenVersion>();
       AddStep<ci::filesystem::StepEnableExternalMount>();
+      AddStep<wgt::filesystem::StepWgtUndoPatchStorageDirectories>();
       AddStep<ci::filesystem::StepDeltaPatch>("res/wgt/");
       AddStep<ci::filesystem::StepDisableExternalMount>();
       AddStep<wgt::configuration::StepCheckStartFiles>();