diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 8a83c70..342ec69 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -364,8 +364,9 @@ class InitCommand : Command { private{ - string m_buildType = "minimal"; + string m_templateType = "minimal"; PackageFormat m_format = PackageFormat.json; + bool m_nonInteractive; } this() { @@ -379,7 +380,7 @@ override void prepare(scope CommandArgs args) { - args.getopt("t|type", &m_buildType, [ + args.getopt("t|type", &m_templateType, [ "Set the type of project to generate. Available types:", "", "minimal - simple \"hello world\" project (default)", @@ -390,6 +391,7 @@ "Sets the format to use for the package description file. Possible values:", " " ~ [__traits(allMembers, PackageFormat)].map!(f => f == m_format.init.to!string ? f ~ " (default)" : f).join(", ") ]); + args.getopt("n", &m_nonInteractive, ["Don't enter interactive mode."]); } override int execute(Dub dub, string[] free_args, string[] app_args) @@ -401,18 +403,57 @@ dir = free_args[0]; free_args = free_args[1 .. $]; } + + string input(string caption, string default_value) + { + writef("%s [%s]: ", caption, default_value); + auto inp = readln(); + return inp.length > 1 ? inp[0 .. $-1] : default_value; + } + + void depCallback(ref PackageRecipe p) { + if (m_nonInteractive) return; + + auto fmt = input("Package recipe format (sdl/json)", m_format.to!string); + auto author = p.authors.join(", "); + p.name = input("Name", p.name); + p.description = input("Description", p.description); + p.authors = input("Author name", author).split(",").map!(a => a.strip).array; + p.license = input("License", p.license); + p.copyright = input("Copyright string", p.copyright); + + while (true) { + auto dep = input("Add dependency (leave empty to skip)", null); + if (!dep.length) break; + auto vers = dub.listPackageVersions(dep); + if (!vers.length) { + logError("Could not find package '%s'.", dep); + continue; + } + string vstr; + auto final_versions = vers.filter!(v => !v.isBranch && !v.isBranch).array; + if (final_versions.length) vstr = "~>" ~ final_versions[$-1].toString(); + else if (vers[$-1].isBranch) vstr = vers[$-1].toString(); + else vstr = "~>" ~ vers[$-1].toString(); + p.buildSettings.dependencies[dep] = Dependency(vstr); + logInfo("Added dependency %s %s", dep, vstr); + } + } + //TODO: Remove this block in next version // Checks if argument uses current method of specifying project type. if (free_args.length) { if (["vibe.d", "deimos", "minimal"].canFind(free_args[0])) { - m_buildType = free_args[0]; + m_templateType = free_args[0]; free_args = free_args[1 .. $]; logInfo("Deprecated use of init type. Use --type=[vibe.d | deimos | minimal] in future."); } } - dub.createEmptyPackage(Path(dir), free_args, m_buildType, m_format); + dub.createEmptyPackage(Path(dir), free_args, m_templateType, m_format, &depCallback); + + logInfo("Package sucessfully created in %s", dir.length ? dir : "."); return 0; } } diff --git a/source/dub/dub.d b/source/dub/dub.d index dd6be06..9810643 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -702,22 +702,32 @@ .filter!(t => t[1].length); } - void createEmptyPackage(Path path, string[] deps, string type, PackageFormat format = PackageFormat.sdl) + Version[] listPackageVersions(string name) + { + Version[] versions; + foreach (ps; this.m_packageSuppliers) { + try versions ~= ps.getVersions(name); + catch (Exception e) { + logDebug("Failed to get versions for package %s on provider %s: %s", name, ps.description, e.msg); + } + } + return versions.sort().uniq.array; + } + + void createEmptyPackage(Path path, string[] deps, string type, PackageFormat format = PackageFormat.sdl, scope void delegate(ref PackageRecipe) recipe_callback = null) { if (!path.absolute) path = m_rootPath ~ path; path.normalize(); - if (m_dryRun) return; string[string] depVers; string[] notFound; // keep track of any failed packages in here - foreach(ps; this.m_packageSuppliers){ - foreach(dep; deps){ - try{ - auto versionStrings = ps.getVersions(dep); - depVers[dep] = versionStrings[$-1].toString; - } catch(Exception e){ - notFound ~= dep; - } + foreach(dep; deps){ + auto vers = listPackageVersions(dep); + if (vers.length == 0) notFound ~= dep; + else { + auto v = vers[$-1]; + if (v.isBranch()) depVers[dep] = v.toString(); + else depVers[dep] = "~>" ~ v.toString(); } } if(notFound.length > 1){ @@ -727,7 +737,9 @@ throw new Exception(.format("Couldn't find package: %-(%s, %).", notFound)); } - initPackage(path, depVers, type, format); + if (m_dryRun) return; + + initPackage(path, depVers, type, format, recipe_callback); //Act smug to the user. logInfo("Successfully created an empty project in '%s'.", path.toNativeString());