<commit_before>## --- BEGIN LICENSE BLOCK ---
# Copyright (c) 2016-present WeWantToKnow AS
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
## --- END LICENSE BLOCK ---

require 'u3d/utils'

module U3d
  UNITY_DIR_CHECK = /Unity_\d+\.\d+\.\d+[a-z]\d+/
  UNITY_DIR_CHECK_LINUX = /unity-editor-\d+\.\d+\.\d+[a-z]\d+\z/

  class Installation
    attr_reader :root_path

    def initialize(root_path: nil, path: nil)
      @root_path = root_path
      @path = path
    end

    def self.create(root_path: nil, path: nil)
      UI.deprecated("path is deprecated. Use root_path instead") unless path.nil?
      if Helper.mac?
        MacInstallation.new(root_path: root_path, path: path)
      elsif Helper.linux?
        LinuxInstallation.new(root_path: root_path, path: path)
      else
        WindowsInstallation.new(root_path: root_path, path: path)
      end
    end
  end

  class PlaybackEngineUtils
    def self.list_module_configs(playbackengine_parent_path)
      Dir.glob("#{playbackengine_parent_path}/PlaybackEngines/*/ivy.xml")
    end

    def self.node_value(config_path, node_name)
      require 'rexml/document'
      UI.verbose("reading #{config_path}")
      raise "File not found at #{config_path}" unless File.exist? config_path
      doc = REXML::Document.new(File.read(config_path))
      REXML::XPath.first(doc, node_name).value
    end

    def self.module_name(config_path)
      node_value(config_path, 'ivy-module/info/@module')
    end

    def self.unity_version(config_path)
      node_value(config_path, 'ivy-module/info/@e:unityVersion')
    end
  end

  class MacInstallation < Installation
    require 'plist'

    def version
      plist['CFBundleVersion']
    end

    def default_log_file
      "#{ENV['HOME']}/Library/Logs/Unity/Editor.log"
    end

    def exe_path
      "#{root_path}/Unity.app/Contents/MacOS/Unity"
    end

    def path
      UI.deprecated("path is deprecated. Use root_path instead")
      return @path if @path
      "#{@root_path}/Unity.app"
    end

    def packages
      # Unity prior to Unity5 did not have package
      return [] if Utils.parse_unity_version(version)[0].to_i <= 4
      PlaybackEngineUtils.list_module_configs(root_path).map do |mpath|
        PlaybackEngineUtils.module_name(mpath)
      end
    end

    def clean_install?
      !(root_path =~ UNITY_DIR_CHECK).nil?
    end

    private

    def plist
      @plist ||=
        begin
          fpath = "#{root_path}/Unity.app/Contents/Info.plist"
          raise "#{fpath} doesn't exist" unless File.exist? fpath
          Plist.parse_xml(fpath)
        end
    end
  end

  class LinuxInstallation < Installation
    def version
      # I don't find an easy way to extract the version on Linux
      path = "#{root_path}/Editor/Data/"
      package = PlaybackEngineUtils.list_module_configs(path).first
      raise "Couldn't find a module under #{path}" unless package
      version = PlaybackEngineUtils.unity_version(package)
      if (m = version.match(/^(.*)x(.*)Linux$/))
        version = "#{m[1]}#{m[2]}"
      end
      version
    end

    def default_log_file
      "#{ENV['HOME']}/.config/unity3d/Editor.log"
    end

    def exe_path
      "#{root_path}/Editor/Unity"
    end

    def path
      UI.deprecated("path is deprecated. Use root_path instead")
      @root_path || @path
    end

    def packages
      false
    end

    def clean_install?
      !(root_path =~ UNITY_DIR_CHECK_LINUX).nil?
    end
  end

  class WindowsInstallation < Installation
    def version
      path = "#{root_path}/Editor/Data/"
      package = PlaybackEngineUtils.list_module_configs(path).first
      raise "Couldn't find a module under #{path}" unless package
      PlaybackEngineUtils.unity_version(package)
    end

    def default_log_file
      if @logfile.nil?
        begin
          loc_appdata = Utils.windows_local_appdata
          log_dir = File.expand_path('Unity/Editor/', loc_appdata)
          UI.important "Log directory (#{log_dir}) does not exist" unless Dir.exist? log_dir
          @logfile = File.expand_path('Editor.log', log_dir)
        rescue RuntimeError => ex
          UI.error "Unable to retrieve the editor logfile: #{ex}"
        end
      end
      @logfile
    end

    def exe_path
      File.join(@root_path, 'Editor', 'Unity.exe')
    end

    def path
      UI.deprecated("path is deprecated. Use root_path instead")
      @root_path || @path
    end

    def packages
      # Unity prior to Unity5 did not have package
      return [] if Utils.parse_unity_version(version)[0].to_i <= 4
      path = "#{root_path}/Editor/Data/"
      PlaybackEngineUtils.list_module_configs(path).map do |mpath|
        PlaybackEngineUtils.module_name(mpath)
      end
    end

    def clean_install?
      !(root_path =~ UNITY_DIR_CHECK).nil?<commit_msg>Remove unecessary check as all the empty array is computed anyway when the list_module_configs is empty<commit_after>## --- BEGIN LICENSE BLOCK ---
# Copyright (c) 2016-present WeWantToKnow AS
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
## --- END LICENSE BLOCK ---

require 'u3d/utils'

module U3d
  UNITY_DIR_CHECK = /Unity_\d+\.\d+\.\d+[a-z]\d+/
  UNITY_DIR_CHECK_LINUX = /unity-editor-\d+\.\d+\.\d+[a-z]\d+\z/

  class Installation
    attr_reader :root_path

    def initialize(root_path: nil, path: nil)
      @root_path = root_path
      @path = path
    end

    def self.create(root_path: nil, path: nil)
      UI.deprecated("path is deprecated. Use root_path instead") unless path.nil?
      if Helper.mac?
        MacInstallation.new(root_path: root_path, path: path)
      elsif Helper.linux?
        LinuxInstallation.new(root_path: root_path, path: path)
      else
        WindowsInstallation.new(root_path: root_path, path: path)
      end
    end
  end

  class PlaybackEngineUtils
    def self.list_module_configs(playbackengine_parent_path)
      Dir.glob("#{playbackengine_parent_path}/PlaybackEngines/*/ivy.xml")
    end

    def self.node_value(config_path, node_name)
      require 'rexml/document'
      UI.verbose("reading #{config_path}")
      raise "File not found at #{config_path}" unless File.exist? config_path
      doc = REXML::Document.new(File.read(config_path))
      REXML::XPath.first(doc, node_name).value
    end

    def self.module_name(config_path)
      node_value(config_path, 'ivy-module/info/@module')
    end

    def self.unity_version(config_path)
      node_value(config_path, 'ivy-module/info/@e:unityVersion')
    end
  end

  class MacInstallation < Installation
    require 'plist'

    def version
      plist['CFBundleVersion']
    end

    def default_log_file
      "#{ENV['HOME']}/Library/Logs/Unity/Editor.log"
    end

    def exe_path
      "#{root_path}/Unity.app/Contents/MacOS/Unity"
    end

    def path
      UI.deprecated("path is deprecated. Use root_path instead")
      return @path if @path
      "#{@root_path}/Unity.app"
    end

    def packages
      PlaybackEngineUtils.list_module_configs(root_path).map do |mpath|
        PlaybackEngineUtils.module_name(mpath)
      end
    end

    def clean_install?
      !(root_path =~ UNITY_DIR_CHECK).nil?
    end

    private

    def plist
      @plist ||=
        begin
          fpath = "#{root_path}/Unity.app/Contents/Info.plist"
          raise "#{fpath} doesn't exist" unless File.exist? fpath
          Plist.parse_xml(fpath)
        end
    end
  end

  class LinuxInstallation < Installation
    def version
      # I don't find an easy way to extract the version on Linux
      path = "#{root_path}/Editor/Data/"
      package = PlaybackEngineUtils.list_module_configs(path).first
      raise "Couldn't find a module under #{path}" unless package
      version = PlaybackEngineUtils.unity_version(package)
      if (m = version.match(/^(.*)x(.*)Linux$/))
        version = "#{m[1]}#{m[2]}"
      end
      version
    end

    def default_log_file
      "#{ENV['HOME']}/.config/unity3d/Editor.log"
    end

    def exe_path
      "#{root_path}/Editor/Unity"
    end

    def path
      UI.deprecated("path is deprecated. Use root_path instead")
      @root_path || @path
    end

    def packages
      false
    end

    def clean_install?
      !(root_path =~ UNITY_DIR_CHECK_LINUX).nil?
    end
  end

  class WindowsInstallation < Installation
    def version
      path = "#{root_path}/Editor/Data/"
      package = PlaybackEngineUtils.list_module_configs(path).first
      raise "Couldn't find a module under #{path}" unless package
      PlaybackEngineUtils.unity_version(package)
    end

    def default_log_file
      if @logfile.nil?
        begin
          loc_appdata = Utils.windows_local_appdata
          log_dir = File.expand_path('Unity/Editor/', loc_appdata)
          UI.important "Log directory (#{log_dir}) does not exist" unless Dir.exist? log_dir
          @logfile = File.expand_path('Editor.log', log_dir)
        rescue RuntimeError => ex
          UI.error "Unable to retrieve the editor logfile: #{ex}"
        end
      end
      @logfile
    end

    def exe_path
      File.join(@root_path, 'Editor', 'Unity.exe')
    end

    def path
      UI.deprecated("path is deprecated. Use root_path instead")
      @root_path || @path
    end

    def packages
      path = "#{root_path}/Editor/Data/"
      PlaybackEngineUtils.list_module_configs(path).map do |mpath|
        PlaybackEngineUtils.module_name(mpath)
      end
    end

    def clean_install?
      !(root_path =~ UNITY_DIR_CHECK).nil?
{'fraction_non_alphanumeric': 0.09627437325905293, 'fraction_numerical': 0.0020891364902506965, 'mean_word_length': 2.9131471389645776, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, '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': '625992', 'n_tokens_mistral': 3613, 'n_tokens_neox': 3464, 'n_words': 1012}