-
Notifications
You must be signed in to change notification settings - Fork 240
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #75 from leoafarias/feature/list-releases
Feature/list releases
- Loading branch information
Showing
14 changed files
with
302 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import 'package:args/command_runner.dart'; | ||
import 'package:console/console.dart'; | ||
import 'package:date_format/date_format.dart'; | ||
import 'package:io/ansi.dart'; | ||
|
||
import 'package:fvm/utils/releases_helper.dart'; | ||
|
||
/// List installed SDK Versions | ||
class ReleasesCommand extends Command { | ||
// The [name] and [description] properties must be defined by every | ||
// subclass. | ||
@override | ||
final name = 'releases'; | ||
|
||
@override | ||
final description = 'Lists Flutter SDK releases.'; | ||
|
||
/// Constructor | ||
ReleasesCommand(); | ||
|
||
@override | ||
void run() async { | ||
final flutterReleases = await fetchReleases(); | ||
final channels = flutterReleases.currentRelease.toHashMap(); | ||
final releases = flutterReleases.releases.reversed; | ||
|
||
releases.forEach((r) { | ||
final channel = channels[r.version]; | ||
final channelOutput = green.wrap('$channel'); | ||
final version = yellow.wrap(r.version.padRight(17)); | ||
final pipe = Icon.PIPE_VERTICAL; | ||
final friendlyDate = | ||
formatDate(r.releaseDate, [M, ' ', d, ' ', yy]).padRight(10); | ||
if (channel != null) { | ||
print('----------$channelOutput----------'); | ||
print('$friendlyDate $pipe $version'); | ||
} else { | ||
print('$friendlyDate $pipe $version'); | ||
} | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
import 'dart:convert'; | ||
import 'dart:io'; | ||
|
||
import 'package:fvm/exceptions.dart'; | ||
import 'package:http/http.dart' as http; | ||
|
||
/// Gets platform specific release URL | ||
String getReleasesUrl({String platform}) { | ||
platform ??= Platform.operatingSystem; | ||
return 'https://storage.googleapis.com/flutter_infra/releases/releases_$platform.json'; | ||
} | ||
|
||
/// Fetches Flutter SDK Releases | ||
Future<FlutterReleases> fetchReleases() async { | ||
try { | ||
final response = await http.get(getReleasesUrl()); | ||
return flutterReleasesFromMap(response.body); | ||
} on Exception { | ||
throw ExceptionCouldNotFetchReleases(); | ||
} | ||
} | ||
|
||
Map<String, dynamic> filterCurrentReleases(Map<String, dynamic> json) { | ||
final currentRelease = json['current_release'] as Map<String, dynamic>; | ||
final releases = json['releases'] as List<dynamic>; | ||
// Hashes of current releases | ||
final hashMap = currentRelease.map((key, value) => MapEntry(value, key)); | ||
|
||
// Filter out channel/currentRelease versions | ||
releases.forEach((r) { | ||
// Check if release hash is in hashmap | ||
final channel = hashMap[r['hash']]; | ||
if (channel != null) { | ||
currentRelease[channel] = r['version']; | ||
} | ||
}); | ||
|
||
return currentRelease; | ||
} | ||
|
||
FlutterReleases flutterReleasesFromMap(String str) => | ||
FlutterReleases.fromMap(jsonDecode(str) as Map<String, dynamic>); | ||
|
||
String flutterReleasesToMap(FlutterReleases data) => json.encode(data.toMap()); | ||
|
||
class FlutterReleases { | ||
FlutterReleases({ | ||
this.baseUrl, | ||
this.currentRelease, | ||
this.releases, | ||
}); | ||
|
||
final String baseUrl; | ||
final CurrentRelease currentRelease; | ||
final List<Release> releases; | ||
|
||
factory FlutterReleases.fromMap(Map<String, dynamic> json) { | ||
final currentRelease = filterCurrentReleases(json); | ||
return FlutterReleases( | ||
baseUrl: json['base_url'] as String, | ||
currentRelease: CurrentRelease.fromMap(currentRelease), | ||
releases: List<Release>.from(json['releases'] | ||
.map((x) => Release.fromMap(x as Map<String, dynamic>)) | ||
as Iterable<dynamic>), | ||
); | ||
} | ||
|
||
Map<String, dynamic> toMap() => { | ||
'base_url': baseUrl, | ||
'current_release': currentRelease.toMap(), | ||
'releases': List<dynamic>.from(releases.map((x) => x.toMap())), | ||
}; | ||
} | ||
|
||
class CurrentRelease { | ||
CurrentRelease({ | ||
this.beta, | ||
this.dev, | ||
this.stable, | ||
}); | ||
|
||
final String beta; | ||
final String dev; | ||
final String stable; | ||
|
||
factory CurrentRelease.fromMap(Map<String, dynamic> json) => CurrentRelease( | ||
beta: json['beta'] as String, | ||
dev: json['dev'] as String, | ||
stable: json['stable'] as String, | ||
); | ||
|
||
Map<String, dynamic> toMap() => { | ||
'beta': beta, | ||
'dev': dev, | ||
'stable': stable, | ||
}; | ||
|
||
Map<String, dynamic> toHashMap() => { | ||
'$beta': 'beta', | ||
'$dev': 'dev', | ||
'$stable': 'stable', | ||
}; | ||
} | ||
|
||
class Release { | ||
Release({ | ||
this.hash, | ||
this.channel, | ||
this.version, | ||
this.releaseDate, | ||
this.archive, | ||
this.sha256, | ||
}); | ||
|
||
final String hash; | ||
final Channel channel; | ||
final String version; | ||
final DateTime releaseDate; | ||
final String archive; | ||
final String sha256; | ||
|
||
factory Release.fromMap(Map<String, dynamic> json) => Release( | ||
hash: json['hash'] as String, | ||
channel: channelValues.map[json['channel']], | ||
version: json['version'] as String, | ||
releaseDate: DateTime.parse(json['release_date'] as String), | ||
archive: json['archive'] as String, | ||
sha256: json['sha256'] as String, | ||
); | ||
|
||
Map<String, dynamic> toMap() => { | ||
'hash': hash, | ||
'channel': channelValues.reverse[channel], | ||
'version': version, | ||
'release_date': releaseDate.toIso8601String(), | ||
'archive': archive, | ||
'sha256': sha256, | ||
}; | ||
} | ||
|
||
enum Channel { STABLE, DEV, BETA } | ||
|
||
final channelValues = EnumValues( | ||
{'beta': Channel.BETA, 'dev': Channel.DEV, 'stable': Channel.STABLE}); | ||
|
||
class EnumValues<T> { | ||
Map<String, T> map; | ||
Map<T, String> reverseMap; | ||
|
||
EnumValues(this.map); | ||
|
||
Map<T, String> get reverse { | ||
reverseMap ??= map.map((k, v) => MapEntry(v, k)); | ||
|
||
return reverseMap; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.