Rollback for StepRemoveFiles 15/43915/2
authorTomasz Iwanek <t.iwanek@samsung.com>
Tue, 14 Jul 2015 11:23:21 +0000 (13:23 +0200)
committerPawel Sikorski <p.sikorski@samsung.com>
Wed, 15 Jul 2015 12:57:38 +0000 (05:57 -0700)
Implement rollback operations for StepRemoveFiles.
If any action after file removal fails then the old
content of package should be restored.

Icons removal was moved to another step.

Change-Id: I532ad5d03bbd99ed29db4db565a6a2ea4d96a7d4

src/common/CMakeLists.txt
src/common/step/step_remove_files.cc
src/common/step/step_remove_icons.cc [new file with mode: 0644]
src/common/step/step_remove_icons.h [new file with mode: 0644]
src/tpk/task.cc
src/wgt/wgt_backend.cc

index 9baeff3..b81d35f 100644 (file)
@@ -20,6 +20,7 @@ SET(SRCS
   step/step_register_app.cc
   step/step_old_manifest.cc
   step/step_parse.cc
+  step/step_remove_icons.cc
   step/step_remove_files.cc
   step/step_revoke_security.cc
   step/step_register_security.cc
index bc9c626..4ae1c87 100755 (executable)
@@ -2,18 +2,16 @@
 // Use of this source code is governed by an apache 2.0 license that can be
 // found in the LICENSE file.
 
-
 #include "common/step/step_remove_files.h"
 
-#include <pkgmgr-info.h>
-
-#include <cstring>
+#include <boost/system/error_code.hpp>
 
 #include "common/utils/file_util.h"
 
 namespace common_installer {
 namespace remove {
 
+namespace bs = boost::system;
 namespace fs = boost::filesystem;
 
 Step::Status StepRemoveFiles::precheck() {
@@ -30,42 +28,38 @@ Step::Status StepRemoveFiles::precheck() {
     LOG(ERROR) << "pkg_path ("
                << context_->pkg_path.get()
                << ") path does not exist";
-
-  if (context_->xml_path.get().empty())
-    LOG(ERROR) << "xml_path attribute is empty";
-  else if (!fs::exists(context_->xml_path.get()))
-    LOG(ERROR) << "xml_path ("
-               << context_->xml_path.get()
-               << ") path does not exist";
-
   // TODO(p.sikorski) check context_->uid.get()
 
   return Step::Status::OK;
 }
 
 Step::Status StepRemoveFiles::process() {
-  uiapplication_x* ui = context_->manifest_data.get()->uiapplication;
-
-  fs::remove_all(context_->pkg_path.get());
-  for (; ui != nullptr; ui = ui->next) {
-    fs::path app_icon = fs::path(getIconPath(context_->uid.get()))
-      / fs::path(ui->appid);
-    app_icon += fs::path(".png");
-    if (fs::exists(app_icon))
-      fs::remove_all(app_icon);
+  fs::path backup_path = GetBackupPathForPackagePath(context_->pkg_path.get());
+  if (!MoveDir(context_->pkg_path.get(), backup_path)) {
+    LOG(ERROR) << "Cannot remove widget files from its location";
+    return Status::ERROR;
   }
-  fs::remove_all(context_->xml_path.get());
-
-  LOG(DEBUG) << "Removing dir: " << context_->pkg_path.get();
-
+  LOG(DEBUG) << "Removed directory: " << context_->pkg_path.get();
   return Status::OK;
 }
 
 Step::Status StepRemoveFiles::clean() {
+  bs::error_code error;
+  fs::path backup_path = GetBackupPathForPackagePath(context_->pkg_path.get());
+  fs::remove_all(backup_path, error);
   return Status::OK;
 }
 
 Step::Status StepRemoveFiles::undo() {
+  fs::path backup_path = GetBackupPathForPackagePath(context_->pkg_path.get());
+  if (fs::exists(backup_path)) {
+    LOG(DEBUG) << "Restoring directory: " << context_->pkg_path.get();
+    if (!MoveDir(backup_path, context_->pkg_path.get())) {
+      LOG(ERROR) << "Cannot restore widget files";
+      return Status::OK;
+    }
+  }
+
   return Status::OK;
 }
 
diff --git a/src/common/step/step_remove_icons.cc b/src/common/step/step_remove_icons.cc
new file mode 100644 (file)
index 0000000..32d6d5a
--- /dev/null
@@ -0,0 +1,78 @@
+// Copyright (c) 2015 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 "common/step/step_remove_icons.h"
+
+#include <boost/system/error_code.hpp>
+#include <pkgmgr-info.h>
+
+#include <cstring>
+
+#include "common/utils/clist_helpers.h"
+#include "common/utils/file_util.h"
+
+namespace common_installer {
+namespace remove_icons {
+
+namespace bs = boost::system;
+namespace fs = boost::filesystem;
+
+Step::Status StepRemoveIcons::precheck() {
+  if (!context_->manifest_data.get()) {
+    LOG(ERROR) << "manifest_data attribute is empty";
+    return Status::ERROR;
+  }
+
+  return Status::OK;
+}
+
+Step::Status StepRemoveIcons::process() {
+  uiapplication_x* ui = nullptr;
+  PKGMGR_LIST_MOVE_NODE_TO_HEAD(context_->manifest_data.get()->uiapplication,
+                                ui);
+  for (; ui != nullptr; ui = ui->next) {
+    fs::path app_icon = fs::path(getIconPath(context_->uid.get()))
+      / fs::path(ui->appid);
+    app_icon += fs::path(".png");
+    if (fs::exists(app_icon)) {
+      fs::path backup_icon_file = app_icon;
+      backup_icon_file += ".bck";
+      if (!MoveFile(app_icon, backup_icon_file)) {
+        LOG(ERROR) << "Failed to create backup for icon: " << app_icon;
+        return Status::ERROR;
+      }
+      backups_.emplace_back(backup_icon_file, app_icon);
+    }
+  }
+  return Status::OK;
+}
+
+Step::Status StepRemoveIcons::clean() {
+  bs::error_code error;
+  if (!backups_.empty()) {
+    LOG(DEBUG) << "Clean up icons files...";
+    for (auto& pair : backups_) {
+      fs::remove(pair.first, error);
+      if (error) {
+        LOG(WARNING) << "Failed to remove: " << pair.first;
+      }
+    }
+  }
+  return Status::OK;
+}
+
+Step::Status StepRemoveIcons::undo() {
+  if (!backups_.empty()) {
+    LOG(DEBUG) << "Restoring icons files...";
+    for (auto& pair : backups_) {
+      if (!MoveFile(pair.first, pair.second)) {
+        LOG(ERROR) << "Failed to restore: " << pair.second;
+        // We need to try to restore all icons anyway...
+      }
+    }
+  }
+  return Status::OK;
+}
+}  // namespace remove_icons
+}  // namespace common_installer
diff --git a/src/common/step/step_remove_icons.h b/src/common/step/step_remove_icons.h
new file mode 100644 (file)
index 0000000..11094fb
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright (c) 2015 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 COMMON_STEP_STEP_REMOVE_ICONS_H_
+#define COMMON_STEP_STEP_REMOVE_ICONS_H_
+
+#include <boost/filesystem/path.hpp>
+
+#include <utility>
+#include <vector>
+
+#include "common/context_installer.h"
+#include "common/step/step.h"
+#include "common/utils/logging.h"
+
+namespace common_installer {
+namespace remove_icons {
+
+class StepRemoveIcons : public Step {
+ public:
+  using Step::Step;
+
+  Status process() override;
+  Status clean() override;
+  Status undo() override;
+  Status precheck() override;
+
+ private:
+  std::vector<std::pair<boost::filesystem::path, boost::filesystem::path>>
+      backups_;
+
+  SCOPE_LOG_TAG(RemoveIcons)
+};
+
+}  // namespace remove_icons
+}  // namespace common_installer
+
+#endif  // COMMON_STEP_STEP_REMOVE_ICONS_H_
index 353395e..5db820a 100644 (file)
@@ -17,6 +17,7 @@
 #include "common/step/step_old_manifest.h"
 #include "common/step/step_parse.h"
 #include "common/step/step_register_app.h"
+#include "common/step/step_remove_icons.h"
 #include "common/step/step_remove_files.h"
 #include "common/step/step_revoke_security.h"
 #include "common/step/step_register_security.h"
@@ -135,6 +136,7 @@ int Task::Uninstall() {
   ai.AddStep<ci::parse::StepParse>();
   ai.AddStep<ci::unregister_app::StepUnregisterApplication>();
   ai.AddStep<ci::remove::StepRemoveFiles>();
+  ai.AddStep<ci::remove_icons::StepRemoveIcons>();
   ai.AddStep<ci::revoke_security::StepRevokeSecurity>();
 
   return ai.Run();
index 422ace9..dfd867b 100644 (file)
@@ -17,6 +17,7 @@
 #include "common/step/step_generate_xml.h"
 #include "common/step/step_parse.h"
 #include "common/step/step_register_app.h"
+#include "common/step/step_remove_icons.h"
 #include "common/step/step_remove_files.h"
 #include "common/step/step_revoke_security.h"
 #include "common/step/step_register_security.h"
@@ -86,6 +87,7 @@ int main(int argc, char** argv) {
       installer.AddStep<ci::parse::StepParse>();
       installer.AddStep<ci::unregister_app::StepUnregisterApplication>();
       installer.AddStep<ci::remove::StepRemoveFiles>();
+      installer.AddStep<ci::remove_icons::StepRemoveIcons>();
       installer.AddStep<ci::revoke_security::StepRevokeSecurity>();
       break;
     }