mirror of
https://github.com/balena-io/etcher.git
synced 2025-07-27 13:16:36 +00:00
Convert window-network-drives.js to typescript
Change-type: patch
This commit is contained in:
parent
255fae3a90
commit
b266a72726
@ -1,143 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 balena.io
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict'
|
|
||||||
|
|
||||||
const Bluebird = require('bluebird')
|
|
||||||
const cp = require('child_process')
|
|
||||||
const fs = require('fs')
|
|
||||||
const _ = require('lodash')
|
|
||||||
const os = require('os')
|
|
||||||
const Path = require('path')
|
|
||||||
const process = require('process')
|
|
||||||
const { promisify } = require('util')
|
|
||||||
|
|
||||||
const { tmpFileDisposer } = require('../../../shared/utils')
|
|
||||||
|
|
||||||
const readFileAsync = promisify(fs.readFile)
|
|
||||||
|
|
||||||
const execAsync = promisify(cp.exec)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @summary Returns wmic's output for network drives
|
|
||||||
* @function
|
|
||||||
*
|
|
||||||
* @returns {Promise<String>}
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* const output = await getWmicNetworkDrivesOutput()
|
|
||||||
*/
|
|
||||||
exports.getWmicNetworkDrivesOutput = async () => {
|
|
||||||
// Exported for tests.
|
|
||||||
// When trying to read wmic's stdout directly from node, it is encoded with the current
|
|
||||||
// console codepage (depending on the computer).
|
|
||||||
// Decoding this would require getting this codepage somehow and using iconv as node
|
|
||||||
// doesn't know how to read cp850 directly for example.
|
|
||||||
// We could also use wmic's "/output:" switch but it doesn't work when the filename
|
|
||||||
// contains a space and the os temp dir may contain spaces ("D:\Windows Temp Files" for example).
|
|
||||||
// So we just redirect to a file and read it afterwards as we know it will be ucs2 encoded.
|
|
||||||
const options = {
|
|
||||||
|
|
||||||
// Close the file once it's created
|
|
||||||
discardDescriptor: true,
|
|
||||||
|
|
||||||
// Wmic fails with "Invalid global switch" when the "/output:" switch filename contains a dash ("-")
|
|
||||||
prefix: 'tmp'
|
|
||||||
}
|
|
||||||
return Bluebird.using(tmpFileDisposer(options), async ({ path }) => {
|
|
||||||
const command = [
|
|
||||||
Path.join(process.env.SystemRoot, 'System32', 'Wbem', 'wmic'),
|
|
||||||
'path',
|
|
||||||
'Win32_LogicalDisk',
|
|
||||||
'Where',
|
|
||||||
'DriveType="4"',
|
|
||||||
'get',
|
|
||||||
'DeviceID,ProviderName',
|
|
||||||
'>',
|
|
||||||
`"${path}"`
|
|
||||||
]
|
|
||||||
await execAsync(command.join(' '), { windowsHide: true })
|
|
||||||
return readFileAsync(path, 'ucs2')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @summary returns a Map of drive letter -> network locations on Windows
|
|
||||||
* @function
|
|
||||||
*
|
|
||||||
* @returns {Promise<Map<String, String>>} - 'Z:' -> '\\\\192.168.0.1\\Public'
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* getWindowsNetworkDrives()
|
|
||||||
* .then(console.log);
|
|
||||||
*/
|
|
||||||
const getWindowsNetworkDrives = async () => {
|
|
||||||
const result = await exports.getWmicNetworkDrivesOutput()
|
|
||||||
const couples = _.chain(result)
|
|
||||||
.split('\n')
|
|
||||||
|
|
||||||
// Remove header line
|
|
||||||
// eslint-disable-next-line no-magic-numbers
|
|
||||||
.slice(1)
|
|
||||||
|
|
||||||
// Remove extra spaces / tabs / carriage returns
|
|
||||||
.invokeMap(String.prototype.trim)
|
|
||||||
|
|
||||||
// Filter out empty lines
|
|
||||||
.compact()
|
|
||||||
.map((str) => {
|
|
||||||
const colonPosition = str.indexOf(':')
|
|
||||||
// eslint-disable-next-line no-magic-numbers
|
|
||||||
if (colonPosition === -1) {
|
|
||||||
throw new Error(`Can't parse wmic output: ${result}`)
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line no-magic-numbers
|
|
||||||
return [ str.slice(0, colonPosition + 1), _.trim(str.slice(colonPosition + 1)) ]
|
|
||||||
})
|
|
||||||
// eslint-disable-next-line no-magic-numbers
|
|
||||||
.filter((couple) => couple[1].length > 0)
|
|
||||||
.value()
|
|
||||||
return new Map(couples)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @summary Replaces network drive letter with network drive location in the provided filePath on Windows
|
|
||||||
* @function
|
|
||||||
*
|
|
||||||
* @param {String} filePath - file path
|
|
||||||
*
|
|
||||||
* @returns {String} - updated file path
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* replaceWindowsNetworkDriveLetter('Z:\\some-file')
|
|
||||||
* .then(console.log);
|
|
||||||
*/
|
|
||||||
exports.replaceWindowsNetworkDriveLetter = async (filePath) => {
|
|
||||||
let result = filePath
|
|
||||||
if (os.platform() === 'win32') {
|
|
||||||
const matches = /^([A-Z]+:)\\(.*)$/.exec(filePath)
|
|
||||||
if (matches !== null) {
|
|
||||||
const [ , drive, relativePath ] = matches
|
|
||||||
const drives = await getWindowsNetworkDrives()
|
|
||||||
const location = drives.get(drive)
|
|
||||||
// eslint-disable-next-line no-undefined
|
|
||||||
if (location !== undefined) {
|
|
||||||
result = `${location}\\${relativePath}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
115
lib/gui/app/os/windows-network-drives.ts
Executable file
115
lib/gui/app/os/windows-network-drives.ts
Executable file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 balena.io
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { using } from 'bluebird';
|
||||||
|
import { exec } from 'child_process';
|
||||||
|
import { readFile } from 'fs';
|
||||||
|
import { chain, trim } from 'lodash';
|
||||||
|
import { platform } from 'os';
|
||||||
|
import { join } from 'path';
|
||||||
|
import { env } from 'process';
|
||||||
|
import { promisify } from 'util';
|
||||||
|
|
||||||
|
import { tmpFileDisposer } from '../../../shared/utils';
|
||||||
|
|
||||||
|
const readFileAsync = promisify(readFile);
|
||||||
|
|
||||||
|
const execAsync = promisify(exec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Returns wmic's output for network drives
|
||||||
|
*/
|
||||||
|
export async function getWmicNetworkDrivesOutput(): Promise<string> {
|
||||||
|
// Exported for tests.
|
||||||
|
// When trying to read wmic's stdout directly from node, it is encoded with the current
|
||||||
|
// console codepage (depending on the computer).
|
||||||
|
// Decoding this would require getting this codepage somehow and using iconv as node
|
||||||
|
// doesn't know how to read cp850 directly for example.
|
||||||
|
// We could also use wmic's "/output:" switch but it doesn't work when the filename
|
||||||
|
// contains a space and the os temp dir may contain spaces ("D:\Windows Temp Files" for example).
|
||||||
|
// So we just redirect to a file and read it afterwards as we know it will be ucs2 encoded.
|
||||||
|
const options = {
|
||||||
|
// Close the file once it's created
|
||||||
|
discardDescriptor: true,
|
||||||
|
// Wmic fails with "Invalid global switch" when the "/output:" switch filename contains a dash ("-")
|
||||||
|
prefix: 'tmp',
|
||||||
|
};
|
||||||
|
return using(tmpFileDisposer(options), async ({ path }) => {
|
||||||
|
const command = [
|
||||||
|
join(env.SystemRoot as string, 'System32', 'Wbem', 'wmic'),
|
||||||
|
'path',
|
||||||
|
'Win32_LogicalDisk',
|
||||||
|
'Where',
|
||||||
|
'DriveType="4"',
|
||||||
|
'get',
|
||||||
|
'DeviceID,ProviderName',
|
||||||
|
'>',
|
||||||
|
`"${path}"`,
|
||||||
|
];
|
||||||
|
await execAsync(command.join(' '), { windowsHide: true });
|
||||||
|
return readFileAsync(path, 'ucs2');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary returns a Map of drive letter -> network locations on Windows: 'Z:' -> '\\\\192.168.0.1\\Public'
|
||||||
|
*/
|
||||||
|
async function getWindowsNetworkDrives(): Promise<Map<string, string>> {
|
||||||
|
// Use getWindowsNetworkDrives from "exports." so it can be mocked in tests
|
||||||
|
const result = await exports.getWmicNetworkDrivesOutput();
|
||||||
|
const couples: Array<[string, string]> = chain(result)
|
||||||
|
.split('\n')
|
||||||
|
// Remove header line
|
||||||
|
.slice(1)
|
||||||
|
// Remove extra spaces / tabs / carriage returns
|
||||||
|
.invokeMap(String.prototype.trim)
|
||||||
|
// Filter out empty lines
|
||||||
|
.compact()
|
||||||
|
.map((str: string): [string, string] => {
|
||||||
|
const colonPosition = str.indexOf(':');
|
||||||
|
if (colonPosition === -1) {
|
||||||
|
throw new Error(`Can't parse wmic output: ${result}`);
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
str.slice(0, colonPosition + 1),
|
||||||
|
trim(str.slice(colonPosition + 1)),
|
||||||
|
];
|
||||||
|
})
|
||||||
|
.filter(couple => couple[1].length > 0)
|
||||||
|
.value();
|
||||||
|
return new Map(couples);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Replaces network drive letter with network drive location in the provided filePath on Windows
|
||||||
|
*/
|
||||||
|
export async function replaceWindowsNetworkDriveLetter(
|
||||||
|
filePath: string,
|
||||||
|
): Promise<string> {
|
||||||
|
let result = filePath;
|
||||||
|
if (platform() === 'win32') {
|
||||||
|
const matches = /^([A-Z]+:)\\(.*)$/.exec(filePath);
|
||||||
|
if (matches !== null) {
|
||||||
|
const [, drive, relativePath] = matches;
|
||||||
|
const drives = await getWindowsNetworkDrives();
|
||||||
|
const location = drives.get(drive);
|
||||||
|
if (location !== undefined) {
|
||||||
|
result = `${location}\\${relativePath}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
20
npm-shrinkwrap.json
generated
20
npm-shrinkwrap.json
generated
@ -1193,9 +1193,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "6.14.9",
|
"version": "12.12.24",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-6.14.9.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.24.tgz",
|
||||||
"integrity": "sha512-leP/gxHunuazPdZaCvsCefPQxinqUDsCxCR5xaDUrY2MkYxQRFZZwU5e7GojyYsGB7QVtCi7iVEl/hoFXQYc+w=="
|
"integrity": "sha512-1Ciqv9pqwVtW6FsIUKSZNB82E5Cu1I2bBTj1xuIHXLe/1zYLl3956Nbhg2MzSYHVfl9/rmanjbQIb7LibfCnug=="
|
||||||
},
|
},
|
||||||
"@types/normalize-package-data": {
|
"@types/normalize-package-data": {
|
||||||
"version": "2.4.0",
|
"version": "2.4.0",
|
||||||
@ -6054,6 +6054,13 @@
|
|||||||
"unzip-stream": "^0.3.0",
|
"unzip-stream": "^0.3.0",
|
||||||
"xxhash": "^0.3.0",
|
"xxhash": "^0.3.0",
|
||||||
"yauzl": "^2.9.2"
|
"yauzl": "^2.9.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": {
|
||||||
|
"version": "6.14.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-6.14.9.tgz",
|
||||||
|
"integrity": "sha512-leP/gxHunuazPdZaCvsCefPQxinqUDsCxCR5xaDUrY2MkYxQRFZZwU5e7GojyYsGB7QVtCi7iVEl/hoFXQYc+w=="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"event-emitter": {
|
"event-emitter": {
|
||||||
@ -10037,6 +10044,13 @@
|
|||||||
"@types/node": "^6.0.112",
|
"@types/node": "^6.0.112",
|
||||||
"@types/usb": "^1.5.1",
|
"@types/usb": "^1.5.1",
|
||||||
"debug": "^3.1.0"
|
"debug": "^3.1.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": {
|
||||||
|
"version": "6.14.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-6.14.9.tgz",
|
||||||
|
"integrity": "sha512-leP/gxHunuazPdZaCvsCefPQxinqUDsCxCR5xaDUrY2MkYxQRFZZwU5e7GojyYsGB7QVtCi7iVEl/hoFXQYc+w=="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node-releases": {
|
"node-releases": {
|
||||||
|
@ -94,6 +94,7 @@
|
|||||||
"@babel/plugin-proposal-function-bind": "^7.2.0",
|
"@babel/plugin-proposal-function-bind": "^7.2.0",
|
||||||
"@babel/preset-env": "^7.6.0",
|
"@babel/preset-env": "^7.6.0",
|
||||||
"@babel/preset-react": "^7.0.0",
|
"@babel/preset-react": "^7.0.0",
|
||||||
|
"@types/node": "^12.12.24",
|
||||||
"@types/react-dom": "^16.8.4",
|
"@types/react-dom": "^16.8.4",
|
||||||
"babel-loader": "^8.0.4",
|
"babel-loader": "^8.0.4",
|
||||||
"chalk": "^1.1.3",
|
"chalk": "^1.1.3",
|
||||||
|
@ -22,6 +22,7 @@ const m = require('mochainon')
|
|||||||
const { env } = require('process')
|
const { env } = require('process')
|
||||||
const { promisify } = require('util')
|
const { promisify } = require('util')
|
||||||
|
|
||||||
|
// eslint-disable-next-line node/no-missing-require
|
||||||
const wnd = require('../../../lib/gui/app/os/windows-network-drives')
|
const wnd = require('../../../lib/gui/app/os/windows-network-drives')
|
||||||
|
|
||||||
const readFileAsync = promisify(readFile)
|
const readFileAsync = promisify(readFile)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user