diff --git a/DependencyControl.json b/DependencyControl.json index 8b5ec96..97122d1 100644 --- a/DependencyControl.json +++ b/DependencyControl.json @@ -802,7 +802,8 @@ "feat(CLI): `--serve-channel` can be given more than once to graft the dev build onto several channels at once, the first of which becomes the served feed's default.", "fix: A package's settings are no longer reverted by a second DependencyControl instance writing the same config file (e.g. during a DependencyControl update, in another automation script context, or from another Aegisub process). Each save now writes only the fields it changed since it last read the file.", "fix: A regression introduced in v0.7.0 was fixed that prevented the new version number of updated packages from being written into the DependencyControl config file when nothing else in its DependencyControl record changed.", - "fix: Changes to settings that affect feed fetching (private host blocking, feed size and timeout limits) now take effect immediately instead of requiring an automation scripts reload." + "fix: Changes to settings that affect feed fetching (private host blocking, feed size and timeout limits) now take effect immediately instead of requiring an automation scripts reload.", + "fix: A required module that isn't managed by DependencyControl and declares a version that can't be parsed no longer fails to load with a 'Bad DependencyControl record' error. It is now treated as outdated and updated from its feed." ] } }, diff --git a/modules/l0/DependencyControl/ModuleLoader.moon b/modules/l0/DependencyControl/ModuleLoader.moon index febf2a5..7f9244a 100644 --- a/modules/l0/DependencyControl/ModuleLoader.moon +++ b/modules/l0/DependencyControl/ModuleLoader.moon @@ -45,7 +45,8 @@ class ModuleLoader url = url and ": #{url}" or "" if ref -- unmanaged records have refs whose .version is a string instead of a DepCtrl record - version = SemanticVersion\toString type(ref.version) == "table" and ref.version.version or ref.version + rawVersion = type(ref.version) == "table" and ref.version.version or ref.version + version = SemanticVersion\toString(rawVersion) or tostring rawVersion return msgs.formatVersionErrorTemplate.outdated\format name, version, reqVersion, url, reason else reqVersion = reqVersion and " (v#{reqVersion})" or "" @@ -162,7 +163,9 @@ class ModuleLoader continue if not ModuleProvider.isDepCtrlVersionRecord record - record = @@ moduleName: .moduleName, version: record, recordType: domain.RecordType.Unmanaged + -- a version that doesn't parse can't satisfy the requirement, so it counts as 0.0.0 and the module gets updated + version = SemanticVersion\toPacked(record) or 0 + record = @@ moduleName: .moduleName, :version, recordType: domain.RecordType.Unmanaged -- force an update for outdated modules if not record\checkVersion .version diff --git a/modules/l0/DependencyControl/test/ModuleLoader.moon b/modules/l0/DependencyControl/test/ModuleLoader.moon index 7e51819..dc892ec 100644 --- a/modules/l0/DependencyControl/test/ModuleLoader.moon +++ b/modules/l0/DependencyControl/test/ModuleLoader.moon @@ -36,6 +36,12 @@ ut\assertContains result, "Required: v2.0.0" ut\assertContains result, "1.1.1" + formatVersionErrorTemplate_outdated_unparseableRef: (ut) -> + ref = {version: "##__LOG_VERSION__##"} + result = ModuleLoader.formatVersionErrorTemplate nil, "MyModule", "1.0.0", nil, "too old", ref + ut\assertContains result, "Installed: v##__LOG_VERSION__##" + ut\assertContains result, "Required: v1.0.0" + formatVersionErrorTemplate_outdated_tableRef: (ut) -> ref = {version: {version: 65793}} -- 1*65536 + 1*256 + 1 = "1.1.1" in base-256 encoding result = ModuleLoader.formatVersionErrorTemplate nil, "MyModule", "2.0.0", nil, "too old", ref @@ -281,6 +287,31 @@ ut\assertEquals err, "" ut\assertEquals mdl._ref, newRef + -- loadModules: an unmanaged module whose version string doesn't parse gets an unmanaged record at + -- 0.0.0, which fails the requirement and sends the module to the updater. + loadModules_unparseableUnmanagedVersionForcesUpdate: (ut) -> + ns = "test.ModuleLoader.unparseableVersion" + newRef = {updated: true} + loadedRef = {version: "##__LOG_VERSION__##"} + local constructedArgs, requiredRecord + updater = {require: (record) => + requiredRecord = record + newRef} + recClass = setmetatable {ScriptType: domain.ScriptType, __name: "DependencyControl", :updater}, + {__call: (cls, args) -> + constructedArgs = args + {checkVersion: ((target) => SemanticVersion\toPacked(args.version) >= SemanticVersion\toPacked target)}} + rec = {feed: nil, moduleName: "host.Module", name: "host", __class: recClass} + mdl = {moduleName: ns, name: ns, version: SemanticVersion\toPacked "1.0.0"} + (ut\stub ModuleLoader, "loadModule")\calls (self, m, usePrivate) -> m._ref = loadedRef unless usePrivate + success, err = ModuleLoader.loadModules rec, {mdl} + ut\assertTrue success + ut\assertEquals err, "" + ut\assertEquals constructedArgs.version, 0 + ut\assertEquals constructedArgs.recordType, domain.RecordType.Unmanaged + ut\assertNotNil requiredRecord + ut\assertEquals mdl._ref, newRef + -- loadModules: an outdated *required* module the updater can't update fails with an "outdated" error loadModules_outdatedRequiredFails: (ut) -> ns = "test.ModuleLoader.outdatedFail" @@ -344,7 +375,8 @@ _order: { "formatVersionErrorTemplate_missing_bare", "formatVersionErrorTemplate_missing_withVersion", "formatVersionErrorTemplate_missing_withUrl", - "formatVersionErrorTemplate_outdated_scalarRef", "formatVersionErrorTemplate_outdated_tableRef", + "formatVersionErrorTemplate_outdated_scalarRef", "formatVersionErrorTemplate_outdated_unparseableRef", + "formatVersionErrorTemplate_outdated_tableRef", "createDummyRef_nonModule", "createDummyRef_newRef", "createDummyRef_existingRef", "removeDummyRef_nonModule", "removeDummyRef_dummy", "removeDummyRef_nonDummy", "loadModule_cached", "loadModule_success", "loadModule_missing", "loadModule_error", @@ -352,7 +384,8 @@ "loadModules_skipsModule", "loadModules_allLoaded", "loadModules_missingFetchedViaUpdater", "loadModules_missingRequiredFails", "loadModules_missingOptionalSkipped", "loadModules_requirementsUnmetSurfacesNestedReason", - "loadModules_outdatedForcesUpdate", "loadModules_outdatedRequiredFails", + "loadModules_outdatedForcesUpdate", "loadModules_unparseableUnmanagedVersionForcesUpdate", + "loadModules_outdatedRequiredFails", "loadModules_updateInProgressAcceptsLoadedRef", "checkOptionalModules_noneOptional", "checkOptionalModules_missingOptional" }