mirror of
https://github.com/flutter/packages.git
synced 2025-06-29 22:33:11 +08:00
[xdg_directories] Remove process
dependency (#4460)
Replaces the `process` dependency with direct use of `io.Process`, to reduce external dependencies, since this is a `path_provider` dependency and thus a core package. Fixes https://github.com/flutter/flutter/issues/129787
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
## NEXT
|
||||
## 1.0.1
|
||||
|
||||
* Removes `process` dependency.
|
||||
* Updates minimum supported SDK version to Flutter 3.3/Dart 2.18.
|
||||
|
||||
## 1.0.0
|
||||
|
@ -9,7 +9,9 @@ import 'dart:io';
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:process/process.dart';
|
||||
|
||||
// From errno definitions.
|
||||
const int _noSuchFileError = 2;
|
||||
|
||||
/// An override function used by the tests to override the environment variable
|
||||
/// lookups using [xdgEnvironmentOverride].
|
||||
@ -36,16 +38,44 @@ EnvironmentAccessor? _xdgEnvironmentOverride;
|
||||
EnvironmentAccessor _getenv = _productionGetEnv;
|
||||
String? _productionGetEnv(String value) => Platform.environment[value];
|
||||
|
||||
/// A testing function that replaces the process manager used to run xdg-user-path
|
||||
/// with the one supplied.
|
||||
/// A wrapper around Process.runSync to allow injection of a fake in tests.
|
||||
@visibleForTesting
|
||||
abstract class XdgProcessRunner {
|
||||
/// Runs the given command synchronously.
|
||||
ProcessResult runSync(
|
||||
String executable,
|
||||
List<String> arguments, {
|
||||
Encoding? stdoutEncoding = systemEncoding,
|
||||
Encoding? stderrEncoding = systemEncoding,
|
||||
});
|
||||
}
|
||||
|
||||
class _DefaultProcessRunner implements XdgProcessRunner {
|
||||
const _DefaultProcessRunner();
|
||||
|
||||
@override
|
||||
ProcessResult runSync(String executable, List<String> arguments,
|
||||
{Encoding? stdoutEncoding = systemEncoding,
|
||||
Encoding? stderrEncoding = systemEncoding}) {
|
||||
return Process.runSync(
|
||||
executable,
|
||||
arguments,
|
||||
stdoutEncoding: stdoutEncoding,
|
||||
stderrEncoding: stderrEncoding,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// A testing function that replaces the process runner used to run
|
||||
/// xdg-user-path with the one supplied.
|
||||
///
|
||||
/// Only available to tests.
|
||||
@visibleForTesting
|
||||
set xdgProcessManager(ProcessManager processManager) {
|
||||
_processManager = processManager;
|
||||
set xdgProcessRunner(XdgProcessRunner processRunner) {
|
||||
_processRunner = processRunner;
|
||||
}
|
||||
|
||||
ProcessManager _processManager = const LocalProcessManager();
|
||||
XdgProcessRunner _processRunner = const _DefaultProcessRunner();
|
||||
|
||||
List<Directory> _directoryListFromEnvironment(
|
||||
String envVar, List<Directory> fallback) {
|
||||
@ -152,13 +182,20 @@ Directory? get runtimeDir => _directoryFromEnvironment('XDG_RUNTIME_DIR');
|
||||
///
|
||||
/// If the `xdg-user-dir` executable is not present this returns null.
|
||||
Directory? getUserDirectory(String dirName) {
|
||||
if (!_processManager.canRun('xdg-user-dir')) {
|
||||
return null;
|
||||
final ProcessResult result;
|
||||
try {
|
||||
result = _processRunner.runSync(
|
||||
'xdg-user-dir',
|
||||
<String>[dirName],
|
||||
stdoutEncoding: utf8,
|
||||
);
|
||||
} on ProcessException catch (e) {
|
||||
// Silently return null if it's missing, otherwise pass the exception up.
|
||||
if (e.errorCode == _noSuchFileError) {
|
||||
return null;
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
final ProcessResult result = _processManager.runSync(
|
||||
<String>['xdg-user-dir', dirName],
|
||||
stdoutEncoding: utf8,
|
||||
);
|
||||
final String path = (result.stdout as String).split('\n')[0];
|
||||
return Directory(path);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ name: xdg_directories
|
||||
description: A Dart package for reading XDG directory configuration information on Linux.
|
||||
repository: https://github.com/flutter/packages/tree/main/packages/xdg_directories
|
||||
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+xdg_directories%22
|
||||
version: 1.0.0
|
||||
version: 1.0.1
|
||||
|
||||
environment:
|
||||
sdk: ">=2.18.0 <4.0.0"
|
||||
@ -13,7 +13,6 @@ platforms:
|
||||
dependencies:
|
||||
meta: ^1.3.0
|
||||
path: ^1.8.0
|
||||
process: ^4.0.0
|
||||
|
||||
dev_dependencies:
|
||||
test: ^1.16.0
|
||||
|
@ -6,7 +6,6 @@ import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:process/process.dart';
|
||||
import 'package:test/fake.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:xdg_directories/xdg_directories.dart' as xdg;
|
||||
@ -27,6 +26,8 @@ void main() {
|
||||
String testPath(String subdir) => path.join(testRootPath(), subdir);
|
||||
|
||||
setUp(() {
|
||||
xdg.xdgProcessRunner =
|
||||
FakeProcessRunner(<String, String>{}, canRunExecutable: false);
|
||||
tmpDir = Directory.systemTemp.createTempSync('xdg_test');
|
||||
fakeEnv.clear();
|
||||
fakeEnv['HOME'] = testRootPath();
|
||||
@ -103,24 +104,22 @@ XDG_VIDEOS_DIR="$HOME/Videos"
|
||||
'TEMPLATES': testPath('Templates'),
|
||||
'VIDEOS': testPath('Videos'),
|
||||
};
|
||||
xdg.xdgProcessManager = FakeProcessManager(expected);
|
||||
xdg.xdgProcessRunner = FakeProcessRunner(expected);
|
||||
final Set<String> userDirs = xdg.getUserDirectoryNames();
|
||||
expect(userDirs, equals(expected.keys.toSet()));
|
||||
for (final String key in userDirs) {
|
||||
expect(xdg.getUserDirectory(key)!.path, equals(expected[key]),
|
||||
reason: 'Path $key value not correct');
|
||||
}
|
||||
xdg.xdgProcessManager = const LocalProcessManager();
|
||||
});
|
||||
|
||||
test('Returns null when xdg-user-dir executable is not present', () {
|
||||
xdg.xdgProcessManager = FakeProcessManager(
|
||||
xdg.xdgProcessRunner = FakeProcessRunner(
|
||||
<String, String>{},
|
||||
canRunExecutable: false,
|
||||
);
|
||||
expect(xdg.getUserDirectory('DESKTOP'), isNull,
|
||||
reason: 'Found xdg user directory without access to xdg-user-dir');
|
||||
xdg.xdgProcessManager = const LocalProcessManager();
|
||||
});
|
||||
|
||||
test('Throws StateError when HOME not set', () {
|
||||
@ -131,27 +130,22 @@ XDG_VIDEOS_DIR="$HOME/Videos"
|
||||
});
|
||||
}
|
||||
|
||||
class FakeProcessManager extends Fake implements ProcessManager {
|
||||
FakeProcessManager(this.expected, {this.canRunExecutable = true});
|
||||
class FakeProcessRunner extends Fake implements xdg.XdgProcessRunner {
|
||||
FakeProcessRunner(this.expected, {this.canRunExecutable = true});
|
||||
|
||||
Map<String, String> expected;
|
||||
final bool canRunExecutable;
|
||||
|
||||
@override
|
||||
ProcessResult runSync(
|
||||
List<dynamic> command, {
|
||||
String? workingDirectory,
|
||||
Map<String, String>? environment,
|
||||
bool includeParentEnvironment = true,
|
||||
bool runInShell = false,
|
||||
Encoding stdoutEncoding = systemEncoding,
|
||||
Encoding stderrEncoding = systemEncoding,
|
||||
String executable,
|
||||
List<String> arguments, {
|
||||
Encoding? stdoutEncoding = systemEncoding,
|
||||
Encoding? stderrEncoding = systemEncoding,
|
||||
}) {
|
||||
return ProcessResult(0, 0, expected[command[1]], '');
|
||||
}
|
||||
|
||||
@override
|
||||
bool canRun(dynamic executable, {String? workingDirectory}) {
|
||||
return canRunExecutable;
|
||||
if (!canRunExecutable) {
|
||||
throw ProcessException(executable, arguments, 'No such executable', 2);
|
||||
}
|
||||
return ProcessResult(0, 0, expected[arguments.first], '');
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user