// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. /// Utilities to locate the Dart SDK. library; import 'dart:async'; import 'dart:io'; import 'package:path/path.dart' as path; /// The path to the current Dart SDK. String get sdkPath => path.dirname(path.dirname(Platform.resolvedExecutable)); /// Returns the path to the current Dart SDK. @Deprecated("Use 'sdkPath' instead") String getSdkPath() => sdkPath; /// The user-specific application configuration folder for the current platform. /// /// This is a location appropriate for storing application specific /// configuration for the current user. The [productName] should be unique to /// avoid clashes with other applications on the same machine. This method won't /// actually create the folder, merely return the recommended location for /// storing user-specific application configuration. /// /// The folder location depends on the platform: /// * `%APPDATA%\` on **Windows**, /// * `$HOME/Library/Application Support/` on **Mac OS**, /// * `$XDG_CONFIG_HOME/` on **Linux** /// (if `$XDG_CONFIG_HOME` is defined), and, /// * `$HOME/.config/` otherwise. /// /// The chosen location aims to follow best practices for each platform, /// honoring the [XDG Base Directory Specification][1] on Linux and /// [File System Basics][2] on Mac OS. /// /// Throws an [EnvironmentNotFoundException] if an environment entry, /// `%APPDATA%` or `$HOME`, is needed and not available. /// /// [1]: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html /// [2]: https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html#//apple_ref/doc/uid/TP40010672-CH2-SW1 String applicationConfigHome(String productName) => path.join(_configHome, productName); String get _configHome { if (Platform.isWindows) { return _requireEnv('APPDATA'); } if (Platform.isMacOS) { return path.join(_requireEnv('HOME'), 'Library', 'Application Support'); } if (Platform.isLinux) { final xdgConfigHome = _env['XDG_CONFIG_HOME']; if (xdgConfigHome != null) { return xdgConfigHome; } // XDG Base Directory Specification says to use $HOME/.config/ when // $XDG_CONFIG_HOME isn't defined. return path.join(_requireEnv('HOME'), '.config'); } // We have no guidelines, perhaps we should just do: $HOME/.config/ // same as XDG specification would specify as fallback. return path.join(_requireEnv('HOME'), '.config'); } String _requireEnv(String name) => _env[name] ?? (throw EnvironmentNotFoundException(name)); /// Exception thrown if a required environment entry does not exist. /// /// Thrown by [applicationConfigHome] if an expected and required /// platform specific environment entry is not available. class EnvironmentNotFoundException implements Exception { /// Name of environment entry which was needed, but not found. final String entryName; String get message => 'Environment variable \'$entryName\' is not defined!'; EnvironmentNotFoundException(this.entryName); @override String toString() => message; } // This zone override exists solely for testing (see lib/cli_util_test.dart). Map get _env => (Zone.current[#environmentOverrides] as Map?) ?? Platform.environment;