Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(server) Slightly Improved Linux Support #302

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24,331 changes: 24,313 additions & 18 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"fastify": "^3.17.0",
"fastify-static": "^4.0.1",
"fluent-ffmpeg": "^2.1.2",
"getos": "^3.2.1",
"googleapis": "^67.1.1",
"ibm-watson": "^6.1.1",
"moment-timezone": "^0.5.33",
Expand Down
19 changes: 16 additions & 3 deletions scripts/check-os.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import os from '@/helpers/os'
export default () => new Promise(async (resolve, reject) => {
log.info('Checking OS environment...')

const info = os.get()
const info = await os.get()

if (info.type === 'windows') {
log.error('Voice offline mode is not available on Windows')
Expand All @@ -33,8 +33,21 @@ export default () => new Promise(async (resolve, reject) => {
await execa('curl', ['--version'])
log.success('"curl" found')
} else if (info.type === 'linux') {
await execa('apt-get', ['--version'])
log.success('"apt-get" found')
switch (info.distro) {
Copy link

@sleroq sleroq Jan 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the number of different distributions, I think it would be easier to to just try the most popular package managers.

Maybe try something like this?

async function checkPM(name){
    await execa(name, ['--version'])
    return 'name'
}

let packageManager;
try {
    await Promise.any([
        checkPM('pacman'),
        checkPM('apt-get'),
        checkPM('dnf'),
    ])
} catch (error) {
    throw new Error('Unknown package manager')
}
log.success(`${packageManager} found`)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah definitely an improvement! I'll get around to fixing that, thanks. I don't suppose you had the same issue with running the test suite, what I mentioned in the PR description?

// Add distros as needed
case 'Arch Linux':
await execa('pacman', ['--version'])
log.success('"pacman" found')
break
case 'Fedora':
await execa('dnf', ['--version'])
log.success('"dnf" found')
break
default:
await execa('apt-get', ['--version'])
log.success('"apt-get" found')
}

await execa('wget', ['--version'])
log.success('"wget" found')
}
Expand Down
26 changes: 23 additions & 3 deletions scripts/setup-offline/setup-hotword.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,41 @@ import os from '@/helpers/os'
export default () => new Promise(async (resolve, reject) => {
log.info('Setting up offline hotword detection...')

const info = os.get()
let pkgm = 'apt-get install'
const info = await os.get()
let pkgm = ''
if (info.type === 'macos') {
pkgm = 'brew'
}

if (info.name === 'Linux') {
// Add distros as needed
switch (info.distro) {
case 'Arch Linux':
pkgm = 'pacman -S'
break
default:
pkgm = 'apt-get install'
}
}

if (info.type === 'windows') {
log.error('Voice offline mode is not available on Windows')
reject()
} else {
try {
log.info('Installing dependencies...')
let cmd = ''

let cmd = `sudo ${pkgm} sox libsox-fmt-all -y`
if (info.type === 'linux') {
// Add distros as needed
switch (info.distro) {
case 'Arch Linux':
cmd = `sudo ${pkgm} sox libsoxr`
break
default:
cmd = `sudo ${pkgm} sox libsox-fmt-all -y`
}

log.info(`Executing the following command: ${cmd}`)
await command(cmd, { shell: true })
} else if (info.type === 'macos') {
Expand Down
4 changes: 3 additions & 1 deletion scripts/setup-offline/setup-stt.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ export default () => new Promise(async (resolve, reject) => {
const tmpDir = 'scripts/tmp'
const deepSpeechVersion = '0.9.3'
let downloader = 'wget'
if (os.get().type === 'macos') {
const info = await os.get()

if (info.type === 'macos') {
downloader = 'curl -L -O'
}

Expand Down
3 changes: 2 additions & 1 deletion scripts/setup-offline/setup-tts.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export default () => new Promise(async (resolve, reject) => {
makeCores = `-j ${os.cpus().length - 2}`
}
let downloader = 'wget'
if (os.get().type === 'macos') {
const info = await os.get()
if (info.type === 'macos') {
downloader = 'curl -L -O'
}

Expand Down
2 changes: 1 addition & 1 deletion scripts/setup/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import setupPythonPackages from './setup-python-packages'
*/
(async () => {
try {
const info = os.get()
const info = await os.get()

// Required env vars to setup
process.env.LEON_LANG = 'en-US'
Expand Down
22 changes: 17 additions & 5 deletions server/src/helpers/os.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,38 @@
import getos from 'getos'
import o from 'os'

import { promisify } from 'util'

/** change from a callback function to promise */
const getosPromise = promisify(getos)

const os = { }

/**
* Returns information about your OS
*/
os.get = () => {
os.get = async () => {
let type = 'unknown'
let name = ''
let distro

const result = await getosPromise()
const osName = result.os.toLowerCase()

if (o.type().indexOf('Windows') !== -1) {
if (osName.indexOf('windows') !== -1) {
type = 'windows'
name = 'Windows'
} else if (o.type() === 'Darwin') {
} else if (osName === 'darwin') {
type = 'macos'
name = 'macOS'
} else if (o.type() === 'Linux') {
} else if (osName === 'linux') {
type = 'linux'
name = 'Linux'
// e.g "Arch Linux". Linux Examples https://github.com/retrohacker/getos/blob/master/os.json
distro = result.dist
}

return { type, name }
return { type, name, distro }
}

/**
Expand Down
38 changes: 21 additions & 17 deletions test/unit/server/helpers/os.spec.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,40 @@
import getos from 'getos'

jest.mock('getos')

// Import after mock, so we can change the OS
// eslint-disable-next-line
import os from '@/helpers/os'

const setupTest = (osName) => {
getos.mockImplementation((cb) => cb(null, { os: osName, dist: osName === 'Linux' ? 'Arch' : undefined }))
}

describe('OS helper', () => {
describe('get()', () => {
test('returns information about the OS', () => {
const info = os.get()
test('returns information about the OS', async () => {
const info = await os.get()

expect(info.type).toBeOneOf(['windows', 'linux', 'macos'])
expect(info.name).toBeOneOf(['Windows', 'Linux', 'macOS'])
})

test('returns information for Windows', () => {
jest.unmock('os')
const o = jest.requireActual('os')
o.type = jest.fn(() => 'Windows_NT')
test('returns information for Windows', async () => {
setupTest('Windows')

expect(os.get()).toEqual({ name: 'Windows', type: 'windows' })
expect(await os.get()).toEqual({ name: 'Windows', type: 'windows' })
})

test('returns information for Linux', () => {
jest.unmock('os')
const o = jest.requireActual('os')
o.type = jest.fn(() => 'Linux')
test('returns information for Linux', async () => {
setupTest('Linux')

expect(os.get()).toEqual({ name: 'Linux', type: 'linux' })
expect(await os.get()).toEqual({ name: 'Linux', type: 'linux', distro: 'Arch' })
})

test('returns information for macOS', () => {
jest.unmock('os')
const o = jest.requireActual('os')
o.type = jest.fn(() => 'Darwin')
test('returns information for macOS', async () => {
setupTest('Darwin')

expect(os.get()).toEqual({ name: 'macOS', type: 'macos' })
expect(await os.get()).toEqual({ name: 'macOS', type: 'macos' })
})
})

Expand Down