utils.dart 5.8 KB
Newer Older
1 2 3 4 5
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';
6
import 'dart:convert';
Devon Carew's avatar
Devon Carew committed
7
import 'dart:io';
8
import 'dart:math' show Random;
Devon Carew's avatar
Devon Carew committed
9 10

import 'package:crypto/crypto.dart';
Devon Carew's avatar
Devon Carew committed
11
import 'package:path/path.dart' as path;
Devon Carew's avatar
Devon Carew committed
12

13 14
bool get isRunningOnBot {
  // https://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables
15
  // CHROME_HEADLESS is one property set on Flutter's Chrome Infra bots.
16 17
  return
    Platform.environment['TRAVIS'] == 'true' ||
Eric Seidel's avatar
Eric Seidel committed
18
    Platform.environment['CONTINUOUS_INTEGRATION'] == 'true' ||
19
    Platform.environment['CHROME_HEADLESS'] == '1';
20 21
}

Ian Hickson's avatar
Ian Hickson committed
22 23 24 25 26 27 28
String hex(List<int> bytes) {
  StringBuffer result = new StringBuffer();
  for (int part in bytes)
    result.write('${part < 16 ? '0' : ''}${part.toRadixString(16)}');
  return result.toString();
}

Devon Carew's avatar
Devon Carew committed
29
String calculateSha(File file) {
Ian Hickson's avatar
Ian Hickson committed
30
  return hex(sha1.convert(file.readAsBytesSync()).bytes);
Devon Carew's avatar
Devon Carew committed
31
}
32

33 34 35 36 37 38 39 40 41 42 43 44
/// Convert `foo_bar` to `fooBar`.
String camelCase(String str) {
  int index = str.indexOf('_');
  while (index != -1 && index < str.length - 2) {
    str = str.substring(0, index) +
      str.substring(index + 1, index + 2).toUpperCase() +
      str.substring(index + 2);
    index = str.indexOf('_');
  }
  return str;
}

45 46 47 48 49 50
String toTitleCase(String str) {
  if (str.isEmpty)
    return str;
  return str.substring(0, 1).toUpperCase() + str.substring(1);
}

51 52 53
/// Return the plural of the given word (`cat(s)`).
String pluralize(String word, int count) => count == 1 ? word : word + 's';

54 55 56 57 58 59 60
/// Return the name of an enum item.
String getEnumName(dynamic enumItem) {
  String name = '$enumItem';
  int index = name.indexOf('.');
  return index == -1 ? name : name.substring(index + 1);
}

Devon Carew's avatar
Devon Carew committed
61 62 63 64 65 66 67 68 69 70 71 72
File getUniqueFile(Directory dir, String baseName, String ext) {
  int i = 1;

  while (true) {
    String name = '${baseName}_${i.toString().padLeft(2, '0')}.$ext';
    File file = new File(path.join(dir.path, name));
    if (!file.existsSync())
      return file;
    i++;
  }
}

73 74 75 76
String toPrettyJson(Object jsonable) {
  return new JsonEncoder.withIndent('  ').convert(jsonable) + '\n';
}

77 78 79 80 81
/// Return a String - with units - for the size in MB of the given number of bytes.
String getSizeAsMB(int bytesLength) {
  return '${(bytesLength / (1024 * 1024)).toStringAsFixed(1)}MB';
}

82 83 84 85 86 87 88 89 90
String getElapsedAsSeconds(Duration duration) {
  double seconds = duration.inMilliseconds / Duration.MILLISECONDS_PER_SECOND;
  return '${seconds.toStringAsFixed(2)} seconds';
}

String getElapsedAsMilliseconds(Duration duration) {
  return '${duration.inMilliseconds} ms';
}

91 92 93 94 95 96 97
/// Return a relative path if [fullPath] is contained by the cwd, else return an
/// absolute path.
String getDisplayPath(String fullPath) {
  String cwd = Directory.current.path + Platform.pathSeparator;
  return fullPath.startsWith(cwd) ?  fullPath.substring(cwd.length) : fullPath;
}

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
/// A class to maintain a list of items, fire events when items are added or
/// removed, and calculate a diff of changes when a new list of items is
/// available.
class ItemListNotifier<T> {
  ItemListNotifier() {
    _items = new Set<T>();
  }

  ItemListNotifier.from(List<T> items) {
    _items = new Set<T>.from(items);
  }

  Set<T> _items;

  StreamController<T> _addedController = new StreamController<T>.broadcast();
  StreamController<T> _removedController = new StreamController<T>.broadcast();

  Stream<T> get onAdded => _addedController.stream;
  Stream<T> get onRemoved => _removedController.stream;

  List<T> get items => _items.toList();

  void updateWithNewList(List<T> updatedList) {
    Set<T> updatedSet = new Set<T>.from(updatedList);

    Set<T> addedItems = updatedSet.difference(_items);
    Set<T> removedItems = _items.difference(updatedSet);

    _items = updatedSet;

    for (T item in addedItems)
      _addedController.add(item);
    for (T item in removedItems)
      _removedController.add(item);
  }

  /// Close the streams.
  void dispose() {
    _addedController.close();
    _removedController.close();
  }
}
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164

class SettingsFile {
  SettingsFile.parse(String contents) {
    for (String line in contents.split('\n')) {
      line = line.trim();
      if (line.startsWith('#') || line.isEmpty)
        continue;
      int index = line.indexOf('=');
      if (index != -1)
        values[line.substring(0, index)] = line.substring(index + 1);
    }
  }

  factory SettingsFile.parseFromFile(File file) {
    return new SettingsFile.parse(file.readAsStringSync());
  }

  final Map<String, String> values = <String, String>{};

  void writeContents(File file) {
    file.writeAsStringSync(values.keys.map((String key) {
      return '$key=${values[key]}';
    }).join('\n'));
  }
}
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198

/// A UUID generator. This will generate unique IDs in the format:
///
///     f47ac10b-58cc-4372-a567-0e02b2c3d479
///
/// The generated uuids are 128 bit numbers encoded in a specific string format.
///
/// For more information, see
/// http://en.wikipedia.org/wiki/Universally_unique_identifier.
class Uuid {
  Random _random = new Random();

  /// Generate a version 4 (random) uuid. This is a uuid scheme that only uses
  /// random numbers as the source of the generated uuid.
  String generateV4() {
    // Generate xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx / 8-4-4-4-12.
    int special = 8 + _random.nextInt(4);

    return
      '${_bitsDigits(16, 4)}${_bitsDigits(16, 4)}-'
          '${_bitsDigits(16, 4)}-'
          '4${_bitsDigits(12, 3)}-'
          '${_printDigits(special,  1)}${_bitsDigits(12, 3)}-'
          '${_bitsDigits(16, 4)}${_bitsDigits(16, 4)}${_bitsDigits(16, 4)}';
  }

  String _bitsDigits(int bitCount, int digitCount) =>
      _printDigits(_generateBits(bitCount), digitCount);

  int _generateBits(int bitCount) => _random.nextInt(1 << bitCount);

  String _printDigits(int value, int count) =>
      value.toRadixString(16).padLeft(count, '0');
}