diff --git a/source/dub/dependency.d b/source/dub/dependency.d index 3f8de76..f56795b 100644 --- a/source/dub/dependency.d +++ b/source/dub/dependency.d @@ -135,14 +135,26 @@ } /// Determines if the dependency is required or optional. - @property bool optional() const { return m_optional; } + @property bool optional() const scope @safe pure nothrow @nogc + { + return m_optional; + } /// ditto - @property void optional(bool optional) { m_optional = optional; } + @property void optional(bool optional) scope @safe pure nothrow @nogc + { + m_optional = optional; + } /// Determines if an optional dependency should be chosen by default. - @property bool default_() const { return m_default; } + @property bool default_() const scope @safe pure nothrow @nogc + { + return m_default; + } /// ditto - @property void default_(bool value) { m_default = value; } + @property void default_(bool value) scope @safe pure nothrow @nogc + { + m_default = value; + } /// Returns true $(I iff) the version range only matches a specific version. @property bool isExactVersion() const scope @safe @@ -155,7 +167,7 @@ /// Returns the exact version matched by the version range. @property Version version_() const { - enforce(this.m_range.m_versA == this.m_range.m_versB, + enforce(this.m_range.isExactVersion(), "Dependency "~this.versionSpec~" is no exact version."); return this.m_range.m_versA; } @@ -349,21 +361,6 @@ return 0; } - /// ditto - size_t toHash() - const nothrow @trusted { - try { - size_t hash = 0; - hash = this.m_range.m_inclusiveA.hashOf(hash); - hash = this.m_range.m_versA.toString().hashOf(hash); - hash = this.m_range.m_inclusiveB.hashOf(hash); - hash = this.m_range.m_versB.toString().hashOf(hash); - hash = m_optional.hashOf(hash); - hash = m_default.hashOf(hash); - return hash; - } catch (Exception) assert(false); - } - /** Determines if this dependency specification is valid. A specification is valid if it can match at least one version. @@ -792,13 +789,9 @@ bool matches(Version other, VersionMatchMode mode = VersionMatchMode.standard) const scope @safe pure { - if (this != other) - return false; - - if (mode == VersionMatchMode.strict && this.toString() != other.toString()) - return false; - - return true; + if (mode == VersionMatchMode.strict) + return this.toString() == other.toString(); + return this == other; } /** Compares two versions/branches for precedence. @@ -870,7 +863,7 @@ public bool matches (ref const Version v) const @safe { if (m_versA.isBranch) { - enforce(m_versA == m_versB); + enforce(this.isExactVersion()); return m_versA == v; } @@ -990,7 +983,7 @@ string r; if (this == Dependency.invalid.m_range) return "invalid"; - if (m_versA == m_versB && m_inclusiveA && m_inclusiveB) { + if (this.isExactVersion() && m_inclusiveA && m_inclusiveB) { // Special "==" case if (m_versA == Version.masterBranch) return "~master"; else return m_versA.toString(); @@ -1018,7 +1011,7 @@ if (m_versA != Version.minRelease) r = (m_inclusiveA ? ">=" : ">") ~ m_versA.toString(); if (m_versB != Version.maxRelease) r ~= (r.length==0 ? "" : " ") ~ (m_inclusiveB ? "<=" : "<") ~ m_versB.toString(); - if (m_versA == Version.minRelease && m_versB == Version.maxRelease) r = ">=0.0.0"; + if (this.matchesAny()) r = ">=0.0.0"; return r; } diff --git a/source/dub/internal/vibecompat/inet/path.d b/source/dub/internal/vibecompat/inet/path.d index 0872b14..3e844a3 100644 --- a/source/dub/internal/vibecompat/inet/path.d +++ b/source/dub/internal/vibecompat/inet/path.d @@ -60,7 +60,7 @@ } /// Determines if the path is absolute. - @property bool absolute() const { return m_absolute; } + @property bool absolute() const scope @safe pure nothrow @nogc { return m_absolute; } /// Resolves all '.' and '..' path entries as far as possible. void normalize() @@ -84,7 +84,7 @@ /// Converts the Path back to a string representation using slashes. string toString() - const { + const @safe { if( m_nodes.empty ) return absolute ? "/" : ""; Appender!string ret; @@ -190,7 +190,7 @@ @property immutable(PathEntry)[] nodes() const { return m_nodes; } /// The number of path entries of which this path is composed - @property size_t length() const { return m_nodes.length; } + @property size_t length() const scope @safe pure nothrow @nogc { return m_nodes.length; } /// True if the path contains no entries @property bool empty() const { return m_nodes.length == 0; } @@ -242,7 +242,7 @@ void opOpAssign(string OP)(NativePath rhs) if( OP == "~" ) { auto p = this ~ rhs; m_nodes = p.m_nodes; m_endsWithSlash = rhs.m_endsWithSlash; } /// Tests two paths for equality using '=='. - bool opEquals(ref const NativePath rhs) const { + bool opEquals(scope ref const NativePath rhs) const scope @safe { if( m_absolute != rhs.m_absolute ) return false; if( m_endsWithSlash != rhs.m_endsWithSlash ) return false; if( m_nodes.length != rhs.length ) return false; @@ -252,7 +252,7 @@ return true; } /// ditto - bool opEquals(const NativePath other) const { return opEquals(other); } + bool opEquals(scope const NativePath other) const scope @safe { return opEquals(other); } int opCmp(ref const NativePath rhs) const { if( m_absolute != rhs.m_absolute ) return cast(int)m_absolute - cast(int)rhs.m_absolute; @@ -287,17 +287,17 @@ m_name = str; } - string toString() const pure { return m_name; } + string toString() const return scope @safe pure nothrow @nogc { return m_name; } - @property string name() const { return m_name; } + @property string name() const return scope @safe pure nothrow @nogc { return m_name; } NativePath opBinary(string OP)(PathEntry rhs) const if( OP == "~" ) { return NativePath([this, rhs], false); } - bool opEquals(ref const PathEntry rhs) const { return m_name == rhs.m_name; } - bool opEquals(PathEntry rhs) const { return m_name == rhs.m_name; } - bool opEquals(string rhs) const { return m_name == rhs; } - int opCmp(ref const PathEntry rhs) const { return m_name.cmp(rhs.m_name); } - int opCmp(string rhs) const { return m_name.cmp(rhs); } + bool opEquals(scope ref const PathEntry rhs) const scope @safe pure nothrow @nogc { return m_name == rhs.m_name; } + bool opEquals(scope PathEntry rhs) const scope @safe pure nothrow @nogc { return m_name == rhs.m_name; } + bool opEquals(string rhs) const scope @safe pure nothrow @nogc { return m_name == rhs; } + int opCmp(scope ref const PathEntry rhs) const scope @safe pure nothrow @nogc { return m_name.cmp(rhs.m_name); } + int opCmp(string rhs) const scope @safe pure nothrow @nogc { return m_name.cmp(rhs); } } private bool isValidFilename(string str) diff --git a/source/dub/recipe/packagerecipe.d b/source/dub/recipe/packagerecipe.d index d32578e..14bb983 100644 --- a/source/dub/recipe/packagerecipe.d +++ b/source/dub/recipe/packagerecipe.d @@ -465,6 +465,7 @@ private T clone(T)(ref const(T) val) { + import std.sumtype; import std.traits : isSomeString, isDynamicArray, isAssociativeArray, isBasicType, ValueType; static if (is(T == immutable)) return val; @@ -484,6 +485,8 @@ foreach (k, ref f; val) ret[k] = clone!V(f); return ret; + } else static if (is(T == SumType!A, A...)) { + return val.match!((any) => T(clone(any))); } else static if (is(T == struct)) { T ret; foreach (i, M; typeof(T.tupleof))