const PackageManager = require('./PackageManager') class DNFManager extends PackageManager { _command_install_package = 'dnf install -y %%PACKAGE%%' _command_uninstall_package = 'dnf remove -y %%PACKAGE%%' _command_update_package = 'dnf update -y %%PACKAGE%%' _command_reinstall_package = 'dnf reinstall -y %%PACKAGE%%' _command_add_repo = 'dnf config-manager -y --add-repo="%%URI%%"' _command_clear_cache = 'dnf clean all' _command_count_installed = 'dnf list installed -q | wc -l' _command_count_available = 'dnf list available -q | wc -l' async status(pkg) { const result = await this._host.execute(`dnf info -q --installed ${pkg}`) if ( result.exit_code === 0 ) { const data = this._data_from_result(result.clean_out) data.state = this.constructor.PACKAGE_STATE_INSTALLED return data } else { const available_result = await this._host.execute(`dnf info -q --available ${pkg}`) if ( available_result.exit_code === 0 ) { const data = this._data_from_result(available_result.clean_out) data.state = this.constructor.PACKAGE_STATE_AVAILABLE return data } else { return { name: pkg, state: this.constructor.PACKAGE_STATE_UNKNOWN, } } } } async list_updates() { const result = await this._host.execute(`dnf check-update -q`) // 100 is the known exit code for successful result, but updates pending if ( ![0, 100].includes(result.exit_code) ) { throw new Error('Unable to check for updates: '+result.stderr.join('\n')) } const updates = [] for ( const line of result.clean_out ) { const parts = line.trim().split(' ').filter(Boolean) const data = this._package_info_from_line_parts(parts) updates.push(data) } return updates } async list_repos() { const result = await this._host.execute(`dnf repolist all -q`) if ( result.exit_code !== 0 ) { throw new Error('Unable to determine repositories: '+result.stderr.join('\n')) } const offset_length = result.clean_out[0].toLowerCase().indexOf('repo name') return result.clean_out.slice(1).map(line => line.substr(0, offset_length).trim()) } async list_installed() { const result = await this._host.execute(`dnf list installed -q`) if ( result.exit_code !== 0 ) { throw new Error('Unable to determine installed packages: '+result.stderr.join('\n')) } const results = [] for ( const line of result.clean_out.slice(1) ) { const parts = line.trim().split(' ').filter(Boolean) const data = this._package_info_from_line_parts(parts) results.push(data) } return results } async search(term) { const result = await this._host.execute(`dnf search ${term} -q`) if ( result.exit_code !== 0 ) { throw new Error('Unable to complete search: '+result.stderr.join('\n')) } const results = [] for ( const line of result.clean_out ) { if ( !line.trim().startsWith('=') ) { const parts = line.split(':').map(x => x.trim()) const data = this._package_info_from_line_parts(parts) if ( data.version ) { data.summary = data.version delete data.version } results.push(data) } } return results } _data_from_result(stdout) { const data = {} for ( const line of stdout ) { const parts = line.split(':').map(x => String(x).trim()) if ( parts.length > 1 && parts[0] ) { let key = parts[0].toLowerCase() if ( key === 'from repo' ) key = 'repo' data[key] = parts.slice(1).join(':') } } return data } _package_info_from_line_parts(parts) { const data = {} if ( parts.length > 0 ) { data.name = parts[0] if ( data.name.indexOf('.') >= 0 ) { const arch_parts = data.name.split('.').reverse() data.architecture = arch_parts[0] data.name = arch_parts.slice(1).reverse().join('.') } } if ( parts.length > 1 ) data.version = parts[1] if ( parts.length > 2 ) data.repository = parts[2] return data } } module.exports = exports = DNFManager