[CopyBackup] Added step for update installation 26/38926/1
authorTomasz Iwanek <t.iwanek@samsung.com>
Wed, 25 Mar 2015 12:34:45 +0000 (13:34 +0100)
committerTomasz Iwanek <t.iwanek@samsung.com>
Thu, 30 Apr 2015 11:21:47 +0000 (13:21 +0200)
Tizen-JIRA: TC-2482

Change-Id: I8c366e911b218ec363959812db7b0e268b8da4ae

src/common/CMakeLists.txt
src/common/step/step_copy_backup.cc [new file with mode: 0644]
src/common/step/step_copy_backup.h [new file with mode: 0644]
src/utils/file_util.cc

index 1da40c8..b1f070c 100644 (file)
@@ -11,6 +11,7 @@ SET(SRCS
   step/step_check_signature.cc
   step/step_configure.cc
   step/step_copy.cc
+  step/step_copy_backup.cc
   step/step_generate_xml.cc
   step/step_register_app.cc
   step/step_old_manifest.cc
diff --git a/src/common/step/step_copy_backup.cc b/src/common/step/step_copy_backup.cc
new file mode 100644 (file)
index 0000000..4466f31
--- /dev/null
@@ -0,0 +1,128 @@
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "common/step/step_copy_backup.h"
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/system/error_code.hpp>
+
+#include <cassert>
+#include <string>
+
+#include "utils/file_util.h"
+
+namespace common_installer {
+namespace copy_backup {
+
+namespace bf = boost::filesystem;
+namespace bs = boost::system;
+
+Step::Status StepCopyBackup::process() {
+  assert(!context_->pkgid.get().empty());
+
+  // set application path
+  context_->application_path.set(
+      context_->root_application_path.get() / context_->pkgid.get());
+
+  // set paths
+  install_path_ = context_->application_path.get();
+  context_->pkg_path.set(install_path_.string());
+
+  // FIXME: correctly order app's data.
+  // If there is 1 app in package, app's data are stored in <pkg_path>/<app_id>
+  // If there are >1 apps in package, app's data are stored in <pkg_path>
+  // considering that multiple apps data are already separated in folders.
+  if (context_->manifest_data.get()->uiapplication &&
+      !context_->manifest_data.get()->uiapplication->next)
+    install_path_ /= bf::path(context_->manifest_data.get()->mainapp_id);
+
+  backup_path_ = context_->pkg_path.get();
+  backup_path_ += ".bck";
+
+  // backup old content
+  if (!utils::MoveDir(context_->pkg_path.get(), backup_path_)) {
+    LOG(ERROR) << "Fail to backup widget directory";
+    return Step::Status::ERROR;
+  }
+  LOG(INFO) << "Old widget context saved to: " << backup_path_;
+
+  // copy new content
+  bs::error_code error;
+  bf::create_directories(install_path_.parent_path(), error);
+  if (error) {
+    LOG(ERROR) << "Cannot create widget directory";
+    return Status::ERROR;
+  }
+  if (!utils::MoveDir(context_->unpacked_dir_path.get(), install_path_)) {
+    LOG(ERROR) << "Fail to copy tmp dir: " << context_->unpacked_dir_path.get()
+               << " to dst dir: " << install_path_;
+    return Step::Status::ERROR;
+  }
+
+  LOG(INFO) << "Successfully move: " << context_->unpacked_dir_path.get()
+            << " to: " << install_path_ << " directory";
+  return Status::OK;
+}
+
+Step::Status StepCopyBackup::clean() {
+  assert(!backup_path_.empty());
+  assert(!install_path_.empty());
+
+  if (!CleanBackupDirectory()) {
+    LOG(DEBUG) << "Cannot remove backup directory";
+    return Status::ERROR;
+  }
+  LOG(DEBUG) << "Applications files backup directory removed";
+
+  return Status::OK;
+}
+
+Step::Status StepCopyBackup::undo() {
+  assert(!backup_path_.empty());
+  assert(!install_path_.empty());
+
+  // TODO(t.iwanek): this should be done in StepUnzip
+  bs::error_code error;
+  LOG(DEBUG) << "Remove tmp dir: " << context_->unpacked_dir_path.get();
+  bf::remove_all(context_->unpacked_dir_path.get(), error);  // ignore error
+
+  // if backup was created then restore files
+  if (bf::exists(backup_path_)) {
+    if (!RollbackApplicationDirectory()) {
+      LOG(ERROR) << "Failed to revert widget directory";
+      return Status::ERROR;
+    }
+    LOG(DEBUG) << "Application files reverted from backup";
+  }
+  return Status::OK;
+}
+
+bool StepCopyBackup::CleanBackupDirectory() {
+  if (bf::exists(backup_path_)) {
+    bs::error_code error;
+    bf::remove_all(backup_path_, error);
+    if (error)
+      return false;
+  }
+  return true;
+}
+
+bool StepCopyBackup::RollbackApplicationDirectory() {
+  bs::error_code error;
+  if (bf::exists(context_->pkg_path.get())) {
+    bf::remove_all(context_->pkg_path.get(), error);
+    if (error) {
+      return false;
+    }
+  }
+
+  if (!utils::MoveDir(backup_path_, context_->pkg_path.get())) {
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace copy_backup
+}  // namespace common_installer
diff --git a/src/common/step/step_copy_backup.h b/src/common/step/step_copy_backup.h
new file mode 100644 (file)
index 0000000..bd0e07a
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_STEP_STEP_COPY_BACKUP_H_
+#define COMMON_STEP_STEP_COPY_BACKUP_H_
+
+#include <boost/filesystem/path.hpp>
+
+#include "common/context_installer.h"
+#include "common/step/step.h"
+#include "utils/logging.h"
+
+namespace common_installer {
+namespace copy_backup {
+
+class StepCopyBackup : public Step {
+ public:
+  using Step::Step;
+
+  Status process() override;
+  Status clean() override;
+  Status undo() override;
+  Status precheck() override { return Status::OK; }
+
+ private:
+  bool CleanBackupDirectory();
+  bool RollbackApplicationDirectory();
+
+  boost::filesystem::path install_path_;
+  boost::filesystem::path backup_path_;
+
+  SCOPE_LOG_TAG(CopyBackup)
+};
+
+}  // namespace copy_backup
+}  // namespace common_installer
+
+#endif  // COMMON_STEP_STEP_COPY_BACKUP_H_
index b61ec84..1638ac4 100644 (file)
@@ -70,6 +70,9 @@ bool CopyDir(const fs::path& src, const fs::path& dst) {
         if (!CopyDir(current, dst / current.filename())) {
           return false;
         }
+      } else if (fs::is_symlink(current)) {
+        // Found symlink
+        fs::copy_symlink(current, dst / current.filename());
       } else {
         // Found file: Copy
         fs::copy_file(current, dst / current.filename());