<commit_before>/*
 * SessionUserPrefsMigration.cpp
 *
 * Copyright (C) 2009-19 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionUserPrefsMigration.hpp"

#include <core/json/Json.hpp>
#include <core/Settings.hpp>

#include <session/SessionOptions.hpp>
#include <session/prefs/UserPrefs.hpp>

#include <r/session/RSession.hpp>

using namespace rstudio::core;
using namespace rstudio::session::prefs;

namespace rstudio {
namespace session {
namespace modules {
namespace prefs {
namespace {

void migrateUiPrefs(const json::Object& uiPrefs, json::Object* dest)
{
   std::vector<std::string> keys = userPrefs().allKeys();
   json::Value val;
   for (const auto &key: keys)
   {
      if (key == kPanes)
      {
         // Migrate pane locations
         json::Object::iterator it = uiPrefs.find("pane_config");
         if (it != uiPrefs.end())
         {
            json::Object old = (*it).value().get_obj();
            json::Object panes;
            panes[kPanesQuadrants] = old["panes"];
            panes[kPanesTabSet1] = old["tabSet1"];
            panes[kPanesTabSet2] = old["tabSet2"];
            panes[kPanesConsoleLeftOnTop] = old["consoleLeftOnTop"];
            panes[kPanesConsoleRightOnTop] = old["consoleRightOnTop"];

            (*dest)[key] = panes;
         }
      }
      else if (key == kEditorKeybindings)
      {
         // Migrate editor keybindings (was a bunch of booleans)
         std::string keybindings;
         bool vim, emacs, sublime;
         json::getOptionalParam(uiPrefs, "use_vim_mode", false, &vim);
         json::getOptionalParam(uiPrefs, "enable_emacs_keybindings", false, &emacs);
         json::getOptionalParam(uiPrefs, "enable_sublime_keybindings", false, &sublime);
         if (vim)
         {
            keybindings = kEditorKeybindingsVim;
         }
         else if (emacs)
         {
            keybindings = kEditorKeybindingsEmacs;
         }
         else if (sublime)
         {
            keybindings = kEditorKeybindingsSublime;
         }

         if (!keybindings.empty())
         {
            (*dest)[key] = keybindings;
         }
      }
      else if (key == kFoldStyle ||
               key == kJobsTabVisibility ||
               key == kLauncherJobsSort ||
               key == kBusyDetection ||
               key == kDocOutlineShow)
      {
         // These preferences don't migrate
         continue;
      }
      else if (key == kEditorTheme)
      {
         json::Object::iterator it = uiPrefs.find("rstheme");
         if (it != uiPrefs.end())
         {
            std::string theme;
            json::getOptionalParam((*it).value().get_obj(), "name", std::string(), &theme);
            if (!theme.empty())
            {
               // We only need to preserve the name of the theme; the other theme properties will be
               // automatically derived
               (*dest)[key] = theme;
            }
         }
      }
      else if (key == kGlobalTheme)
      {
         // Migrate the global theme (formerly called "flat theme")
         std::string theme;
         json::getOptionalParam(uiPrefs, "flat_theme", std::string(), &theme);
         if (!theme.empty())
         {
            (*dest)[key] = theme;
         }
      }
      else
      {
         // Most UI prefs can just be copied to the new system without modification.
         json::Object::iterator it = uiPrefs.find(key);
         if (it != uiPrefs.end())
         {
            (*dest)[key] = (*it).value();
         }
      }
   }
}

} // anonymous namespace


core::Error migratePrefs(const FilePath& src)
{
   json::Object srcPrefs;
   json::Object destPrefs;

   // Read the old settings file
   Settings settings; 
   Error err = settings.initialize(src);
   if (err)
      return err;

   // Migrate UI prefs if present.
   std::string uiPrefs = settings.get("uiPrefs");
   if (!uiPrefs.empty())
   {
      json::Value val;
      err = json::parse(uiPrefs, ERROR_LOCATION, &val);
      if (err)
      {
         LOG_ERROR(err);
      }
      else if (val.type() == json::ObjectType)
      {
         migrateUiPrefs(val.get_obj(), &destPrefs);
      }
   }

   // Migrate .rprofile execution
   bool rprofileOnResume = settings.getBool("rprofileOnResume",
         session::options().rProfileOnResumeDefault());
   userPrefs().setRunRprofileOnResume(rprofileOnResume);

   // Migrate save action
   int saveAction = settings.getInt("saveAction", 
         session::options().saveActionDefault());
   if (saveAction == r::session::kSaveActionSave)
      destPrefs[kSaveWorkspace] = kSaveWorkspaceAlways;<commit_msg>blacklist more prefs; guard against exceptions<commit_after>/*
 * SessionUserPrefsMigration.cpp
 *
 * Copyright (C) 2009-19 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionUserPrefsMigration.hpp"

#include <core/json/Json.hpp>
#include <core/Settings.hpp>

#include <session/SessionOptions.hpp>
#include <session/prefs/UserPrefs.hpp>

#include <r/session/RSession.hpp>

using namespace rstudio::core;
using namespace rstudio::session::prefs;

namespace rstudio {
namespace session {
namespace modules {
namespace prefs {
namespace {

void migrateUiPrefs(const json::Object& uiPrefs, json::Object* dest)
{
   std::vector<std::string> keys = userPrefs().allKeys();
   json::Value val;
   for (const auto &key: keys)
   {
      if (key == kPanes)
      {
         // Migrate pane locations
         json::Object::iterator it = uiPrefs.find("pane_config");
         if (it != uiPrefs.end())
         {
            json::Object old = (*it).value().get_obj();
            json::Object panes;
            panes[kPanesQuadrants] = old["panes"];
            panes[kPanesTabSet1] = old["tabSet1"];
            panes[kPanesTabSet2] = old["tabSet2"];
            panes[kPanesConsoleLeftOnTop] = old["consoleLeftOnTop"];
            panes[kPanesConsoleRightOnTop] = old["consoleRightOnTop"];

            (*dest)[key] = panes;
         }
      }
      else if (key == kEditorKeybindings)
      {
         // Migrate editor keybindings (was a bunch of booleans)
         std::string keybindings;
         bool vim, emacs, sublime;
         json::getOptionalParam(uiPrefs, "use_vim_mode", false, &vim);
         json::getOptionalParam(uiPrefs, "enable_emacs_keybindings", false, &emacs);
         json::getOptionalParam(uiPrefs, "enable_sublime_keybindings", false, &sublime);
         if (vim)
         {
            keybindings = kEditorKeybindingsVim;
         }
         else if (emacs)
         {
            keybindings = kEditorKeybindingsEmacs;
         }
         else if (sublime)
         {
            keybindings = kEditorKeybindingsSublime;
         }

         if (!keybindings.empty())
         {
            (*dest)[key] = keybindings;
         }
      }
      else if (key == kFoldStyle ||
               key == kJobsTabVisibility ||
               key == kLauncherJobsSort ||
               key == kBusyDetection ||
               key == kDocOutlineShow ||
               key == kRmdViewerType ||
               key == kShinyViewerType ||
               key == kPlumberViewerType ||
               key == kAnsiConsoleMode)
      {
         // These preferences don't migrate
         continue;
      }
      else if (key == kEditorTheme)
      {
         json::Object::iterator it = uiPrefs.find("rstheme");
         if (it != uiPrefs.end())
         {
            std::string theme;
            json::getOptionalParam((*it).value().get_obj(), "name", std::string(), &theme);
            if (!theme.empty())
            {
               // We only need to preserve the name of the theme; the other theme properties will be
               // automatically derived
               (*dest)[key] = theme;
            }
         }
      }
      else if (key == kGlobalTheme)
      {
         // Migrate the global theme (formerly called "flat theme")
         std::string theme;
         json::getOptionalParam(uiPrefs, "flat_theme", std::string(), &theme);
         if (!theme.empty())
         {
            (*dest)[key] = theme;
         }
      }
      else
      {
         // Most UI prefs can just be copied to the new system without modification.
         json::Object::iterator it = uiPrefs.find(key);
         if (it != uiPrefs.end())
         {
            (*dest)[key] = (*it).value();
         }
      }
   }
}

} // anonymous namespace


core::Error migratePrefs(const FilePath& src)
{
   json::Object srcPrefs;
   json::Object destPrefs;

   // Read the old settings file
   Settings settings; 
   Error err = settings.initialize(src);
   if (err)
      return err;

   // Migrate UI prefs if present.
   std::string uiPrefs = settings.get("uiPrefs");
   if (!uiPrefs.empty())
   {
      json::Value val;
      err = json::parse(uiPrefs, ERROR_LOCATION, &val);
      if (err)
      {
         LOG_ERROR(err);
      }
      else if (val.type() == json::ObjectType)
      {
         // Migrate UI prefs; guard against JSON exceptions (there's a lot of potential for these
         // due to malformed or invalid prefs files from the wild)
         try
         {
            migrateUiPrefs(val.get_obj(), &destPrefs);
         }
         CATCH_UNEXPECTED_EXCEPTION
      }
   }

   // Migrate .rprofile execution
   bool rprofileOnResume = settings.getBool("rprofileOnResume",
         session::options().rProfileOnResumeDefault());
   userPrefs().setRunRprofileOnResume(rprofileOnResume);

   // Migrate save action
   int saveAction = settings.getInt("saveAction", 
         session::options().saveActionDefault());
   if (saveAction == r::session::kSaveActionSave)
      destPrefs[kSaveWorkspace] = kSaveWorkspaceAlways;
{'fraction_non_alphanumeric': 0.11768579492003763, 'fraction_numerical': 0.0024459078080903106, 'mean_word_length': 2.2342561606327958, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5624262', 'n_tokens_mistral': 3193, 'n_tokens_neox': 3119, 'n_words': 770}