1 |
|
2 |
|
3 |
|
4 | 'use strict';
|
5 |
|
6 | const fs = require('fs');
|
7 | const os = require('os');
|
8 | const path = require('path');
|
9 | const spawnSync = require('child_process').spawnSync;
|
10 | const semverCoerce = require('semver/functions/coerce');
|
11 | const semverGreaterThanOrEqualTo = require('semver/functions/gte');
|
12 |
|
13 | const platform = require('./platform');
|
14 | const { config } = require('../package.json');
|
15 |
|
16 | const env = process.env;
|
17 | const minimumLibvipsVersionLabelled = env.npm_package_config_libvips ||
|
18 | config.libvips;
|
19 | const minimumLibvipsVersion = semverCoerce(minimumLibvipsVersionLabelled).version;
|
20 |
|
21 | const spawnSyncOptions = {
|
22 | encoding: 'utf8',
|
23 | shell: true
|
24 | };
|
25 |
|
26 | const vendorPath = path.join(__dirname, '..', 'vendor', minimumLibvipsVersion, platform());
|
27 |
|
28 | const mkdirSync = function (dirPath) {
|
29 | try {
|
30 | fs.mkdirSync(dirPath, { recursive: true });
|
31 | } catch (err) {
|
32 |
|
33 | if (err.code !== 'EEXIST') {
|
34 | throw err;
|
35 | }
|
36 | }
|
37 | };
|
38 |
|
39 | const cachePath = function () {
|
40 | const npmCachePath = env.npm_config_cache ||
|
41 | (env.APPDATA ? path.join(env.APPDATA, 'npm-cache') : path.join(os.homedir(), '.npm'));
|
42 | mkdirSync(npmCachePath);
|
43 | const libvipsCachePath = path.join(npmCachePath, '_libvips');
|
44 | mkdirSync(libvipsCachePath);
|
45 | return libvipsCachePath;
|
46 | };
|
47 |
|
48 | const integrity = function (platformAndArch) {
|
49 | return env[`npm_package_config_integrity_${platformAndArch.replace('-', '_')}`] || config.integrity[platformAndArch];
|
50 | };
|
51 |
|
52 | const log = function (item) {
|
53 | if (item instanceof Error) {
|
54 | console.error(`sharp: Installation error: ${item.message}`);
|
55 | } else {
|
56 | console.log(`sharp: ${item}`);
|
57 | }
|
58 | };
|
59 |
|
60 | const isRosetta = function () {
|
61 |
|
62 | if (process.platform === 'darwin' && process.arch === 'x64') {
|
63 | const translated = spawnSync('sysctl sysctl.proc_translated', spawnSyncOptions).stdout;
|
64 | return (translated || '').trim() === 'sysctl.proc_translated: 1';
|
65 | }
|
66 | return false;
|
67 | };
|
68 |
|
69 | const globalLibvipsVersion = function () {
|
70 | if (process.platform !== 'win32') {
|
71 | const globalLibvipsVersion = spawnSync('pkg-config --modversion vips-cpp', {
|
72 | ...spawnSyncOptions,
|
73 | env: {
|
74 | ...env,
|
75 | PKG_CONFIG_PATH: pkgConfigPath()
|
76 | }
|
77 | }).stdout;
|
78 |
|
79 | return (globalLibvipsVersion || '').trim();
|
80 | } else {
|
81 | return '';
|
82 | }
|
83 | };
|
84 |
|
85 | const hasVendoredLibvips = function () {
|
86 | return fs.existsSync(vendorPath);
|
87 | };
|
88 |
|
89 |
|
90 | const removeVendoredLibvips = function () {
|
91 | fs.rmSync(vendorPath, { recursive: true, maxRetries: 3, force: true });
|
92 | };
|
93 |
|
94 |
|
95 | const pkgConfigPath = function () {
|
96 | if (process.platform !== 'win32') {
|
97 | const brewPkgConfigPath = spawnSync(
|
98 | 'which brew >/dev/null 2>&1 && brew environment --plain | grep PKG_CONFIG_LIBDIR | cut -d" " -f2',
|
99 | spawnSyncOptions
|
100 | ).stdout || '';
|
101 | return [
|
102 | brewPkgConfigPath.trim(),
|
103 | env.PKG_CONFIG_PATH,
|
104 | '/usr/local/lib/pkgconfig',
|
105 | '/usr/lib/pkgconfig',
|
106 | '/usr/local/libdata/pkgconfig',
|
107 | '/usr/libdata/pkgconfig'
|
108 | ].filter(Boolean).join(':');
|
109 | } else {
|
110 | return '';
|
111 | }
|
112 | };
|
113 |
|
114 | const useGlobalLibvips = function () {
|
115 | if (Boolean(env.SHARP_IGNORE_GLOBAL_LIBVIPS) === true) {
|
116 | return false;
|
117 | }
|
118 |
|
119 | if (isRosetta()) {
|
120 | log('Detected Rosetta, skipping search for globally-installed libvips');
|
121 | return false;
|
122 | }
|
123 | const globalVipsVersion = globalLibvipsVersion();
|
124 | return !!globalVipsVersion &&
|
125 | semverGreaterThanOrEqualTo(globalVipsVersion, minimumLibvipsVersion);
|
126 | };
|
127 |
|
128 | module.exports = {
|
129 | minimumLibvipsVersion,
|
130 | minimumLibvipsVersionLabelled,
|
131 | cachePath,
|
132 | integrity,
|
133 | log,
|
134 | globalLibvipsVersion,
|
135 | hasVendoredLibvips,
|
136 | removeVendoredLibvips,
|
137 | pkgConfigPath,
|
138 | useGlobalLibvips,
|
139 | mkdirSync
|
140 | };
|