Skip to content

Commit

Permalink
feat(update): on update, write full binary paths to file (#140)
Browse files Browse the repository at this point in the history
- Adding back in curl calls, these were removed on the new
  `Downloader.getFile`. Add curl call to reflect proxies.

- Fix output dir to read from update's options instead of Config

- Feature will help directConnect users for Protractor. The file
  will keep track of the last binary version as well as all other
  binaries downloaded.

  The file will be created in the output directory. By default this is
  `selenium/update-config.json`. On `clean` this file will be removed.

  ```
  webdriver-manager update --versions.chrome=2.20 --standalone=false
  --gecko=false
  ```

  file created:
  ```
  {
    "chrome": {
      "last": "/opt/src/webdriver-manager/selenium/chromedriver_2.20",
      "all": ["/opt/src/webdriver-manager/selenium/chromedriver_2.20"]
    }
  }
  ```

  then the user wants to use 2.25:

  ```
  webdriver-manager update --versions.chrome=2.25 --standalone=false
  --gecko=false

  ```

  file created:
  ```
  {
    "chrome": {
      "last": "/opt/src/webdriver-manager/selenium/chromedriver_2.25",
      "all": ["/opt/src/webdriver-manager/selenium/chromedriver_2.20",
              "/opt/src/webdriver-manager/selenium/chromedriver_2.25"]
    }
  }
  ```
  • Loading branch information
cnishina authored Nov 30, 2016
1 parent f38a713 commit b5638ef
Show file tree
Hide file tree
Showing 10 changed files with 242 additions and 58 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
built/
node_modules/
selenium/
selenium_test/
typings/
.idea/
npm-debug.log
8 changes: 4 additions & 4 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ gulp.task('shutdown', ['build'], function(done) {
});

// Test
gulp.task('test:unit', ['build'], function(done) {
gulp.task('test:unit', ['format', 'build'], function(done) {
runSpawn(process.execPath, ['node_modules/jasmine/bin/jasmine.js'], done);
});

Expand All @@ -99,6 +99,6 @@ gulp.task('test:e2e:headless', function(done) {
});


gulp.task('test', ['format', 'test:unit', 'test:e2e']);
gulp.task('test:no_update', ['format', 'test:unit', 'test:e2e:no_update']);
gulp.task('test:headless', ['format', 'test:unit', 'test:e2e:headless']);
gulp.task('test', ['test:unit', 'test:e2e']);
gulp.task('test:no_update', ['test:unit', 'test:e2e:no_update']);
gulp.task('test:headless', ['test:unit', 'test:e2e:headless']);
4 changes: 2 additions & 2 deletions lib/cli/programs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@ export class Program {
* method.
* @param args The arguments that will be parsed to run the method.
*/
run(json: JSON): void {
run(json: JSON): Promise<void> {
for (let opt in this.options) {
this.options[opt].value = this.getValue_(opt, json);
}
this.runMethod(this.options);
return Promise.resolve(this.runMethod(this.options));
}

private getValue_(key: string, json: JSON): number|boolean|string {
Expand Down
130 changes: 97 additions & 33 deletions lib/cmds/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,14 @@ if (argv._[0] === 'update-run') {
prog.printHelp();
}

let browserFile: BrowserFile;

/**
* Parses the options and downloads binaries if they do not exist.
* @param options
*/
function update(options: Options): void {
function update(options: Options): Promise<void> {
let promises: q.IPromise<void>[] = [];
let standalone = options[Opt.STANDALONE].getBoolean();
let chrome = options[Opt.CHROME].getBoolean();
let gecko = options[Opt.GECKO].getBoolean();
Expand All @@ -83,7 +85,15 @@ function update(options: Options): void {
if (options[Opt.IOS]) {
ios = options[Opt.IOS].getBoolean();
}
let outputDir = Config.getSeleniumDir();
let outputDir = options[Opt.OUT_DIR].getString();

try {
browserFile =
JSON.parse(fs.readFileSync(path.resolve(outputDir, 'update-config.json')).toString());
} catch (err) {
browserFile = {};
}

let android_api_levels: string[] = options[Opt.ANDROID_API_LEVELS].getString().split(',');
let android_architectures: string[] = options[Opt.ANDROID_ARCHITECTURES].getString().split(',');
let android_platforms: string[] = options[Opt.ANDROID_PLATFORMS].getString().split(',');
Expand Down Expand Up @@ -118,63 +128,74 @@ function update(options: Options): void {
// permissions
if (standalone) {
let binary = binaries[StandAlone.id];
FileManager.downloadFile(binary, outputDir, proxy, ignoreSSL).then((downloaded: boolean) => {
if (!downloaded) {
logger.info(
binary.name + ': file exists ' +
path.resolve(outputDir, binary.filename(Config.osType(), Config.osArch())));
logger.info(binary.name + ': v' + binary.versionCustom + ' up to date');
}
});
updateBrowserFile(binary, outputDir);
promises.push(
FileManager.downloadFile(binary, outputDir, proxy, ignoreSSL)
.then<void>((downloaded: boolean) => {
if (!downloaded) {
logger.info(
binary.name + ': file exists ' +
path.resolve(outputDir, binary.filename(Config.osType(), Config.osArch())));
logger.info(binary.name + ': ' + binary.versionCustom + ' up to date');
}
}));
}
if (chrome) {
let binary = binaries[ChromeDriver.id];
updateBinary(binary, outputDir, proxy, ignoreSSL);
updateBrowserFile(binary, outputDir);
promises.push(updateBinary(binary, outputDir, proxy, ignoreSSL));
}
if (gecko) {
let binary = binaries[GeckoDriver.id];
updateBinary(binary, outputDir, proxy, ignoreSSL);
updateBrowserFile(binary, outputDir);
promises.push(updateBinary(binary, outputDir, proxy, ignoreSSL));
}
if (ie) {
let binary = binaries[IEDriver.id];
binary.arch = Config.osArch(); // Win32 or x64
updateBinary(binary, outputDir, proxy, ignoreSSL);
updateBrowserFile(binary, outputDir);
promises.push(updateBinary(binary, outputDir, proxy, ignoreSSL));
}
if (ie32) {
let binary = binaries[IEDriver.id];
binary.arch = 'Win32';
updateBinary(binary, outputDir, proxy, ignoreSSL);
updateBrowserFile(binary, outputDir);
promises.push(updateBinary(binary, outputDir, proxy, ignoreSSL));
}
if (android) {
let binary = binaries[AndroidSDK.id];
let sdk_path = path.resolve(outputDir, binary.executableFilename(Config.osType()));
let oldAVDList: string;

q.nfcall(fs.readFile, path.resolve(sdk_path, 'available_avds.json'))
.then(
(oldAVDs: string) => {
oldAVDList = oldAVDs;
},
() => {
oldAVDList = '[]';
})
.then(() => {
return updateBinary(binary, outputDir, proxy, ignoreSSL);
})
.then(() => {
initializeAndroid(
path.resolve(outputDir, binary.executableFilename(Config.osType())),
android_api_levels, android_architectures, android_platforms, android_accept_licenses,
binaries[AndroidSDK.id].versionCustom, JSON.parse(oldAVDList), logger, verbose);
})
.done();
promises.push(q.nfcall(fs.readFile, path.resolve(sdk_path, 'available_avds.json'))
.then(
(oldAVDs: string) => {
oldAVDList = oldAVDs;
},
() => {
oldAVDList = '[]';
})
.then(() => {
return updateBinary(binary, outputDir, proxy, ignoreSSL);
})
.then<void>(() => {
initializeAndroid(
path.resolve(outputDir, binary.executableFilename(Config.osType())),
android_api_levels, android_architectures, android_platforms,
android_accept_licenses, binaries[AndroidSDK.id].versionCustom,
JSON.parse(oldAVDList), logger, verbose);
}));
}
if (ios) {
checkIOS(logger);
}
if (android || ios) {
installAppium(binaries[Appium.id], outputDir);
}

writeBrowserFile(outputDir);

return Promise.all(promises).then(() => {});
}

function updateBinary(
Expand All @@ -193,7 +214,7 @@ function updateBinary(
path.resolve(outputDir, binary.filename(Config.osType(), Config.osArch())));
let fileName = binary.filename(Config.osType(), Config.osArch());
unzip(binary, outputDir, fileName);
logger.info(binary.name + ': v' + binary.versionCustom + ' up to date');
logger.info(binary.name + ': ' + binary.versionCustom + ' up to date');
}
});
}
Expand Down Expand Up @@ -251,3 +272,46 @@ function installAppium(binary: Binary, outputDir: string): void {
path.resolve(folder, 'package.json'), JSON.stringify({scripts: {appium: 'appium'}}));
spawn('npm', ['install', 'appium@' + binary.version()], null, {cwd: folder});
}

interface BinaryPath {
last?: string, all?: string[]
}

interface BrowserFile {
chrome?: BinaryPath, standalone?: BinaryPath, gecko?: BinaryPath, iedriver?: BinaryPath
}

function updateBrowserFile<T extends Binary>(binary: T, outputDir: string) {
let currentDownload = path.resolve(outputDir, binary.executableFilename(Config.osType()));

// if browserFile[id] exists, we should update it
if ((browserFile as any)[binary.id()]) {
let binaryPath: BinaryPath = (browserFile as any)[binary.id()];
if (binaryPath.last === currentDownload) {
return;
} else {
binaryPath.last = currentDownload;
for (let bin of binaryPath.all) {
if (bin === currentDownload) {
return;
}
}
binaryPath.all.push(currentDownload);
}
} else {
// The browserFile[id] does not exist / has not been downloaded previously.
// We should create the entry.
let binaryPath: BinaryPath = {last: currentDownload, all: [currentDownload]};
(browserFile as any)[binary.id()] = binaryPath;
}
}

function writeBrowserFile(outputDir: string) {
let filePath = path.resolve(outputDir, 'update-config.json');
fs.writeFileSync(filePath, JSON.stringify(browserFile));
}

// for testing
export function clearBrowserFile() {
browserFile = {};
}
17 changes: 13 additions & 4 deletions lib/files/downloader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ export class Downloader {
static getFile(
binary: Binary, fileUrl: string, fileName: string, outputDir: string, contentLength: number,
opt_proxy?: string, opt_ignoreSSL?: boolean, callback?: Function): Promise<any> {
// logger.info('curl -o ' + outputDir + '/' + fileName + ' ' + fileUrl);
// let contentLength = 0;
let filePath = path.resolve(outputDir, fileName);
let file: any;

Expand All @@ -90,8 +88,8 @@ export class Downloader {

if (opt_proxy) {
options.proxy = Downloader.resolveProxy_(fileUrl, opt_proxy);
if (options.url.indexOf('https://') === 0) {
options.url = options.url.replace('https://', 'http://');
if (url.parse(options.url).protocol === 'https:') {
options.url = options.url.replace('https:', 'http:');
}
}

Expand All @@ -108,6 +106,17 @@ export class Downloader {
response.destroy();
resolve(false);
} else {
if (opt_proxy) {
let pathUrl = url.parse(options.url).path;
let host = url.parse(options.url).host;
let newFileUrl = url.resolve(opt_proxy, pathUrl);
logger.info(
'curl -o ' + outputDir + '/' + fileName + ' \'' + newFileUrl +
'\' -H \'host:' + host + '\'');
} else {
logger.info('curl -o ' + outputDir + '/' + fileName + ' ' + fileUrl);
}

// only pipe if the headers are different length
file = fs.createWriteStream(filePath);
req.pipe(file);
Expand Down
33 changes: 20 additions & 13 deletions lib/files/file_manager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as fs from 'fs';
import * as path from 'path';
import * as q from 'q';
import * as rimraf from 'rimraf';

import {Binary, BinaryMap, ChromeDriver, IEDriver, AndroidSDK, Appium, StandAlone, OS} from
'../binaries';
Expand Down Expand Up @@ -188,7 +187,7 @@ export class FileManager {
let v = versions[index];
if (v === version) {
contentLength = fs.statSync(filePath).size;
Downloader
return Downloader
.getFile(
binary, fileUrl, fileName, outputDir, contentLength, opt_proxy, opt_ignoreSSL,
callback)
Expand All @@ -197,17 +196,17 @@ export class FileManager {
});
}
}
} else {
// We have not downloaded it before, or the version does not exist. Use the default content
// length of zero and download the file.
Downloader
.getFile(
binary, fileUrl, fileName, outputDir, contentLength, opt_proxy, opt_ignoreSSL,
callback)
.then(downloaded => {
resolve(downloaded);
});
}
// We have not downloaded it before, or the version does not exist. Use the default content
// length of zero and download the file.
Downloader
.getFile(
binary, fileUrl, fileName, outputDir, contentLength, opt_proxy, opt_ignoreSSL,
callback)
.then(downloaded => {
resolve(downloaded);
});

});
}

Expand Down Expand Up @@ -238,6 +237,14 @@ export class FileManager {
logger.info('removed ' + file);
}
}
})
});

let updateConfig = path.resolve(outputDir, 'update-config.json');
try {
fs.unlinkSync(updateConfig);
logger.info('removed update-config.json');
} catch (e) {
return;
}
}
}
1 change: 0 additions & 1 deletion lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import * as path from 'path';

import {Config} from './config';


function spawnFactory(sync: false):
(cmd: string, args: string[], stdio?: any, opts?: child_process.SpawnOptions) =>
child_process.ChildProcess;
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"format": "gulp format",
"prepublish": "gulp prepublish",
"test": "gulp test",
"test_unit": "gulp test:unit",
"test_travis": "gulp test:headless"
},
"keywords": [
Expand Down
Loading

0 comments on commit b5638ef

Please sign in to comment.