isolate_current_directory 2.1.0 copy "isolate_current_directory: ^2.1.0" to clipboard
isolate_current_directory: ^2.1.0 copied to clipboard

Support for isolated Directory.current. Use the `withCurrentDirectory` function to change the Dart current directory within a scope without affecting the global one.

isolate_current_directory #

GitHub Actions pub package

This library exports a single function, withCurrentDirectory, which can change Directory.current (the working directory) within the scope of a lambda, but not the global value.

That means that using this function, it's possible to write concurrent Dart code that executes in different working directories without different computations affecting each other.

Using this library #

To add a dependency on your pubspec:

dart pub add isolate_current_directory

Now, you can use withCurrentDirectory:

withCurrentDirectory('my-dir', () async {
  // this file resolves to my-dir/example.txt
  final file = File('example.txt');
  // use the file!
});

See isolate_current_directory_example.dart for a complete example.

Motivation #

Dart's Directory.current is a global variable that can be changed at any time by any Dart code.

In asynchronous code, you could use a lock (see the synchronized package) to try to avoid modifying the working directory while other async code is running, but that is impossible to guarantee as any code that ignores the lock could still concurrently modify the working directory.

This problem is even more vexing in the presence of Isolates because if any code in any Isolate changes the working directory, then all other Isolates will see that but have no way that I know of to synchronize access to Directory.current, because Isolates are supposed to be, well, isolated from each other so they cannot share the same lock!

By using IOOverrides, this library leverages Dart Zones to isolate Directory.current to the scope of a function. No matter how many functions are running concurrently, even across many Isolates, each function has its own working directory. It can change its own working directory without affecting any other code running in a different scope.

Caveats #

Process #

Unfortunately, methods from Process do not honour the scoped Directory.current value by default.

For this reason, when using Process, you must pass in the workingDirectory argument explicitly:

Process.start('cmd', const ['args'], workingDirectory: Directory.current.path);

Isolates #

When starting a new Isolate, unfortunately, the new Isolate will not inherit the scoped current directory of the calling code.

To work around that, wrap Isolate functions as follows:

// BEFORE
Isolate.run(myIsolateFunction);

// AFTER
// capture the working directory in this Isolate
final workingDir = Directory.current.path;
// in the new Isolate, use withCurrentDirectory
Isolate.run(() => withCurrentDirectory(workingDir, myIsolateFunction));  

Performance #

Another possible issue is performance. When a FileSystemEntity is created within the scope of withCurrentDirectory, a custom implementation of the dart:io type (File, Directory, Link) is created which will check at each operation what's the scoped value of Directory.current, which may have a non-negligible cost if this happens in the hot path of an application.

Links mostly work, but mysteriously, exists() doesn't seem to.

See link_test.dart.

1
likes
160
pub points
25%
popularity

Publisher

unverified uploader

Support for isolated Directory.current. Use the `withCurrentDirectory` function to change the Dart current directory within a scope without affecting the global one.

Repository (GitHub)
View/report issues

Documentation

API reference

License

Apache-2.0 (license)

Dependencies

path

More

Packages that depend on isolate_current_directory