summaryrefslogtreecommitdiff
path: root/lib/license/finder/ext/composer.rb
blob: 993119ce6130a31e492e7e31f0e10f4f8f61e43c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# frozen_string_literal: true

module LicenseFinder
  class Composer < PackageManager
    def prepare
      create_vendor_path

      within_project_path do
        tool_box.install(tool: :php)
        shell.execute([
          :composer,
          :install,
          '--ignore-platform-reqs',
          '--no-dev',
          '--no-interaction',
          '--no-plugins',
          '--no-progress',
          '--no-scripts',
          '--verbose'
        ], env: default_env)
      end
    end

    def current_packages
      within_project_path do
        dependencies.map do |data|
          map_from(data)
        end
      end
    end

    private

    def default_env
      @default_env ||= {
        'COMPOSER_ALLOW_SUPER' => '1',
        'COMPOSER_CAFILE' => ENV.fetch('COMPOSER_CACHE_DIR', shell.default_certificate_path).to_s
      }.tap do |env|
        if vendor_path.exist?
          env['COMPOSER_CACHE_DIR'] = ENV.fetch('COMPOSER_CACHE_DIR', vendor_path.join('.cache')).to_s
          env['COMPOSER_VENDOR_DIR'] = ENV.fetch('COMPOSER_VENDOR_DIR', vendor_path).to_s
        end
      end
    end

    def dependencies
      stdout, _stderr, status = shell.execute([
        :composer,
        :licenses,
        '--format=json'
      ], env: default_env)
      return from_lockfile unless status.success?

      dependencies = JSON.parse(stdout).fetch('dependencies', {})
      return from_lockfile if dependencies.empty?

      dependencies.map do |name, data|
        data.merge('name' => name) if data.is_a?(Hash)
      end.compact
    end

    def map_from(data)
      Dependency.new(
        'Composer',
        data['name'],
        data['version'],
        spec_licenses: data['license'],
        detection_path: detected_package_path,
        install_path: path_to(data['name'])
      )
    end

    def path_to(package_name)
      stdout, _stderr, status = shell.execute([
        :composer,
        :show,
        package_name,
        "-P"
      ], env: default_env)
      status.success? ? stdout.split(' ').last : ''
    end

    def from_lockfile
      return [] unless lockfile_path.exist?

      json = JSON.parse(lockfile_path.read)
      json.fetch('packages', [])
    end
  end
end