diff --git a/source/dub/dub.d b/source/dub/dub.d index ec8e83f..ebb50da 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -519,7 +519,7 @@ /// Loads a specific package as the main project package (can be a sub package) void loadPackage(Package pack) { - auto selections = Project.loadSelections(pack); + auto selections = Project.loadSelections(pack, m_packageManager); m_project = new Project(m_packageManager, pack, selections); } diff --git a/source/dub/internal/configy/Read.d b/source/dub/internal/configy/Read.d index 71f877f..cb07be2 100644 --- a/source/dub/internal/configy/Read.d +++ b/source/dub/internal/configy/Read.d @@ -296,11 +296,14 @@ /// Ditto public Nullable!T parseConfigFileSimple (T) (in CLIArgs args, StrictMode strict = StrictMode.Error) { + return wrapException(parseConfigFile!T(args, strict)); +} + +/// Ditto +public Nullable!T wrapException (T) (lazy T parseCall) +{ try - { - Node root = Loader.fromFile(args.config_path).load(); - return nullable(parseConfig!T(args, root, strict)); - } + return nullable(parseCall); catch (ConfigException exc) { exc.printException(); diff --git a/source/dub/packagemanager.d b/source/dub/packagemanager.d index 3b071b8..d9fd001 100644 --- a/source/dub/packagemanager.d +++ b/source/dub/packagemanager.d @@ -30,6 +30,7 @@ import std.exception; import std.range; import std.string; +import std.typecons; import std.zip; @@ -1109,6 +1110,41 @@ } /** + * Loads the selections file (`dub.selections.json`) + * + * The selections file is only used for the root package / project. + * However, due to it being a filesystem interaction, it is managed + * from the `PackageManager`. + * + * Under normal conditions, either `null` is returned (if no selection + * file exists or parsing encountered an error), or a `SelectionFile` + * is returned. Note that the returned `SelectionsFile` might use an + * unsupported version (see `SelectionsFile` documentation). + * + * Note that this is currently not part of the public API, and won't be + * until there is a clear need for it. + * + * Params: + * project = The `Package` for which to load a selection file. + * + * Returns: + * The parsed `SelectionsFile`, or a null instance if none exists. + */ + package final Nullable!SelectionsFile readSelections(in Package project) { + import dub.internal.configy.Read; + + const path = (project.path ~ "dub.selections.json"); + if (!this.existsFile(path)) + return typeof(return).init; + const content = this.readText(path); + // TODO: Remove `StrictMode.Warn` after v1.40 release + // The default is to error, but as the previous parser wasn't + // complaining, we should first warn the user. + return wrapException(parseConfigString!SelectionsFile( + content, path.toNativeString(), StrictMode.Warn)); + } + + /** * Writes the selections file (`dub.selections.json`) * * The selections file is only used for the root package / project. diff --git a/source/dub/project.d b/source/dub/project.d index 1a7016b..d733f35 100644 --- a/source/dub/project.d +++ b/source/dub/project.d @@ -76,7 +76,7 @@ /// Ditto this(PackageManager package_manager, Package pack) { - auto selections = Project.loadSelections(pack); + auto selections = Project.loadSelections(pack, package_manager); this(package_manager, pack, selections); } @@ -103,31 +103,22 @@ * Returns: * Always a non-null instance. */ - static package SelectedVersions loadSelections(in Package pack) + static package SelectedVersions loadSelections(in Package pack, PackageManager mgr) { import dub.version_; import dub.internal.dyaml.stdsumtype; - auto selverfile = (pack.path ~ SelectedVersions.defaultFile).toNativeString(); - - // No file exists - if (!existsFile(selverfile)) - return new SelectedVersions(); - - // TODO: Remove `StrictMode.Warn` after v1.40 release - // The default is to error, but as the previous parser wasn't - // complaining, we should first warn the user. - auto selected = parseConfigFileSimple!SelectionsFile(selverfile, StrictMode.Warn); - - // Parsing error, it will be displayed to the user + auto selected = mgr.readSelections(pack); + // Parsing error that will be displayed to the user or just no selections if (selected.isNull()) return new SelectedVersions(); return selected.get().content.match!( (Selections!0 s) { logWarnTag("Unsupported version", - "File %s has fileVersion %s, which is not yet supported by DUB %s.", - selverfile, s.fileVersion, dubVersion); + "File %s/dub.selections.json has fileVersion %s, which " ~ + "is not yet supported by DUB %s.", + pack.path, s.fileVersion, dubVersion); logWarn("Ignoring selections file. Use a newer DUB version " ~ "and set the appropriate toolchainRequirements in your recipe file"); return new SelectedVersions(); diff --git a/source/dub/test/base.d b/source/dub/test/base.d index d61dc66..a17587f 100644 --- a/source/dub/test/base.d +++ b/source/dub/test/base.d @@ -282,16 +282,6 @@ return new MockPackageSupplier(url); } - /// Loads a specific package as the main project package (can be a sub package) - public override void loadPackage(Package pack) - { - auto selections = this.packageManager.loadSelections(pack); - m_project = new Project(m_packageManager, pack, selections); - } - - /// Reintroduce parent overloads - public alias loadPackage = Dub.loadPackage; - /** * Returns a fully typed `TestPackageManager` * @@ -347,43 +337,6 @@ super(local, user, system, false); } - /// Port of `Project.loadSelections` - SelectedVersions loadSelections(in Package pack) - { - import dub.version_; - import dub.internal.configy.Read; - import dub.internal.dyaml.stdsumtype; - - auto selverfile = (pack.path ~ SelectedVersions.defaultFile); - // No file exists - if (!this.fs.existsFile(selverfile)) - return new SelectedVersions(); - - SelectionsFile selected; - try - { - const content = this.fs.readText(selverfile); - selected = parseConfigString!SelectionsFile( - content, selverfile.toNativeString()); - } - catch (Exception exc) { - logError("Error loading %s: %s", selverfile, exc.message()); - return new SelectedVersions(); - } - - return selected.content.match!( - (Selections!0 s) { - logWarnTag("Unsupported version", - "File %s has fileVersion %s, which is not yet supported by DUB %s.", - selverfile, s.fileVersion, dubVersion); - logWarn("Ignoring selections file. Use a newer DUB version " ~ - "and set the appropriate toolchainRequirements in your recipe file"); - return new SelectedVersions(); - }, - (Selections!1 s) => new SelectedVersions(s), - ); - } - /** * Re-Implementation of `gitClone`. *