Future loadGistFromRepo()

in lib/sharing/gists.dart [276:354]


  Future<Gist> loadGistFromRepo({
    required String owner,
    required String repo,
    required String path,
    String? ref,
  }) async {
    // Download and parse the exercise's `dartpad_metadata.json` file.
    final metadataUrl =
        _buildContentsUrl(owner, repo, '$path/$_metadataFilename', ref);
    final metadataResponse = await _client.get(metadataUrl);

    if (metadataResponse.statusCode == 404) {
      throw GistLoaderException(GistLoaderFailureType.contentNotFound);
    } else if (metadataResponse.statusCode == 403) {
      throw GistLoaderException(GistLoaderFailureType.rateLimitExceeded);
    } else if (metadataResponse.statusCode != 200) {
      throw GistLoaderException(GistLoaderFailureType.unknown);
    }

    final metadataContent = extractGitHubResponseBody(metadataResponse.body);

    final ExerciseMetadata metadata;

    try {
      final yamlMap = yaml.loadYaml(metadataContent);

      if (yamlMap is! Map) {
        throw FormatException();
      }

      metadata = ExerciseMetadata.fromMap(yamlMap);
    } on MetadataException catch (ex) {
      throw GistLoaderException(GistLoaderFailureType.invalidExerciseMetadata,
          'Issue parsing metadata: $ex');
    } on FormatException catch (ex) {
      throw GistLoaderException(GistLoaderFailureType.invalidExerciseMetadata,
          'Issue parsing metadata: $ex');
    }

    // Make additional requests for the files listed in the metadata.
    final requests = metadata.files.map((file) async {
      final contentUrl =
          _buildContentsUrl(owner, repo, '$path/${file.path}', ref);
      final contentResponse = await _client.get(contentUrl);

      if (contentResponse.statusCode == 404) {
        // Blame the metadata for listing an invalid file.
        throw GistLoaderException(
            GistLoaderFailureType.invalidExerciseMetadata);
      } else if (metadataResponse.statusCode == 403) {
        throw GistLoaderException(GistLoaderFailureType.rateLimitExceeded);
      } else if (metadataResponse.statusCode != 200) {
        throw GistLoaderException(GistLoaderFailureType.unknown);
      }

      return extractGitHubResponseBody(contentResponse.body);
    });

    // This will rethrow the first exception created above, if one is thrown.
    final responses = await Future.wait(requests, eagerError: true);

    // Responses should be in the order they're listed in the metadata.
    final gistFiles = <GistFile>[
      for (var i = 0; i < metadata.files.length; i++)
        GistFile(
          name: metadata.files[i].name,
          content: responses[i],
        )
    ];

    final gist = Gist(
      files: gistFiles,
      description: metadata.name,
    );

    afterLoadHook?.call(gist);

    return gist;
  }