diff --git a/source/dub/dub.d b/source/dub/dub.d index ad95dc3..7ca6461 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -472,21 +472,6 @@ if( !path.absolute() ) path = m_rootPath ~ path; path.normalize(); - //Check to see if a target directory needs to be created - if( !path.empty ){ - if( !existsFile(path) ) - createDirectory(path); - } - - //Make sure we do not overwrite anything accidentally - if( existsFile(path ~ PackageJsonFilename) || - existsFile(path ~ "source") || - existsFile(path ~ "views") || - existsFile(path ~ "public") ) - { - throw new Exception("The current directory is not empty.\n"); - } - if (m_dryRun) return; initPackage(path, type); diff --git a/source/dub/init.d b/source/dub/init.d index 866e721..f0f8d2e 100644 --- a/source/dub/init.d +++ b/source/dub/init.d @@ -9,9 +9,10 @@ import dub.internal.vibecompat.core.file; import dub.internal.vibecompat.core.log; -import dub.package_ : PackageJsonFilename; +import dub.package_ : packageInfoFilenames; import std.datetime; +import std.exception; import std.file; import std.format; import std.process; @@ -20,6 +21,17 @@ void initPackage(Path root_path, string type) { + //Check to see if a target directory needs to be created + if( !root_path.empty ){ + if( !existsFile(root_path) ) + createDirectory(root_path); + } + + //Make sure we do not overwrite anything accidentally + auto files = packageInfoFilenames ~ ["source/", "views/", "public/"]; + foreach (fil; files) + enforce(!existsFile(root_path ~ fil), "The target directory already contains a '"~fil~"' file. Aborting."); + switch (type) { default: throw new Exception("Unknown package init type: "~type); case "minimal": initMinimalPackage(root_path); break; @@ -77,7 +89,7 @@ version (Windows) username = environment.get("USERNAME", "Peter Parker"); else username = environment.get("USER", "Peter Parker"); - auto fil = openFile(root_path ~ PackageJsonFilename, FileMode.Append); + auto fil = openFile(root_path ~ "dub.json", FileMode.Append); scope(exit) fil.close(); fil.formattedWrite("{\n\t\"name\": \"%s\",\n", root_path.head.toString().toLower()); diff --git a/source/dub/package_.d b/source/dub/package_.d index bf57fd9..f3542ac 100644 --- a/source/dub/package_.d +++ b/source/dub/package_.d @@ -24,26 +24,48 @@ import std.string; import std.traits : EnumMembers; -enum PackageJsonFilename = "package.json"; +enum packageInfoFilenames = ["dub.json", /*"dub.sdl",*/ "package.json"]; -/// Representing a downloded / cached package, usually constructed from a json object. -/// Documentation of the package.json can be found at -/// http://registry.vibed.org/package-format +/** + Represents a package, including its sub packages + + Documentation of the package.json can be found at + http://registry.vibed.org/package-format +*/ class Package { static struct LocalPackageDef { string name; Version version_; Path path; } private { Path m_path; + Path m_infoFile; PackageInfo m_info; Package m_parentPackage; Package[] m_subPackages; Path[string] m_exportedPackages; } + static bool isPackageAt(Path path) + { + foreach (f; packageInfoFilenames) + if (existsFile(path ~ f)) + return true; + return false; + } + this(Path root, Package parent = null) { - this(jsonFromFile(root ~ PackageJsonFilename), root, parent); + Json info; + if (existsFile(root ~ "dub.json")) { + m_infoFile = root ~ "dub.json"; + info = jsonFromFile(m_infoFile); + } else if (existsFile(root ~ "package.json")) { + m_infoFile = root ~ "package.json"; + info = jsonFromFile(root ~ "package.json"); + } else { + throw new Exception("Missing package description for package in %s", root.toNativeString()); + } + this(info, root, parent); } this(Json packageInfo, Path root = Path(), Package parent = null) @@ -162,9 +184,10 @@ } @property string vers() const { return m_parentPackage ? m_parentPackage.vers : m_info.version_; } @property Version ver() const { return Version(this.vers); } + @property void ver(Version ver) { assert(m_parentPackage is null); m_info.version_ = ver.toString(); } @property ref inout(PackageInfo) info() inout { return m_info; } @property Path path() const { return m_path; } - @property Path packageInfoFile() const { return m_path ~ PackageJsonFilename; } + @property Path packageInfoFile() const { return m_infoFile; } @property const(Dependency[string]) dependencies() const { return m_info.dependencies; } @property inout(Package) basePackage() inout { return m_parentPackage ? m_parentPackage.basePackage : this; } @property inout(Package) parentPackage() inout { return m_parentPackage; } @@ -179,6 +202,15 @@ return ret.data; } + /** Overwrites the packge description file with the current information. + */ + void storeInfo() + { + auto dstFile = openFile((m_path ~ "dub.json").toString(), FileMode.CreateTrunc); + scope(exit) dstFile.close(); + dstFile.writePrettyJsonString(m_info.toJson()); + } + inout(Package) getSubPackage(string name) inout { foreach (p; m_subPackages) if (p.name == this.name ~ ":" ~ name) @@ -295,14 +327,6 @@ return s; } - /// Writes the json file back to the filesystem - void writeJson(Path path) { - auto dstFile = openFile((path~PackageJsonFilename).toString(), FileMode.CreateTrunc); - scope(exit) dstFile.close(); - dstFile.writePrettyJsonString(m_info.toJson()); - assert(false); - } - bool hasDependency(string depname, string config) const { if (depname in m_info.buildSettings.dependencies) return true; diff --git a/source/dub/packagemanager.d b/source/dub/packagemanager.d index fe6c3d5..4ac0267 100644 --- a/source/dub/packagemanager.d +++ b/source/dub/packagemanager.d @@ -225,13 +225,13 @@ // In a github zip, the actual contents are in a subfolder Path zip_prefix; - auto json_file = PathEntry(PackageJsonFilename); - foreach(ArchiveMember am; archive.directory) { + outer: foreach(ArchiveMember am; archive.directory) { auto path = Path(am.name); - if (path.length == 2 && path.head == json_file && path.length) { - zip_prefix = path[0 .. $-1]; - break; - } + foreach (fil; packageInfoFilenames) + if (path.length == 2 && path.head.toString == fil) { + zip_prefix = path[0 .. $-1]; + break outer; + } } logDebug("zip root folder: %s", zip_prefix); @@ -270,21 +270,17 @@ logDiagnostic("%s file(s) copied.", to!string(countFiles)); // overwrite package.json (this one includes a version field) - Json pi = jsonFromFile(destination~PackageJsonFilename); - pi["name"] = toLower(pi["name"].get!string()); - pi["version"] = package_info["version"]; - writeJsonFile(destination~PackageJsonFilename, pi); + auto pack = new Package(destination); + pack.info.version_ = package_info["version"].get!string; + pack.storeInfo(); // Write journal logDebug("Saving retrieval action journal..."); journal.add(Journal.Entry(Journal.Type.RegularFile, Path(JournalJsonFilename))); journal.save(destination ~ JournalJsonFilename); - if( existsFile(destination~PackageJsonFilename) ) - logInfo("%s is present with version %s", package_name, package_version); - - auto pack = new Package(destination); addPackages(m_packages, pack); + return pack; } @@ -367,19 +363,15 @@ Package addLocalPackage(in Path path, string verName, LocalPackageType type) { Package[]* packs = &m_repositories[type].localPackages; - auto info = jsonFromFile(path ~ PackageJsonFilename, false); - string name; - if( "name" !in info ) info["name"] = path.head.toString(); - if (verName.length) info["version"] = Version(verName).toString(); - // load package - auto pack = new Package(info, path); - Version ver = pack.ver; + auto pack = new Package(path); + if (verName.length) + pack.ver = Version(verName); // don't double-add packages - foreach( p; *packs ){ - if( p.path == path ){ - enforce(p.ver == ver, "Adding the same local package twice with differing versions is not allowed."); + foreach (p; *packs) { + if (p.path == path) { + enforce(p.ver == pack.ver, "Adding the same local package twice with differing versions is not allowed."); logInfo("Package is already registered: %s (version: %s)", p.name, p.ver); return p; } @@ -422,12 +414,8 @@ return p; } - auto info = jsonFromFile(path ~ PackageJsonFilename, false); - string name; - if( "name" !in info ) info["name"] = path.head.toString(); - info["version"] = ver.toString(); - - auto pack = new Package(info, path); + auto pack = new Package(path); + pack.ver = ver; addPackages(m_temporaryPackages, pack); return pack; } @@ -468,22 +456,29 @@ if (name == "*") { paths ~= path; } else { - auto ver = pentry["version"].get!string(); - auto info = Json.emptyObject; - if( existsFile(path ~ PackageJsonFilename) ) info = jsonFromFile(path ~ PackageJsonFilename); - if( "name" in info && info.name.get!string() != name ) - logWarn("Local package at %s has different name than %s (%s)", path.toNativeString(), name, info.name.get!string()); - info.name = name; - if (ver.length) info["version"] = ver; + auto ver = Version(pentry["version"].get!string()); Package pp; - if (!refresh_existing_packages) + if (!refresh_existing_packages) { foreach (p; m_repositories[type].localPackages) if (p.path == path) { pp = p; break; } - if (!pp) pp = new Package(info, path); + } + + if (!pp) { + if (Package.isPackageAt(path)) pp = new Package(path); + else { + auto info = Json.emptyObject; + info.name = name; + } + } + + if (pp.name != name) + logWarn("Local package at %s has different name than %s (%s)", path.toNativeString(), name, pp.name); + pp.ver = ver; + addPackages(packs, pp); } } catch( Exception e ){ @@ -510,7 +505,7 @@ logDebug("iterating dir %s entry %s", path.toNativeString(), pdir.name); if( !pdir.isDirectory ) continue; auto pack_path = path ~ pdir.name; - if( !existsFile(pack_path ~ PackageJsonFilename) ) continue; + if (!Package.isPackageAt(pack_path)) continue; Package p; try { if (!refresh_existing_packages) diff --git a/source/dub/project.d b/source/dub/project.d index 409102d..8eb7d7a 100644 --- a/source/dub/project.d +++ b/source/dub/project.d @@ -163,8 +163,8 @@ // load package description if (!m_fixedPackage) { - if (!existsFile(m_root~PackageJsonFilename)) { - logWarn("There was no '"~PackageJsonFilename~"' found for the application in '%s'.", m_root.toNativeString()); + if (!Package.isPackageAt(m_root)) { + logWarn("There was no package description found for the application in '%s'.", m_root.toNativeString()); auto json = Json.emptyObject; json.name = "unknown"; m_main = new Package(json, m_root); @@ -474,11 +474,11 @@ // Gather retrieved Package[string] retrieved; retrieved[m_main.name] = m_main; - foreach(ref Package p; m_dependencies) { + foreach(dep, ref Package p; m_dependencies) { auto pbase = p.basePackage; auto pexist = retrieved.get(pbase.name, null); if (pexist && pexist !is pbase){ - logError("The same package is referenced in different paths:"); + logError("Conflicting package references found:"); logError(" %s %s: %s", pexist.name, pexist.vers, pexist.path.toNativeString()); logError(" %s %s: %s", pbase.name, pbase.vers, pbase.path.toNativeString()); throw new Exception("Conflicting package multi-references.");