Skip to content

Commit

Permalink
Merge pull request #2566 from jeedom/pip-on-debian-12
Browse files Browse the repository at this point in the history
Pip on debian 12
  • Loading branch information
zoic21 authored May 21, 2024
2 parents 46dc015 + 83375b0 commit 000a689
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 96 deletions.
2 changes: 1 addition & 1 deletion core/ajax/jeedom.ajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@
$cmd .= system::checkInstallationLog();
$cmd .= system::getCmdSudo() . " apt update\n";
$package = explode('::', init('package'));
$cmd .= system::installPackage($package[0], $package[1]) . "\n";
$cmd .= system::installPackage($package[0], $package[1], $package[3], $package[2]) . "\n";
if (file_exists('/tmp/jeedom_fix_package')) {
shell_exec(system::getCmdSudo() . ' rm /tmp/jeedom_fix_package');
}
Expand Down
2 changes: 1 addition & 1 deletion core/class/plugin.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,7 @@ public function dependancy_info($_refresh = false) {
}
if (file_exists(__DIR__ . '/../../plugins/' . $plugin_id . '/plugin_info/packages.json')) {
$return = array('log' => $plugin_id . '_packages');
$packages = system::checkAndInstall(json_decode(file_get_contents(__DIR__ . '/../../plugins/' . $plugin_id . '/plugin_info/packages.json'), true));
$packages = system::checkAndInstall(json_decode(file_get_contents(__DIR__ . '/../../plugins/' . $plugin_id . '/plugin_info/packages.json'), true), false, false, $plugin_id);
$has_dep_to_install = false;
foreach ($packages as $package => $info) {
if ($info['status'] != 0 || $info['optional']) {
Expand Down
133 changes: 88 additions & 45 deletions core/class/system.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,9 @@ public static function getUpgradablePackage($_type, $_forceRefresh = false) {
}
break;
case 'pip3':
if (version_compare(self::getOsVersion(), '12', '>=')) {
return array();
}
$ignore_package = array('dbus-python', 'gpg', 'pycairo', 'pycurl', 'PyGObject');
$datas = json_decode(shell_exec(system::getCmdSudo() . ' pip3 list --outdated --format=json 2>/dev/null'), true);
if (count($datas) > 0) {
Expand Down Expand Up @@ -267,6 +270,9 @@ public static function upgradePackage($_type, $_package = null) {
}
break;
case 'pip3':
if (version_compare(self::getOsVersion(), '12', '>=')) {
return;
}
if ($_package == null) {
$packages = self::getUpgradablePackage($_type);
if (count($packages) == '') {
Expand Down Expand Up @@ -304,11 +310,40 @@ public static function upgradePackage($_type, $_package = null) {
self::launchScriptPackage();
}

public static function getInstallPackage($_type) {
if (isset(self::$_installPackage[$_type])) {
return self::$_installPackage[$_type];
private static function getPython3VenvDir($_plugin) {
if ($_plugin == '') return '';
return __DIR__ . "/../../plugins/{$_plugin}/resources/python_venv";
}

public static function getCmdPython3($_plugin) {
if ($_plugin == '') return 'python3 ';

if (version_compare(self::getOsVersion(), '12', '<')) {
return 'python3 ';
} else {
return self::getPython3VenvDir($_plugin) . '/bin/python3 ';
}
}

private static function splitpackageByPlugin($_type, $_plugin = '') {
if (version_compare(self::getOsVersion(), '12', '>=') && in_array($_type, ['pip3']) && $_plugin != '') {
return true;
} else {
return false;
}
}

public static function getInstallPackage($_type, $_plugin) {
if (self::splitpackageByPlugin($_type, $_plugin)) {
$type_key = $_type . '::' . $_plugin;
} else {
$type_key = $_type;
}

if (isset(self::$_installPackage[$type_key])) {
return self::$_installPackage[$type_key];
}
self::$_installPackage[$_type] = array();
self::$_installPackage[$type_key] = array();
switch ($_type) {
case 'apt':
$lines = explode("\n", shell_exec('dpkg -l | grep "^ii"'));
Expand All @@ -320,51 +355,54 @@ public static function getInstallPackage($_type) {
if (strpos($infos[1], ':') !== false) {
$infos[1] = explode(':', $infos[1])[0];
}
self::$_installPackage[$_type][mb_strtolower($infos[1])] = array(
self::$_installPackage[$type_key][mb_strtolower($infos[1])] = array(
'version' => $infos[2]
);
}
$npm = shell_exec('npm -v 2>/dev/null');
if ($npm != '') {
self::$_installPackage[$_type]['npm'] = array(
self::$_installPackage[$type_key]['npm'] = array(
'version' => $npm
);
}
break;
case 'pip2':
if (version_compare(self::getOsVersion(), '11', '>=')) {
return self::$_installPackage[$_type];
return self::$_installPackage[$type_key];
}
$datas = json_decode(shell_exec(self::getCmdSudo() . ' pip2 list --format=json 2>/dev/null'), true);
foreach ($datas as $value) {
self::$_installPackage[$_type][mb_strtolower($value['name'])] = array(
self::$_installPackage[$type_key][mb_strtolower($value['name'])] = array(
'version' => $value['version']
);
}
break;
case 'pip3':
$datas = json_decode(shell_exec(self::getCmdSudo() . ' pip3 list --format=json 2>/dev/null'), true);
$datas = json_decode(shell_exec(self::getCmdSudo() . self::getCmdPython3($_plugin) . ' -m pip list --format=json 2>/dev/null'), true);
if (!is_array($datas)) {
break;
}
foreach ($datas as $value) {
self::$_installPackage[$_type][mb_strtolower($value['name'])] = array(
self::$_installPackage[$type_key][mb_strtolower($value['name'])] = array(
'version' => $value['version']
);
}
break;
case 'npm':
$datas = json_decode(shell_exec(self::getCmdSudo() . ' npm -g ls -json -depth 1 2>/dev/null'), true);
if (isset($datas['dependencies']['yarn'])) {
self::$_installPackage[$_type]['yarn'] = array(
self::$_installPackage[$type_key]['yarn'] = array(
'version' => $datas['dependencies']['yarn']['version']
);
}
if (isset($datas['dependencies']) && is_array($datas['dependencies']) && count($datas['dependencies']) > 0) {
foreach ($datas['dependencies'] as $key => $value) {
self::$_installPackage[$_type][mb_strtolower($key)] = array(
self::$_installPackage[$type_key][mb_strtolower($key)] = array(
'version' => $value['version']
);
if (isset($value['dependencies'])) {
foreach ($value['dependencies'] as $key2 => $value2) {
self::$_installPackage[$_type][mb_strtolower($key2)] = array(
self::$_installPackage[$type_key][mb_strtolower($key2)] = array(
'version' => $value2['version']
);
}
Expand All @@ -375,25 +413,25 @@ public static function getInstallPackage($_type) {
case 'yarn':
$datas = json_decode(shell_exec('cat `' . self::getCmdSudo() . ' yarn global dir`/package.json 2>/dev/null'), true);
foreach ($datas['dependencies'] as $key => $value) {
self::$_installPackage[$_type][mb_strtolower($key)] = array(
self::$_installPackage[$type_key][mb_strtolower($key)] = array(
'version' => json_decode(shell_exec('yarn info ' . $key . ' version --json 2>/dev/null'), true)['data']
);
}
break;
case 'composer':
$datas = shell_exec(self::getCmdSudo() . ' composer show -f json 2>/dev/null');
case 'composer':
$datas = json_decode(shell_exec(self::getCmdSudo() . ' composer show -f json 2>/dev/null'));
foreach ($datas['installed'] as $value) {
self::$_installPackage[$_type][mb_strtolower($value['name'])] = array('version' => $value['version']);
self::$_installPackage[$type_key][mb_strtolower($value['name'])] = array('version' => $value['version']);
}
break;
case 'plugin':
$updates = update::byType('plugin');
foreach ($updates as $update) {
self::$_installPackage[$_type][mb_strtolower($update->getLogicalId())] = array('version' => $update->getLocalVersion());
self::$_installPackage[$type_key][mb_strtolower($update->getLogicalId())] = array('version' => $update->getLocalVersion());
}
break;
}
return self::$_installPackage[$_type];
return self::$_installPackage[$type_key];
}

public static function os_incompatible($_type, $_package, $_info): bool {
Expand All @@ -414,13 +452,13 @@ public static function os_incompatible($_type, $_package, $_info): bool {
return false;
}

public static function checkAndInstall($_packages, $_fix = false, $_foreground = false, $_plugin = '',$_force = false) {
public static function checkAndInstall($_packages, $_fix = false, $_foreground = false, $_plugin = '', $_force = false) {
$return = array();
foreach ($_packages as $type => $value) {
if ($type == 'post-install' || $type == 'pre-install') {
continue;
}
$installPackage = self::getInstallPackage($type);
$installPackage = self::getInstallPackage($type, $_plugin);

foreach ($_packages[$type] as $package => $info) {
$found = 0;
Expand All @@ -430,10 +468,10 @@ public static function checkAndInstall($_packages, $_fix = false, $_foreground =
$version = json_decode(file_get_contents(__DIR__ . '/../../' . $package . '/package.json'), true)['version'];
if ($type == 'npm') {
if (file_exists(__DIR__ . '/../../' . $package . '/node_modules')) {
exec('cd ' . __DIR__ . '/../../' . $package . ';' . self::getCmdSudo() . ' npm ls', $output, $return_var);
exec('cd ' . __DIR__ . '/../../' . $package . ';' . self::getCmdSudo() . ' npm ls', $output, $return_var);
if ($return_var == 0) {
$found = 1;
}
$found = 1;
}
}
} else {
exec('cd ' . __DIR__ . '/../../' . $package . ';' . self::getCmdSudo() . ' yarn check', $output, $return_var);
Expand Down Expand Up @@ -462,8 +500,8 @@ public static function checkAndInstall($_packages, $_fix = false, $_foreground =
if ($type == 'composer' && strpos($package, '/') !== false) {
if (file_exists(__DIR__ . '/../../' . $package . '/composer.json')) {
$version = json_decode(file_get_contents(__DIR__ . '/../../' . $package . '/package.json'), true)['version'];
$output = shell_exec('cd ' . __DIR__ . '/../../' . $package . ';' . self::getCmdSudo() . ' composer install --dry-run 2>&1 | grep Required | grep present | wc -l');
if ($output == 0) {
$output = shell_exec('cd ' . __DIR__ . '/../../' . $package . ';' . self::getCmdSudo() . ' composer install --dry-run 2>&1 | grep Required | grep present | wc -l');
if ($output == 0) {
$found = 1;
}
} else {
Expand Down Expand Up @@ -524,7 +562,7 @@ public static function checkAndInstall($_packages, $_fix = false, $_foreground =
$found = 0;
$needUpdate = true;
}
$return[$type . '::' . $package] = array(
$return[$type . '::' . $package . '::' . (self::splitpackageByPlugin($type, $_plugin) ? $_plugin : '') . '::' . (isset($info['version']) ? $info['version'] : '')] = array(
'name' => $package,
'status' => $found,
'version' => $version,
Expand All @@ -534,7 +572,7 @@ public static function checkAndInstall($_packages, $_fix = false, $_foreground =
'alternative_found' => $alternative_found,
'optional' => isset($info['optional']) ? $info['optional'] : false,
'reinstall' => isset($info['reinstall']) ? $info['reinstall'] : false,
'fix' => ($found == 0) ? self::installPackage($type, $package) : '',
'fix' => ($found == 0) ? self::installPackage($type, $package, isset($info['version']) ? $info['version'] : '', $_plugin) : '',
'remark' => isset($info['remark']) ? __($info['remark'], 'install/packages.json') : '',
);
}
Expand Down Expand Up @@ -621,11 +659,19 @@ public static function checkAndInstall($_packages, $_fix = false, $_foreground =
$count++;
$cmd .= 'echo ' . $count . ' > ' . $progress_file . "\n";
}
}else{
} else {
if ($_foreground) {
echo shell_exec(self::getCmdSudo() . ' apt update;'.self::getCmdSudo() .' apt install -y pipx');
}else{
$cmd .= self::getCmdSudo() . " apt update;\n".self::getCmdSudo() ." apt install -y pipx\n";
echo shell_exec(self::getCmdSudo() . ' apt update;' . self::getCmdSudo() . ' apt-get install -y python3 python3-pip python3-dev python3-venv');
echo shell_exec(self::getCmdSudo() . ' python3 -m venv --upgrade-deps ' . self::getPython3VenvDir($_plugin));
echo shell_exec(self::getCmdSudo() . self::getCmdPython3($_plugin) . ' -m pip install --upgrade pip wheel');
} else {
$cmd .= self::getCmdSudo() . " apt update;\n" . self::getCmdSudo() . " apt-get install -y python3 python3-pip python3-dev python3-venv\n";
$count++;
$cmd .= 'echo ' . $count . ' > ' . $progress_file . "\n";
$cmd .= self::getCmdSudo() . 'python3 -m venv --upgrade-deps ' . self::getPython3VenvDir($_plugin) . "\n";
$count++;
$cmd .= 'echo ' . $count . ' > ' . $progress_file . "\n";
$cmd .= self::getCmdSudo() . self::getCmdPython3($_plugin) . " -m pip install --upgrade pip wheel\n";
$count++;
$cmd .= 'echo ' . $count . ' > ' . $progress_file . "\n";
}
Expand All @@ -647,7 +693,7 @@ public static function checkAndInstall($_packages, $_fix = false, $_foreground =
$count++;
$cmd .= 'echo ' . $count . ' > ' . $progress_file . "\n";
}
case 'composer':
case 'composer':
if ($_foreground) {
echo shell_exec(self::getCmdSudo() . ' chmod +x ' . __DIR__ . '/../../resources/install_composer.sh;' . self::getCmdSudo() . ' ' . __DIR__ . '/../../resources/install_composer.sh');
} else {
Expand All @@ -658,9 +704,9 @@ public static function checkAndInstall($_packages, $_fix = false, $_foreground =
}
}
if ($_foreground) {
echo shell_exec(self::installPackage($info['type'], $info['name'], $info['needVersion']) . ' 2>&1');
echo shell_exec(self::installPackage($info['type'], $info['name'], $info['needVersion'], $_plugin) . ' 2>&1');
} else {
$cmd .= self::installPackage($info['type'], $info['name'], $info['needVersion']) . "\n";
$cmd .= self::installPackage($info['type'], $info['name'], $info['needVersion'], $_plugin) . "\n";
$count++;
$cmd .= 'echo ' . $count . ' > ' . $progress_file . "\n";
}
Expand Down Expand Up @@ -690,8 +736,8 @@ public static function checkAndInstall($_packages, $_fix = false, $_foreground =
}
if ($_plugin != '') {
if ($_foreground) {
echo shell_exec('php ' . __DIR__ . '/../php/jeecli.php plugin dependancy_end ' . $_plugin .' 2>&1');
}else{
echo shell_exec('php ' . __DIR__ . '/../php/jeecli.php plugin dependancy_end ' . $_plugin . ' 2>&1');
} else {
$cmd .= 'php ' . __DIR__ . '/../php/jeecli.php plugin dependancy_end ' . $_plugin . "\n";
$count++;
$cmd .= 'echo ' . $count . ' > ' . $progress_file . "\n";
Expand All @@ -706,7 +752,7 @@ public static function checkAndInstall($_packages, $_fix = false, $_foreground =
shell_exec(system::getCmdSudo() . ' rm /tmp/jeedom_fix_package');
}
file_put_contents('/tmp/jeedom_fix_package', $cmd);
self::launchScriptPackage($_plugin,$_force);
self::launchScriptPackage($_plugin, $_force);
}

public static function installPackageInProgress($_plugin = ''): bool {
Expand All @@ -729,13 +775,13 @@ public static function installPackageInProgress($_plugin = ''): bool {
}
return true;
}
if(shell_exec('ls /tmp/jeedom_install_in_progress* | wc -l') > 0){
if (shell_exec('ls /tmp/jeedom_install_in_progress* | wc -l') > 0) {
return true;
}
return false;
}

public static function launchScriptPackage($_plugin = '',$_force = false) {
public static function launchScriptPackage($_plugin = '', $_force = false) {
if (!$_force && self::installPackageInProgress($_plugin)) {
throw new \Exception(__('Installation de package impossible car il y a déjà une installation en cours', __FILE__));
}
Expand All @@ -761,7 +807,7 @@ public static function launchScriptPackage($_plugin = '',$_force = false) {
}
}

public static function installPackage($_type, $_package, $_version = '') {
public static function installPackage($_type, $_package, $_version = '', $_plugin = '') {
switch ($_type) {
case 'apt':
if ($_package == 'node' || $_package == 'nodejs' || $_package == 'npm') {
Expand All @@ -777,10 +823,7 @@ public static function installPackage($_type, $_package, $_version = '') {
if ($_version != '') {
$_package .= '==' . $_version;
}
if (version_compare(self::getOsVersion(), '12', '>=')) {
return self::getCmdSudo() . ' pipx install --force-reinstall --upgrade ' . $_package;
}
return self::getCmdSudo() . ' pip3 install --force-reinstall --upgrade ' . $_package;
return self::getCmdSudo() . self::getCmdPython3($_plugin) . ' -m pip install --force-reinstall --upgrade ' . $_package;
case 'npm':
if (strpos($_package, '/') === false) {
return self::getCmdSudo() . ' NODE_OPTIONS=--dns-result-order=ipv4first npm install --force -g ' . $_package;
Expand Down
Loading

0 comments on commit 000a689

Please sign in to comment.