maestro/app/classes/logical/packages/APTManager.js
2020-04-15 09:11:10 -05:00

178 lines
6.1 KiB
JavaScript

const PackageManager = require('./PackageManager')
class APTManager extends PackageManager {
_command_install_package = 'apt-get install -y %%PACKAGE%%'
_command_uninstall_package = 'apt-get purge -y %%PACKAGE%%'
_command_update_package = 'apt-get upgrade -y %%PACKAGE%%'
_command_reinstall_package = 'apt-get install -y --reinstall %%PACKAGE%%'
_command_clear_cache = 'apt-get clean'
_command_count_installed = 'dpkg --list | wc -l'
_command_count_available = 'apt-cache pkgnames | wc -l'
_command_add_repo = `add-apt-repository '%%URI%%'`
_command_preflight = 'apt-get update'
_status_keymap = {
package: 'name',
filename: 'source',
section: 'repository',
'description-en': 'summary',
}
async status(pkg) {
await this.preflight()
const result = await this._host.execute(`apt-cache show ${pkg}`)
if ( ![0, 100].includes(result.exit_code) ) {
throw new Error('Unable to determine package information: '+result.stderr.join('\n'))
}
if ( result.exit_code === 100 ) {
return {
name: pkg,
state: this.constructor.PACKAGE_STATE_UNKNOWN,
}
}
const data = {}
let last_data_key = false
for ( const line of result.clean_out ) {
if ( last_data_key && line.startsWith(' ') ) {
data[last_data_key] += line
} else {
const parts = line.trim().split(':')
const key = parts[0].toLowerCase()
const value = parts.slice(1).join(':').trim()
data[key] = value
last_data_key = key
}
}
for ( const key in this._status_keymap ) {
if ( !this._status_keymap.hasOwnProperty(key) ) continue
if ( data[key] ) {
data[this._status_keymap[key]] = data[key]
delete data[key]
}
}
// check installation state
const install_result = await this._host.execute(`dpkg -s ${pkg}`)
data.state = install_result.exit_code === 0 ? this.constructor.PACKAGE_STATE_INSTALLED : this.constructor.PACKAGE_STATE_AVAILABLE
return data
}
async list_updates() {
await this.preflight()
const result = await this._host.execute(`apt-get --just-print upgrade`)
if ( result.exit_code !== 0 ) {
throw new Error('Unable to determine packages for update: '+result.stderr.join('\n'))
}
let start_index = -1
let end_index = -1
for ( let i in result.clean_out ) {
const line = result.clean_out[i]
if ( line.toLowerCase().indexOf('packages will be upgraded') > -1 ) {
start_index = Number(i)+1
} else if ( start_index > -1 && i >= start_index ) {
if ( line.indexOf('newly installed,') > -1 ) break
else {
end_index = Number(i)
}
}
}
const package_strings = result.clean_out.slice(start_index, end_index+1).join(' ').split(' ').filter(Boolean).map(x => x.trim())
const updates = result.clean_out.filter(x => x.startsWith('Inst ')).map(x => {
x = x.substring(5)
x = x.split(' ')
const data = {
name: x[0],
version: x[1].slice(1, -1),
repository: x[3].replace(/,/g, ''),
architecture: x.reverse()[0].replace(/[\[\])(]/g, '')
}
return data
}).filter(x => package_strings.includes(x.name))
return updates
}
async list_repos() {
await this.preflight()
const result = await this._host.execute(`apt-cache policy`)
if ( result.exit_code !== 0 ) {
throw new Error('Unable to read repository list: '+result.stderr.join('\n'))
}
const lines = []
for ( const line of result.clean_out ) {
if ( line.trim().startsWith('500') ) {
lines.push(line)
} else if ( line.toLowerCase().startsWith('pinned packages') ) {
break
}
}
return lines.map(x => x.trim()).filter(x => x.startsWith('500')).map(x => x.split(' ')[2])
}
async list_installed() {
const result = await this._host.execute(`dpkg --list`)
if ( result.exit_code !== 0 ) {
throw new Error('Unable to determine installed packages: '+result.stderr.join('\n'))
}
let header_line = result.clean_out.filter(x => x.trim().startsWith('+'))[0]
let drop_count = 0
while ( header_line.startsWith('+') ) {
drop_count += 1
header_line = header_line.substring(1)
}
let start_at = 0
for ( let i in result.clean_out ) {
if ( result.clean_out[i].startsWith('+') ) {
start_at = Number(i)+1
break
}
}
return result.clean_out.slice(start_at).map(x => {
x = x.substring(drop_count).trim().split(' ').filter(Boolean)
return {
name: x[0],
version: x[1],
architecture: x[2],
summary: x.slice(3).join(' ')
}
})
}
async search(pkg) {
await this.preflight()
const result = await this._host.execute(`apt-cache search ${pkg}`)
if ( result.exit_code !== 0 ) {
throw new Error('Unable to search the package cache: '+result.stderr.join('\n'))
}
const results = []
for ( const line of result.clean_out ) {
const parts = line.trim().split(' - ').map(x => x.trim())
results.push({
name: parts[0],
summary: parts[1]
})
}
return results
}
async preflight() {
const result = await this._host.execute(this._command_preflight)
if ( result.exit_code !== 0 ) {
throw new Error('Error encountered during preflight for APTManager: '+result.stderr.join('\n'))
}
}
}
module.exports = exports = APTManager