CB-12640: support for android sdk tools 26.0.1. simplified target parsing by using avdmanager instead of sdkmanager. flipped target parsing logic so that it always tries to use avdmanager to retrieve targets first, then falls back to android command if avdmanager cannot be found (and errors with ENOENT). updated tests.

This commit is contained in:
filmaj 2017-04-06 13:13:38 -07:00
parent a4103d8dc8
commit 765c4ee9f6
8 changed files with 47 additions and 1217 deletions

View File

@ -68,65 +68,38 @@ module.exports.version_string_to_api_level = {
'7.1.1': 25 '7.1.1': 25
}; };
module.exports.list_targets_with_android = function() { function parse_targets(output) {
return superspawn.spawn('android', ['list', 'targets']) var target_out = output.split('\n');
.then(function(stdout) { var targets = [];
var target_out = stdout.split('\n'); for (var i = target_out.length - 1; i >= 0; i--) {
var targets = []; if(target_out[i].match(/id:/)) { // if "id:" is in the line...
for (var i = target_out.length - 1; i >= 0; i--) { targets.push(target_out[i].match(/"(.+)"/)[1]); //.. match whatever is in quotes.
if(target_out[i].match(/id:/)) {
targets.push(target_out[i].match(/"(.+)"/)[1]);
}
} }
return targets; }
}); return targets;
}
module.exports.list_targets_with_android = function() {
return superspawn.spawn('android', ['list', 'target'])
.then(parse_targets);
}; };
module.exports.list_targets_with_sdkmanager = function() { module.exports.list_targets_with_avdmanager = function() {
return superspawn.spawn('sdkmanager', ['--list']) return superspawn.spawn('avdmanager', ['list', 'target'])
.then(function(stdout) { .then(parse_targets);
var parsing_installed_packages = false;
var lines = stdout.split('\n');
var targets = [];
for (var i = 0, l = lines.length; i < l; i++) {
var line = lines[i];
if (line.match(/Installed packages/)) {
parsing_installed_packages = true;
} else if (line.match(/Available Packages/) || line.match(/Available Updates/)) {
// we are done working through installed packages, exit
break;
}
if (parsing_installed_packages) {
// Match stock android platform
if (line.match(/platforms;android-\d+/)) {
targets.push(line.match(/(android-\d+)/)[1]);
}
// Match Google APIs
if (line.match(/addon-google_apis-google-\d+/)) {
var description = lines[i + 1];
// munge description to match output from old android sdk tooling
var api_level = description.match(/Android (\d+)/); //[1];
if (api_level) {
targets.push('Google Inc.:Google APIs:' + api_level[1]);
}
}
// TODO: match anything else?
}
}
return targets;
});
}; };
module.exports.list_targets = function() { module.exports.list_targets = function() {
return module.exports.list_targets_with_android() return module.exports.list_targets_with_avdmanager()
.catch(function(err) { .catch(function(err) {
// there's a chance `android` no longer works. // If there's an error, like avdmanager could not be found, we can try
// lets see if `sdkmanager` is available and we can figure it out // as a last resort, to run `android`, in case this is a super old
var avail_regex = /"?android"? command is no longer available/; // SDK installation.
if (err.code && ((err.stdout && err.stdout.match(avail_regex)) || (err.stderr && err.stderr.match(avail_regex)))) { if (err && err.code == 'ENOENT') {
return module.exports.list_targets_with_sdkmanager(); return module.exports.list_targets_with_android();
} else throw err; } else throw err;
}).then(function(targets) { })
.then(function(targets) {
if (targets.length === 0) { if (targets.length === 0) {
return Q.reject(new Error('No android targets (SDKs) installed!')); return Q.reject(new Error('No android targets (SDKs) installed!'));
} }

View File

@ -0,0 +1,7 @@
Available Android targets:
----------
id: 1 or "android-25"
Name: Android API 25
Type: Platform
API level: 25
Revision: 3

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,7 @@ describe("android_sdk", function () {
it("should parse and return results from `android list targets` command", function(done) { it("should parse and return results from `android list targets` command", function(done) {
var deferred = Q.defer(); var deferred = Q.defer();
spyOn(superspawn, "spawn").and.returnValue(deferred.promise); spyOn(superspawn, "spawn").and.returnValue(deferred.promise);
deferred.resolve(fs.readFileSync(path.join("spec", "fixtures", "android_list_targets.txt"), "utf-8")); deferred.resolve(fs.readFileSync(path.join("spec", "fixtures", "sdk25.2-android_list_targets.txt"), "utf-8"));
return android_sdk.list_targets_with_android() return android_sdk.list_targets_with_android()
.then(function(list) { .then(function(list) {
[ "Google Inc.:Google APIs:23", [ "Google Inc.:Google APIs:23",
@ -53,26 +53,14 @@ describe("android_sdk", function () {
}); });
}); });
}); });
describe("list_targets_with_sdkmanager", function() { describe("list_targets_with_avdmanager", function() {
it("should parse and return results from `sdkmanager --list` command", function(done) { it("should parse and return results from `avdmanager list target` command", function(done) {
var deferred = Q.defer(); var deferred = Q.defer();
spyOn(superspawn, "spawn").and.returnValue(deferred.promise); spyOn(superspawn, "spawn").and.returnValue(deferred.promise);
deferred.resolve(fs.readFileSync(path.join("spec", "fixtures", "sdkmanager_list.txt"), "utf-8")); deferred.resolve(fs.readFileSync(path.join("spec", "fixtures", "sdk25.3-avdmanager_list_target.txt"), "utf-8"));
return android_sdk.list_targets_with_sdkmanager() return android_sdk.list_targets_with_avdmanager()
.then(function(list) { .then(function(list) {
[ "Google Inc.:Google APIs:19", expect(list).toContain("android-25");
"Google Inc.:Google APIs:21",
"Google Inc.:Google APIs:22",
"Google Inc.:Google APIs:23",
"Google Inc.:Google APIs:24",
"android-19",
"android-21",
"android-22",
"android-23",
"android-24",
"android-25" ].forEach(function(target) {
expect(list).toContain(target);
});
}).fail(function(err) { }).fail(function(err) {
console.log(err); console.log(err);
expect(err).toBeUndefined(); expect(err).toBeUndefined();
@ -82,25 +70,24 @@ describe("android_sdk", function () {
}); });
}); });
describe("list_targets", function() { describe("list_targets", function() {
it("should parse Android SDK installed target information with `android` command first", function() { it("should parse Android SDK installed target information with `avdmanager` command first", function() {
var deferred = Q.defer(); var deferred = Q.defer();
var android_spy = spyOn(android_sdk, "list_targets_with_android").and.returnValue(deferred.promise); var avdmanager_spy = spyOn(android_sdk, "list_targets_with_avdmanager").and.returnValue(deferred.promise);
android_sdk.list_targets(); android_sdk.list_targets();
expect(android_spy).toHaveBeenCalled(); expect(avdmanager_spy).toHaveBeenCalled();
}); });
it("should parse Android SDK installed target information with `avdmanager` command if list_targets_with_android fails due to `android` command being obsolete", function(done) { it("should parse Android SDK installed target information with `android` command if list_targets_with_avdmanager fails with ENOENT", function(done) {
var deferred = Q.defer(); var deferred = Q.defer();
spyOn(android_sdk, "list_targets_with_android").and.returnValue(deferred.promise); spyOn(android_sdk, "list_targets_with_avdmanager").and.returnValue(deferred.promise);
deferred.reject({ deferred.reject({
code: 1, code: "ENOENT"
stdout: "The android command is no longer available."
}); });
var twoferred = Q.defer(); var twoferred = Q.defer();
twoferred.resolve(["target1"]); twoferred.resolve(["target1"]);
var sdkmanager_spy = spyOn(android_sdk, "list_targets_with_sdkmanager").and.returnValue(twoferred.promise); var avdmanager_spy = spyOn(android_sdk, "list_targets_with_android").and.returnValue(twoferred.promise);
return android_sdk.list_targets() return android_sdk.list_targets()
.then(function(targets) { .then(function(targets) {
expect(sdkmanager_spy).toHaveBeenCalled(); expect(avdmanager_spy).toHaveBeenCalled();
expect(targets[0]).toEqual("target1"); expect(targets[0]).toEqual("target1");
done(); done();
}); });

View File

@ -28,7 +28,7 @@ describe("emulator", function () {
it("should properly parse details of SDK Tools 25.3.1 `avdmanager` output", function(done) { it("should properly parse details of SDK Tools 25.3.1 `avdmanager` output", function(done) {
var deferred = Q.defer(); var deferred = Q.defer();
spyOn(cc.superspawn, "spawn").and.returnValue(deferred.promise); spyOn(cc.superspawn, "spawn").and.returnValue(deferred.promise);
deferred.resolve(fs.readFileSync(path.join("spec", "fixtures", "avdmanager_list_avd.txt"), "utf-8")); deferred.resolve(fs.readFileSync(path.join("spec", "fixtures", "sdk25.3-avdmanager_list_avd.txt"), "utf-8"));
return emu.list_images_using_avdmanager() return emu.list_images_using_avdmanager()
.then(function(list) { .then(function(list) {
expect(list).toBeDefined(); expect(list).toBeDefined();
@ -47,7 +47,7 @@ describe("emulator", function () {
it("should properly parse details of SDK Tools pre-25.3.1 `android list avd` output", function(done) { it("should properly parse details of SDK Tools pre-25.3.1 `android list avd` output", function(done) {
var deferred = Q.defer(); var deferred = Q.defer();
spyOn(cc.superspawn, "spawn").and.returnValue(deferred.promise); spyOn(cc.superspawn, "spawn").and.returnValue(deferred.promise);
deferred.resolve(fs.readFileSync(path.join("spec", "fixtures", "android_list_avd.txt"), "utf-8")); deferred.resolve(fs.readFileSync(path.join("spec", "fixtures", "sdk25.2-android_list_avd.txt"), "utf-8"));
return emu.list_images_using_android() return emu.list_images_using_android()
.then(function(list) { .then(function(list) {
expect(list).toBeDefined(); expect(list).toBeDefined();