diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 752437b..aab0418 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -248,49 +248,6 @@ return cmd; } - - /** Get a configured dub instance. - - Returns: - A dub instance - */ - Dub prepareDub() { - Dub dub; - - if (options.bare) { - dub = new Dub(NativePath(getcwd())); - dub.rootPath = NativePath(options.root_path); - dub.defaultPlacementLocation = options.placementLocation; - - return dub; - } - - // initialize DUB - auto package_suppliers = options.registry_urls - .map!((url) { - // Allow to specify fallback mirrors as space separated urls. Undocumented as we - // should simply retry over all registries instead of using a special - // FallbackPackageSupplier. - auto urls = url.splitter(' '); - PackageSupplier ps = getRegistryPackageSupplier(urls.front); - urls.popFront; - if (!urls.empty) - ps = new FallbackPackageSupplier(ps ~ urls.map!getRegistryPackageSupplier.array); - return ps; - }) - .array; - - dub = new Dub(options.root_path, package_suppliers, options.skipRegistry); - dub.dryRun = options.annotate; - dub.defaultPlacementLocation = options.placementLocation; - - // make the CWD package available so that for example sub packages can reference their - // parent package. - try dub.packageManager.getOrLoadPackage(NativePath(options.root_path), NativePath.init, false, StrictMode.Warn); - catch (Exception e) { logDiagnostic("No valid package found in current working directory: %s", e.msg); } - - return dub; - } } /// Can get the command names @@ -532,12 +489,8 @@ return 1; } - Dub dub; - // initialize the root package - if (!cmd.skipDubInitialization) { - dub = handler.prepareDub; - } + Dub dub = cmd.prepareDub(handler.options); // execute the command try return cmd.execute(dub, remaining_args, command_args.appArgs); @@ -787,7 +740,6 @@ string[] helpText; bool acceptsAppArgs; bool hidden = false; // used for deprecated commands - bool skipDubInitialization = false; /** Parses all known command line options without executing any actions. @@ -799,6 +751,46 @@ */ abstract void prepare(scope CommandArgs args); + /** + * Initialize the dub instance used by `execute` + */ + public Dub prepareDub(CommonOptions options) { + Dub dub; + + if (options.bare) { + dub = new Dub(NativePath(options.root_path), NativePath(getcwd())); + dub.defaultPlacementLocation = options.placementLocation; + + return dub; + } + + // initialize DUB + auto package_suppliers = options.registry_urls + .map!((url) { + // Allow to specify fallback mirrors as space separated urls. Undocumented as we + // should simply retry over all registries instead of using a special + // FallbackPackageSupplier. + auto urls = url.splitter(' '); + PackageSupplier ps = getRegistryPackageSupplier(urls.front); + urls.popFront; + if (!urls.empty) + ps = new FallbackPackageSupplier(ps ~ urls.map!getRegistryPackageSupplier.array); + return ps; + }) + .array; + + dub = new Dub(options.root_path, package_suppliers, options.skipRegistry); + dub.dryRun = options.annotate; + dub.defaultPlacementLocation = options.placementLocation; + + // make the CWD package available so that for example sub packages can reference their + // parent package. + try dub.packageManager.getOrLoadPackage(NativePath(options.root_path), NativePath.init, false, StrictMode.Warn); + catch (Exception e) { logDiagnostic("No valid package found in current working directory: %s", e.msg); } + + return dub; + } + /** Executes the actual action. Note that `prepare` will be called before any call to `execute`. @@ -2377,18 +2369,23 @@ // speed up loading when in test mode if (m_testPackage.length) { - skipDubInitialization = true; m_nodeps = true; } } + /// Returns: A minimally-initialized dub instance in test mode + override Dub prepareDub(CommonOptions options) + { + if (!m_testPackage.length) + return super.prepareDub(options); + return new Dub(NativePath(options.root_path), NativePath(getcwd())); + } + override int execute(Dub dub, string[] free_args, string[] app_args) { import std.format : formattedWrite; if (m_testPackage.length) { - dub = new Dub(NativePath(getcwd())); - setupPackage(dub, m_testPackage); m_defaultConfig = dub.project.getDefaultConfiguration(this.baseSettings.platform); diff --git a/source/dub/dub.d b/source/dub/dub.d index 1a41cc3..e016025 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -183,12 +183,27 @@ loading a package. This constructor corresponds to the "--bare" option of the command line - interface. Use + interface. + + Params: + root = The root path of the Dub instance itself. + pkg_root = The root of the location where packages are located + Only packages under this location will be accessible. + Note that packages at the top levels will be ignored. */ - this(NativePath override_path) + this(NativePath root, NativePath pkg_root) { + // Note: We're doing `init()` before setting the `rootPath`, + // to prevent `init` from reading the project's settings. init(); - m_packageManager = new PackageManager(override_path); + this.m_rootPath = root; + m_packageManager = new PackageManager(pkg_root); + } + + deprecated("Use the overload that takes `(NativePath pkg_root, NativePath root)`") + this(NativePath pkg_root) + { + this(pkg_root, pkg_root); } private void init() @@ -361,6 +376,8 @@ */ @property NativePath rootPath() const { return m_rootPath; } /// ditto + deprecated("Changing the root path is deprecated as it has non-obvious pitfalls " ~ + "(e.g. settings aren't reloaded). Instantiate a new `Dub` instead") @property void rootPath(NativePath root_path) { m_rootPath = root_path; diff --git a/source/dub/packagemanager.d b/source/dub/packagemanager.d index 0b73fe9..fef7bc4 100644 --- a/source/dub/packagemanager.d +++ b/source/dub/packagemanager.d @@ -701,12 +701,28 @@ } else { if( !existsDirectory(dst_path.parentPath) ) mkdirRecurse(dst_path.parentPath.toNativeString()); + // for symlinks on posix systems, use the symlink function to + // create them. Windows default unzip doesn't handle symlinks, + // so we don't need to worry about it for Windows. + version(Posix) { + import core.sys.posix.sys.stat; + if( S_ISLNK(cast(mode_t)a.fileAttributes) ){ + import core.sys.posix.unistd; + // need to convert name and target to zero-terminated string + auto target = toStringz(cast(const(char)[])archive.expand(a)); + auto dstFile = toStringz(dst_path.toNativeString()); + enforce(symlink(target, dstFile) == 0, "Error creating symlink: " ~ dst_path.toNativeString()); + goto symlink_exit; + } + } + { auto dstFile = openFile(dst_path, FileMode.createTrunc); scope(exit) dstFile.close(); dstFile.put(archive.expand(a)); } setAttributes(dst_path.toNativeString(), a); +symlink_exit: ++countFiles; } }