tpk: Replace common StepGenerateXml to new StepCopyManifestXml 69/43369/4 accepted/tizen/mobile/20150710.080317 accepted/tizen/tv/20150710.080329 accepted/tizen/wearable/20150710.080343 submit/tizen/20150710.061944
authorYoumin Ha <youmin.ha@samsung.com>
Wed, 8 Jul 2015 07:49:49 +0000 (16:49 +0900)
committerSangyoon Jang <s89.jang@samsung.com>
Fri, 10 Jul 2015 05:01:18 +0000 (22:01 -0700)
Current common StepGenerateXml doesn't recover full spec of the original
xml. This commit directly copies the original tizen-manifest.xml to the
destination directory.
This commit fixes the TCT failure, which can't install the TCT apps.

Change-Id: Ic6568509e864c79247c7cc16f5ca9cafc3324d8f
Signed-off-by: Youmin Ha <youmin.ha@msamsung.com>
packaging/app-installers.spec
src/common/pkgmgr_registration.cc
src/common/step/step_generate_xml.cc
src/tpk/CMakeLists.txt
src/tpk/step/step_copy_manifest_xml.cc [new file with mode: 0644]
src/tpk/step/step_copy_manifest_xml.h [new file with mode: 0644]
src/tpk/step/step_create_symbolic_link.cc
src/tpk/task.cc

index 0eb5604..d42505b 100644 (file)
@@ -4,7 +4,7 @@
 Name:           app-installers
 Summary:        Application installers
 Version:        1.0
-Release:        1
+Release:        2
 Group:          Application Framework/Package Management
 License:        Apache-2.0
 Source0:        %{name}-%{version}.tar.gz
index aedebd2..9666c33 100644 (file)
@@ -71,12 +71,14 @@ bool RegisterAppInPkgmgr(const bf::path& xml_path,
       pkgmgr_parser_parse_manifest_for_installation(
           xml_path.c_str(), const_cast<char* const*>(kAppinstTags));
   if (ret) {
-    LOG(ERROR) << "Failed to unregister package: " << xml_path;
+    LOG(ERROR) << "Failed to register package: " << xml_path << ", "
+        "error code=" << ret;
     return false;
   }
 
   if (!!cert_info.author_certificate.get()) {
     if (!RegisterAuthorCertificate(cert_info, pkgid, uid)) {
+      LOG(ERROR) << "Failed to register author certificate";
       return false;
     }
   }
index 6bc9748..41ac592 100755 (executable)
@@ -95,7 +95,7 @@ Step::Status StepGenerateXml::GenerateApplicationCommonXml(T* app,
                                           "%s", BAD_CAST icon.c_str());
     }
   } else {
-    //Default icon setting is role of the platform
+    // Default icon setting is role of the platform
     LOG(DEBUG) << "Icon was not found in package";
   }
 
index d16b5d1..25a52e6 100644 (file)
@@ -9,6 +9,7 @@ SET(SRCS
     task.cc
     step/step_parse.cc
     step/step_create_symbolic_link.cc
+    step/step_copy_manifest_xml.cc
     ../xml_parser/xml_parser.cc
 )
 ADD_EXECUTABLE(${TARGET_TPK} ${SRCS})
@@ -25,7 +26,7 @@ ELSE(${HOSTTEST})
   ADD_DEFINITIONS(${TPK_CFLAGS})
 ENDIF(${HOSTTEST})
 
-APPLY_PKG_CONFIG(${TARGET_TPK} PUBLIC PKGMGR_DEPS)
-TARGET_LINK_LIBRARIES(${TARGET_TPK} PUBLIC ${TARGET_LIBNAME_COMMON})
+APPLY_PKG_CONFIG(${TARGET_TPK} PUBLIC PKGMGR_DEPS Boost)
+TARGET_LINK_LIBRARIES(${TARGET_TPK} PUBLIC ${TARGET_LIBNAME_COMMON} -lboost_regex)
 
 INSTALL(TARGETS ${TARGET_TPK} DESTINATION ${BINDIR})
diff --git a/src/tpk/step/step_copy_manifest_xml.cc b/src/tpk/step/step_copy_manifest_xml.cc
new file mode 100644 (file)
index 0000000..2df0818
--- /dev/null
@@ -0,0 +1,190 @@
+/* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */
+
+#include "tpk/step/step_copy_manifest_xml.h"
+
+#include <sys/types.h>
+#include <pkgmgr-info.h>
+#include <boost/filesystem.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/tr1/regex.hpp>
+
+#include <fstream>
+#include <iostream>
+#include <memory>
+#include <regex>
+#include <string>
+
+#include "common/utils/file_util.h"
+#include "common/utils/logging.h"
+
+namespace bf = boost::filesystem;
+using common_installer::Step;
+
+namespace {
+  const char* source_xml_filename = "tizen-manifest.xml";
+
+  bf::path _getOldDestXmlPath(const bf::path& dest_xml_path) {
+    bf::path old_dest_xml_path = dest_xml_path;
+    old_dest_xml_path += ".old";
+    return old_dest_xml_path;
+  }
+
+  bool _setValidSourceXmlPath(bf::path* source_xml_path_,
+      const common_installer::ContextInstaller* context_) {
+    bf::path& source_xml_path = *source_xml_path_;
+    source_xml_path = context_->pkg_path.get() / source_xml_filename;
+    if (!bf::exists(source_xml_path)) {
+      // Check single app path
+      source_xml_path = context_->pkg_path.get() /
+          context_->manifest_data.get()->mainapp_id / source_xml_filename;
+      if (!bf::exists(source_xml_path)) {
+        LOG(ERROR) << "Source xml file not found: " << source_xml_path;
+        return false;
+      }
+    }
+    return true;
+  }
+
+  void _setDestXmlPath(std::shared_ptr<bf::path>* dest_xml_path_, uid_t uid,
+      const std::string& pkgid) {
+    *dest_xml_path_ = std::make_shared<bf::path>(getUserManifestPath(uid));
+    **dest_xml_path_ /= bf::path(pkgid);
+    **dest_xml_path_ += ".xml";
+  }
+
+
+  bool _trimCopiedXmlContent(const bf::path& xml_path,
+      const common_installer::ContextInstaller* context_) {
+    bf::path pkg_path = context_->pkg_path.get();
+
+    std::ifstream infile(xml_path.string());
+    std::ofstream outfile(xml_path.string() + ".out");
+    std::string line;
+    std::string result;
+
+    boost::regex appid_pattern(".*<(ui|service)-application\\s+(\\S+\\s+)*"
+        "appid=\"(.+?)\".*>", boost::regex_constants::ECMAScript);
+    boost::regex appid_exec_replace_pattern("exec=\"(.+?)\"",
+        boost::regex_constants::ECMAScript);
+    boost::regex manifest_pattern(".*<manifest\\s+.*(type=\"\"){0,1}.*>",
+        boost::regex_constants::ECMAScript);
+    boost::regex manifest_type_replace_pattern("<manifest ",
+        boost::regex_constants::ECMAScript);
+
+    boost::smatch m;
+
+    while (!infile.eof()) {
+      getline(infile, line);
+      result = line;  // Copy line by default
+
+      try {
+        // Find (ui|service)-application element, and get appid
+        if (boost::regex_search(line, m, appid_pattern)) {
+          std::string appid = m[3].str();
+          pkg_path /= bf::path(appid);
+          pkg_path /= bf::path("bin");
+
+          result = boost::regex_replace(line, appid_exec_replace_pattern,
+              std::string("exec=\"") + pkg_path.string() +
+              std::string("/$1\""));
+
+        } else if (boost::regex_search(line, m, manifest_pattern)) {
+          // Check if the 'type=' attribute is not given
+          LOG(DEBUG) << "found manifest";
+          if (m[1].str().size() == 0) {
+            // Add an attribute
+            result = boost::regex_replace(line,
+                manifest_type_replace_pattern,
+                std::string("<manifest type=\"tpk\" "));
+            LOG(DEBUG) << "Found no type attribute. changed:" << result;
+          }
+        }
+      } catch (boost::regex_error& e) {
+        LOG(ERROR) << "Regex error:" << e.what() << ":" << e.code();
+        return false;
+      }
+
+      // Write file
+      outfile << result << std::endl;
+    }
+
+    // Change old file to new file
+    bf::remove(xml_path);
+    bf::rename(xml_path.string() + ".out", xml_path);
+
+    return true;
+  }
+}  // namespace
+
+
+namespace tpk {
+namespace step {
+
+SCOPE_LOG_TAG(TPKCopyManifestXml)
+
+typedef common_installer::Step::Status Status;
+
+Status StepCopyManifestXml::process() {
+  // Set source xml path
+  bf::path source_xml_path;
+  if (!_setValidSourceXmlPath(&source_xml_path, context_))
+    return Status::ERROR;
+
+  // Create destination xml path
+  _setDestXmlPath(&(this->dest_xml_path_), context_->uid.get(),
+      context_->pkgid.get());
+  bf::path& dest_xml_path = *dest_xml_path_;
+  if (!common_installer::CreateDir(dest_xml_path.parent_path())) {
+    LOG(ERROR) << "Destionation directory creation failure" << dest_xml_path;
+    return Status::ERROR;
+  }
+
+  // Backup old xml file if exists
+  if (bf::exists(dest_xml_path)) {
+    common_installer::MoveFile(dest_xml_path,
+        _getOldDestXmlPath(dest_xml_path));
+  }
+
+  // Copy xml file
+  boost::system::error_code boost_err;
+  bf::copy_file(source_xml_path, dest_xml_path, boost_err);
+  if (boost_err) {
+    LOG(ERROR) << "Manifest xml copy failure, from " << source_xml_path <<
+        " to " << dest_xml_path << ", error_code=" << boost_err;
+    return Status::ERROR;
+  }
+
+  // Trim xml file content
+  if (!_trimCopiedXmlContent(dest_xml_path, context_)) return Status::ERROR;
+
+  // Set dest_xml_path (to be used by StepRegisterApplication)
+  context_->xml_path.set(dest_xml_path.string());
+
+  return Status::OK;
+}
+
+
+Status StepCopyManifestXml::clean() {
+  // Delete old xml file if exists
+  bf::path old_dest_xml_path = _getOldDestXmlPath(*dest_xml_path_);
+  if (bf::exists(old_dest_xml_path)) bf::remove(old_dest_xml_path);
+
+  return Status::OK;
+}
+
+
+Status StepCopyManifestXml::undo() {
+  // Remove xml file
+  if (bf::exists(*dest_xml_path_)) bf::remove(*dest_xml_path_);
+
+  // Revert old xml file if exists
+  bf::path old_dest_xml_path = _getOldDestXmlPath(*dest_xml_path_);
+  if (bf::exists(old_dest_xml_path)) {
+    common_installer::MoveFile(old_dest_xml_path, *dest_xml_path_);
+  }
+
+  return Status::OK;
+}
+
+}  // namespace step
+}  // namespace tpk
diff --git a/src/tpk/step/step_copy_manifest_xml.h b/src/tpk/step/step_copy_manifest_xml.h
new file mode 100644 (file)
index 0000000..924ddb6
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef TPK_STEP_STEP_COPY_MANIFEST_XML_H_
+#define TPK_STEP_STEP_COPY_MANIFEST_XML_H_
+
+/* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */
+// Copyright (c) 2016 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.h"
+#include <boost/filesystem.hpp>
+
+#include <memory>
+
+namespace tpk {
+namespace step {
+
+/** Copy tizen-manifest.xml into the application directory
+ *
+ */
+class StepCopyManifestXml : public common_installer::Step {
+ public:
+  using Step::Step;
+  Status precheck() override { return Status::OK; }
+  Status process() override;
+  Status clean() override;
+  Status undo() override;
+
+ private:
+  std::shared_ptr<boost::filesystem::path> dest_xml_path_;
+};
+
+}  // namespace step
+}  // namespace tpk
+
+#endif  // TPK_STEP_STEP_COPY_MANIFEST_XML_H_
index f89a7bd..7ec0cee 100644 (file)
@@ -1,7 +1,11 @@
 /* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */
 #include "tpk/step/step_create_symbolic_link.h"
 #include <boost/filesystem.hpp>
+#include <boost/system/error_code.hpp>
+#include <pkgmgr-info.h>
+
 #include <iostream>
+
 #include "common/step/step.h"
 #include "common/app_installer.h"
 #include "common/context_installer.h"
@@ -22,37 +26,68 @@ namespace {
 
 template <typename T>
 bool CreateSymLink(T *app, ContextInstaller* context) {
-  boost::system::error_code error;
+  boost::system::error_code boost_error;
 
   for (; app != nullptr; app=app->next) {
     fs::path bindir = context->pkg_path.get() / fs::path(app->appid) /
         fs::path("bin");
     LOG(INFO) << "Creating dir: " << bindir;
     if (!common_installer::CreateDir(bindir)) {
-      LOG(ERROR) << "Directory creation failure";
+      LOG(ERROR) << "Directory creation failure: " << bindir;
       return false;
     }
 
+    // Exec path
     // Make a symlink with the name of appid, pointing exec file
     fs::path symlink_path = bindir / fs::path(app->appid);
     LOG(INFO) << "Creating symlink " << symlink_path << " pointing " <<
         app->exec;
-    fs::create_symlink(fs::path(app->exec), symlink_path, error);
-    if (error) {
-      LOG(ERROR) << "Symlink creation failure";
+    fs::create_symlink(fs::path(app->exec), symlink_path, boost_error);
+    if (boost_error) {
+      LOG(ERROR) << "Symlink creation failure: " << symlink_path;
       return false;
     }
 
-    // Give a execution permission to the original executable
+    // Give an execution permission to the original executable
     fs::path exec_path = bindir / fs::path(app->exec);
     LOG(INFO) << "Giving exec permission to " << exec_path;
     fs::permissions(exec_path, fs::owner_all |
         fs::group_read | fs::group_exe |
-        fs::others_read | fs::others_exe, error);
-    if (error) {
+        fs::others_read | fs::others_exe, boost_error);
+    if (boost_error) {
       LOG(ERROR) << "Permission change failure";
       return false;
     }
+
+    // Icon path
+    // Make an Icon symlink, if the icon exists
+    if (app->icon && app->icon->name) {
+      // Check if the icon file actually exists
+      fs::path src_icon_path = fs::path(context->pkg_path.get())
+          / fs::path(app->appid)
+          / fs::path(app->icon->name);
+      if (fs::exists(src_icon_path)) {
+        // copy icon to the destination dir
+        fs::path dest_icon_dir = fs::path(getIconPath(context->uid.get()));
+        fs::path dest_icon_filename = fs::path(app->appid) +=
+            fs::path(app->icon->name).extension();
+        if (!common_installer::CreateDir(dest_icon_dir)) {
+          LOG(ERROR) << "Directory creation failure: " << dest_icon_dir;
+          return false;
+        }
+        fs::path dest_icon_path = dest_icon_dir;
+        dest_icon_path /= dest_icon_filename;
+        LOG(INFO) << "Creating symlink " << dest_icon_path << " pointing " <<
+            src_icon_path;
+        fs::create_symlink(src_icon_path, dest_icon_path, boost_error);
+        if (boost_error) {
+          LOG(ERROR) << "Symlink creation failure: " << dest_icon_path;
+          return false;
+        }
+      } else {
+        LOG(WARNING) << "No icon file found in the package: " << src_icon_path;
+      }
+    }
   }
   return true;
 }
@@ -61,7 +96,7 @@ bool CreateSymLink(T *app, ContextInstaller* context) {
 template <typename T>
 bool RemoveSymLink(T *app, ContextInstaller* context) {
   /* NOTE: Unlike WRT app, tpk apps have bin/ directory by default.
-   * So we don't remove the bin/ directory itself.
+   * So we don't remove the bin/ directory.
    */
   for (; app != nullptr; app=app->next) {
     fs::path exec_path = fs::path(context->pkg_path.get()) /
@@ -74,7 +109,6 @@ bool RemoveSymLink(T *app, ContextInstaller* context) {
 }  // namespace
 
 
-
 Status StepCreateSymbolicLink::process() {
   // Get manifest_x
   manifest_x *m = context_->manifest_data.get();
index d817fff..0db2244 100644 (file)
@@ -24,8 +24,9 @@
 #include "common/step/step_unzip.h"
 #include "common/step/step_update_app.h"
 #include "common/step/step_update_security.h"
-#include "tpk/step/step_parse.h"
+#include "tpk/step/step_copy_manifest_xml.h"
 #include "tpk/step/step_create_symbolic_link.h"
+#include "tpk/step/step_parse.h"
 #include "common/utils/logging.h"
 #endif
 
@@ -100,7 +101,7 @@ int Task::Install() {
   ai.AddStep<ci::create_storage::StepCreateStorageDirectories>();
   ai.AddStep<tpk::step::StepCreateSymbolicLink>();
   ai.AddStep<ci::security::StepRegisterSecurity>();
-  ai.AddStep<ci::generate_xml::StepGenerateXml>();
+  ai.AddStep<tpk::step::StepCopyManifestXml>();
   ai.AddStep<ci::register_app::StepRegisterApplication>();
 
   return ai.Run();
@@ -120,7 +121,7 @@ int Task::Update() {
   ai.AddStep<ci::copy_storage::StepCopyStorageDirectories>();
   ai.AddStep<tpk::step::StepCreateSymbolicLink>();
   ai.AddStep<ci::update_security::StepUpdateSecurity>();
-  ai.AddStep<ci::generate_xml::StepGenerateXml>();
+  ai.AddStep<tpk::step::StepCopyManifestXml>();
   ai.AddStep<ci::update_app::StepUpdateApplication>();
 
   return ai.Run();