/// <summary> /// Parse "android list sdk -u -e -a" output. /// </summary> private AndroidSdkPackageCollection ParseAndroidListSdkOutput( string androidListSdkOutput) { var packages = new AndroidSdkPackageCollection(); AndroidSdkPackage currentPackage = null; foreach (string line in CommandLine.SplitLines(androidListSdkOutput)) { // Check for the start of a new package entry. if (line.StartsWith("---")) { currentPackage = null; continue; } Match match; // If this is the start of a package description, add a package. match = PACKAGE_ID_REGEX.Match(line); if (match.Success) { // TODO(smiles): Convert the legacy package name to a new package name. currentPackage = new AndroidSdkPackage { LegacyName = match.Groups[1].Value }; packages[currentPackage.Name].Add(currentPackage); continue; } if (currentPackage == null) { continue; } // Add a package description. match = PACKAGE_DESCRIPTION_REGEX.Match(line); if (match.Success) { currentPackage.Description = match.Groups[1].Value; continue; } // Parse the install path and record whether the package is installed. match = PACKAGE_INSTALL_LOCATION_REGEX.Match(line); if (match.Success) { currentPackage.Installed = File.Exists( Path.Combine(Path.Combine(sdkPath, match.Groups[1].Value), "source.properties")); } } return(packages); }
/// <summary> /// Parse "sdkmanager --list" output. /// </summary> /// <returns>Dictionary of packages bucketed by package name</returns> private AndroidSdkPackageCollection ParseListOutput( string sdkManagerListOutput) { var packages = new AndroidSdkPackageCollection(); // Whether we're parsing a set of packages. bool parsingPackages = false; // Whether we're parsing within the set of installed packages vs. available packages. bool parsingInstalledPackages = false; // Whether we're parsing the contents of the package table vs. the header. bool inPackageTable = false; foreach (var rawLine in CommandLine.SplitLines(sdkManagerListOutput)) { var line = rawLine.Trim(); var lowerCaseLine = line.ToLower(); if (lowerCaseLine == AVAILABLE_UPDATES_HEADER) { parsingPackages = false; continue; } bool installedPackagesLine = lowerCaseLine == INSTALLED_PACKAGES_HEADER; bool availablePackagesLine = lowerCaseLine == AVAILABLE_PACKAGES_HEADER; if (installedPackagesLine || availablePackagesLine) { parsingPackages = true; parsingInstalledPackages = installedPackagesLine; inPackageTable = false; continue; } if (!parsingPackages) { continue; } if (!inPackageTable) { // If we've reached end of the table header, start parsing the set of packages. if (line.StartsWith("----")) { inPackageTable = true; } continue; } // Split into the fields package_name|version|description|location. // Where "location" is an optional field that contains the install path. var rawTokens = line.Split(new [] { '|' }); if (rawTokens.Length < 3 || String.IsNullOrEmpty(line)) { parsingPackages = false; continue; } // Each field is surrounded by whitespace so trim the fields. string[] tokens = new string[rawTokens.Length]; for (int i = 0; i < rawTokens.Length; ++i) { tokens[i] = rawTokens[i].Trim(); } var packageName = tokens[0]; packages[packageName].Add(new AndroidSdkPackage { Name = packageName, Description = tokens[2], VersionString = tokens[1], Installed = parsingInstalledPackages }); } return(packages); }
/// <summary> /// Parse "sdkmanager --list --verbose" output. /// NOTE: The --verbose output format is only reported by sdkmanager 26.0.2 and above. /// </summary> private AndroidSdkPackageCollection ParseListVerboseOutput( string sdkManagerListVerboseOutput) { var packages = new AndroidSdkPackageCollection(); // Whether we're parsing a set of packages. bool parsingPackages = false; // Whether we're parsing within the set of installed packages vs. available packages. bool parsingInstalledPackages = false; // Fields of the package being parsed. AndroidSdkPackage currentPackage = null; foreach (var rawLine in CommandLine.SplitLines(sdkManagerListVerboseOutput)) { var line = rawLine.Trim(); var lowerCaseLine = line.ToLower(); if (lowerCaseLine == AVAILABLE_UPDATES_HEADER) { parsingPackages = false; continue; } bool installedPackagesLine = lowerCaseLine == INSTALLED_PACKAGES_HEADER; bool availablePackagesLine = lowerCaseLine == AVAILABLE_PACKAGES_HEADER; if (installedPackagesLine || availablePackagesLine) { parsingPackages = true; parsingInstalledPackages = installedPackagesLine; continue; } else if (line.StartsWith("---")) { // Ignore section separators. continue; } else if (String.IsNullOrEmpty(line)) { if (currentPackage != null && !(String.IsNullOrEmpty(currentPackage.Name) || String.IsNullOrEmpty(currentPackage.VersionString))) { packages[currentPackage.Name].Add(currentPackage); } currentPackage = null; continue; } else if (!parsingPackages) { continue; } // Fields of the package are indented. bool indentedLine = rawLine.StartsWith(" "); if (!indentedLine) { // If this isn't an indented line it should be a package name. if (currentPackage == null) { currentPackage = new AndroidSdkPackage { Name = line, Installed = parsingInstalledPackages }; } } else if (currentPackage != null) { // Parse the package field. var fieldSeparatorIndex = line.IndexOf(":"); if (fieldSeparatorIndex >= 0) { var fieldName = line.Substring(0, fieldSeparatorIndex).Trim().ToLower(); var fieldValue = line.Substring(fieldSeparatorIndex + 1).Trim(); if (fieldName == "description") { currentPackage.Description = fieldValue; } else if (fieldName == "version") { currentPackage.VersionString = fieldValue; } } } } return(packages); }