in lib/src/global_packages.dart [699:819]
String? _createBinStub(
Package package,
String executable,
String script, {
required bool overwrite,
required String snapshot,
}) {
var binStubPath = p.join(_binStubDir, executable);
if (Platform.isWindows) binStubPath += '.bat';
// See if the binstub already exists. If so, it's for another package
// since we already deleted all of this package's binstubs.
String? previousPackage;
if (fileExists(binStubPath)) {
var contents = readTextFile(binStubPath);
previousPackage = _binStubProperty(contents, 'Package');
if (previousPackage == null) {
log.fine('Could not parse binstub $binStubPath:\n$contents');
} else if (!overwrite) {
return previousPackage;
}
}
// If the script was built to a snapshot, just try to invoke that
// directly and skip pub global run entirely.
String invocation;
late String binstub;
if (Platform.isWindows) {
if (fileExists(snapshot)) {
// We expect absolute paths from the precompiler since relative ones
// won't be relative to the right directory when the user runs this.
assert(p.isAbsolute(snapshot));
invocation = '''
if exist "$snapshot" (
call dart "$snapshot" %*
rem The VM exits with code 253 if the snapshot version is out-of-date.
rem If it is, we need to delete it and run "pub global" manually.
if not errorlevel 253 (
goto error
)
dart pub global run ${package.name}:$script %*
) else (
dart pub global run ${package.name}:$script %*
)
goto eof
:error
exit /b %errorlevel%
:eof
''';
} else {
invocation = 'dart pub global run ${package.name}:$script %*';
}
binstub = '''
@echo off
rem This file was created by pub v${sdk.version}.
rem Package: ${package.name}
rem Version: ${package.version}
rem Executable: $executable
rem Script: $script
$invocation
''';
} else {
if (fileExists(snapshot)) {
// We expect absolute paths from the precompiler since relative ones
// won't be relative to the right directory when the user runs this.
assert(p.isAbsolute(snapshot));
invocation = '''
if [ -f $snapshot ]; then
dart "$snapshot" "\$@"
# The VM exits with code 253 if the snapshot version is out-of-date.
# If it is, we need to delete it and run "pub global" manually.
exit_code=\$?
if [ \$exit_code != 253 ]; then
exit \$exit_code
fi
dart pub global run ${package.name}:$script "\$@"
else
dart pub global run ${package.name}:$script "\$@"
fi
''';
} else {
invocation = 'dart pub global run ${package.name}:$script "\$@"';
}
binstub = '''
#!/usr/bin/env sh
# This file was created by pub v${sdk.version}.
# Package: ${package.name}
# Version: ${package.version}
# Executable: $executable
# Script: $script
$invocation
''';
}
// Write the binstub to a temporary location, make it executable and move
// it into place afterwards to avoid races.
final tempDir = cache.createTempDir();
try {
final tmpPath = p.join(tempDir, binStubPath);
// Write this as the system encoding since the system is going to
// execute it and it might contain non-ASCII characters in the
// pathnames.
writeTextFile(tmpPath, binstub, encoding: const SystemEncoding());
if (Platform.isLinux || Platform.isMacOS) {
// Make it executable.
var result = Process.runSync('chmod', ['+x', tmpPath]);
if (result.exitCode != 0) {
// Couldn't make it executable so don't leave it laying around.
fail('Could not make "$tmpPath" executable (exit code '
'${result.exitCode}):\n${result.stderr}');
}
}
File(tmpPath).renameSync(binStubPath);
} finally {
deleteEntry(tempDir);
}
return previousPackage;
}