| // Copyright 2014 The Flutter 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 'base/io.dart'; | |
| import 'base/platform.dart'; | |
| import 'base/process.dart'; | |
| import 'convert.dart'; | |
| /// Wrapper around the command-line `git` executable on the host. | |
| interface class Git { | |
| /// Creates a wrapper that executes `git` using [runProcessWith]. | |
| Git({ | |
| required Platform currentPlatform, | |
| required ProcessUtils runProcessWith, | |
| String executable = 'git', | |
| }) : _platform = currentPlatform, | |
| _processUtils = runProcessWith, | |
| _pathToGitExecutable = executable; | |
| final String _pathToGitExecutable; | |
| final Platform _platform; | |
| final ProcessUtils _processUtils; | |
| /// Returns the result of `git log <arguments>`. | |
| /// | |
| /// Automatically injects the arguments `-c log.showSignature=false` in order | |
| /// to ignore user settings that will break the expected output for this call; | |
| /// otherwise this call is identical to using [Git.runSync] directly. | |
| RunResult logSync( | |
| List<String> arguments, { | |
| String? workingDirectory, | |
| Map<String, String>? environment, | |
| }) { | |
| assert(arguments.isEmpty || arguments.first != 'log'); | |
| return runSync( | |
| [..._ignoreLogShowSignature, 'log', ...arguments], | |
| workingDirectory: workingDirectory, | |
| environment: environment, | |
| ); | |
| } | |
| static const _ignoreLogShowSignature = ['-c', 'log.showSignature=false']; | |
| /// Environment variables that can interfere with git commands when targeting | |
| /// the Flutter SDK. | |
| static const Set<String> _kGitEnvironmentVariables = <String>{ | |
| 'GIT_DIR', | |
| 'GIT_INDEX_FILE', | |
| 'GIT_WORK_TREE', | |
| 'GIT_OBJECT_DIRECTORY', | |
| 'GIT_ALTERNATE_OBJECT_DIRECTORIES', | |
| 'GIT_QUARANTINE_PATH', | |
| 'GIT_COMMON_DIR', | |
| }; | |
| Map<String, String> _filterEnvironment(Map<String, String>? environment) { | |
| final result = Map<String, String>.from(environment ?? _platform.environment); | |
| result.removeWhere( | |
| // Doing toUpperCase because windows environment vars are case-insensitive | |
| (String key, String value) => _kGitEnvironmentVariables.contains(key.toUpperCase()), | |
| ); | |
| if (_platform.isWindows) { | |
| result.addAll(_useNoGlobCygwinGit); | |
| } | |
| return result; | |
| } | |
| /// Spawns a child process to run `git`. | |
| /// | |
| /// The arguments are the same as [ProcessUtils.run], except: | |
| /// | |
| /// - [arguments] does _not_ include the executable (it is implicit); | |
| /// - [environment] may include additional (implicit) platform-specific variables | |
| Future<RunResult> run( | |
| List<String> arguments, { | |
| bool throwOnError = false, | |
| RunResultChecker? allowedFailures, | |
| String? workingDirectory, | |
| bool allowReentrantFlutter = false, | |
| Map<String, String>? environment, | |
| Duration? timeout, | |
| int timeoutRetries = 0, | |
| }) { | |
| return _processUtils.run( | |
| [_pathToGitExecutable, ...arguments], | |
| throwOnError: throwOnError, | |
| allowedFailures: allowedFailures, | |
| workingDirectory: workingDirectory, | |
| allowReentrantFlutter: allowReentrantFlutter, | |
| environment: _filterEnvironment(environment), | |
| timeout: timeout, | |
| timeoutRetries: timeoutRetries, | |
| ); | |
| } | |
| /// Runs a command using `git` and blocks waiting for its result. | |
| /// | |
| /// The arguments are the same as [ProcessUtils.runSync], except: | |
| /// | |
| /// - [arguments] does _not_ include the executable (it is implicit); | |
| /// - [environment] may include additional (implicit) platform-specific variables | |
| RunResult runSync( | |
| List<String> arguments, { | |
| bool throwOnError = false, | |
| bool verboseExceptions = false, | |
| RunResultChecker? allowedFailures, | |
| bool hideStdout = false, | |
| String? workingDirectory, | |
| Map<String, String>? environment, | |
| bool allowReentrantFlutter = false, | |
| Encoding encoding = systemEncoding, | |
| }) { | |
| return _processUtils.runSync( | |
| [_pathToGitExecutable, ...arguments], | |
| throwOnError: throwOnError, | |
| verboseExceptions: verboseExceptions, | |
| allowedFailures: allowedFailures, | |
| hideStdout: hideStdout, | |
| workingDirectory: workingDirectory, | |
| environment: _filterEnvironment(environment), | |
| allowReentrantFlutter: allowReentrantFlutter, | |
| encoding: encoding, | |
| ); | |
| } | |
| /// Spawns a child process to run `git` and streams the result to stdout/err. | |
| /// | |
| /// The arguments are the same as [ProcessUtils.stream], except: | |
| /// | |
| /// - [arguments] does _not_ include the executable (it is implicit); | |
| /// - [environment] may include additional (implicit) platform-specific variables | |
| Future<int> stream( | |
| List<String> arguments, { | |
| String? workingDirectory, | |
| bool allowReentrantFlutter = false, | |
| String prefix = '', | |
| bool trace = false, | |
| RegExp? filter, | |
| RegExp? stdoutErrorMatcher, | |
| StringConverter? mapFunction, | |
| Map<String, String>? environment, | |
| }) { | |
| assert(arguments.isEmpty || arguments.first != 'git'); | |
| return _processUtils.stream( | |
| [_pathToGitExecutable, ...arguments], | |
| workingDirectory: workingDirectory, | |
| allowReentrantFlutter: allowReentrantFlutter, | |
| prefix: prefix, | |
| trace: trace, | |
| filter: filter, | |
| stdoutErrorMatcher: stdoutErrorMatcher, | |
| mapFunction: mapFunction, | |
| environment: _filterEnvironment(environment), | |
| ); | |
| } | |
| static const _useNoGlobCygwinGit = {'MSYS': 'noglob', 'CYGWIN': 'noglob'}; | |
| } |