Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
cd03290
fix: add missing SemanticVersioning module
line0 May 23, 2026
f147a45
fix: broken script type handling in update feeds
line0 May 23, 2026
bf66595
fix: module loader running depctrl initializer hooks on already initi…
line0 May 23, 2026
f2e1fa8
fix: update failing due to unsupported string index in capitalization…
line0 May 23, 2026
977f37a
test: add first test
line0 May 23, 2026
75b6c43
ci: enforce LF + EOF newline for consistent hash calculation
line0 May 23, 2026
7f2530a
build: bump version; update feed
line0 May 23, 2026
ff8495a
fix: typo in ModuleLoader breaking optional module presence checks
line0 May 23, 2026
d0cbeee
refactor: tighten version number validation in updater
line0 May 23, 2026
d16fd64
fix: broken version number display in version errors
line0 May 23, 2026
167d427
fix: typos
line0 May 23, 2026
a1fc3f8
fix: semver parsers allowing invalid values
line0 May 23, 2026
5bc3f45
fix: semantic version toString roundtrip exception when invalid semve…
line0 May 23, 2026
c08a79c
fix: update errors missing information about whether or not a record …
line0 May 24, 2026
80ead7c
fix: broken skip lists in module loader
line0 May 24, 2026
c86e07e
feat: port Logger improvements from sqlite branch
line0 May 26, 2026
5a582f0
fix: nil dereference crash in feed template variable expansion
line0 May 26, 2026
4383018
refactor: add basic type annotations
line0 May 26, 2026
d55348e
refactor: port over FileOps improvements from sqlite branch
line0 May 26, 2026
ad04372
refactor port new ConfigHandler/ConfigView from sqlite branch
line0 May 26, 2026
a3106c9
refactor: add unit tests and extend testing framework (WIP)
line0 May 27, 2026
daa023a
refactor: remove dependency on aegisub.re and aegisub.util
line0 May 28, 2026
228cf7c
refactor: lift dependency on PreciseTimer
line0 May 28, 2026
fc48086
feat: provide an alternative to BadMutex that only uses OS APIs
line0 May 28, 2026
b39264d
feat: provide an alternative to DownloadManager that uses only OS API…
line0 May 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto eol=lf
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"files.insertFinalNewline": true
}
74 changes: 58 additions & 16 deletions DependencyControl.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,26 @@
"fileBaseUrl": "@{fileBaseUrl}macros-v@{version}-@{channel}/macros/@{namespace}",
"channels": {
"alpha": {
"version": "0.1.3",
"released": "2016-01-27",
"version": "0.2.0",
"released": "2026-05-23",
"default": true,
"files": [
{
"name": ".moon",
"url": "@{fileBaseUrl}@{fileName}",
"sha1": "3677B2817C3D1FFE86981C8ABCC092B3D2CCEE7B"
"sha1": "5F7E0EEFC89E71F427819EEF69630455C0CC2304"
}
],
"requiredModules": [
{
"moduleName": "l0.DependencyControl",
"version": "0.6.1"
"version": "0.7.0"
}
]
}
},
"changelog": {
"0.1.0": [
"initial release"
],
"0.1.0": ["initial release"],
"0.1.1": [
"The Install/Uninstall/Update dialogs now sort scripts by name.",
"DependencyControl and its requirements no longer appear in the uninstall menu."
Expand All @@ -63,6 +61,9 @@
],
"0.1.3": [
"Fixed an issue where trying to uninstall an unmanaged script resulted in an error unrelated to the intended error message."
],
"0.2.0": [
"Now registers the DepCtrl-internal test suite as a macro."
]
}
}
Expand All @@ -76,44 +77,70 @@
"fileBaseUrl": "@{fileBaseUrl}v@{version}-@{channel}/modules/@{scriptName}",
"channels": {
"alpha": {
"version": "0.6.3",
"released": "2016-02-06",
"version": "0.7.0",
"released": "2026-05-23",
"default": true,
"files": [
{
"name": ".moon",
"url": "@{fileBaseUrl}@{fileName}",
"sha1": "76C22149258CB1189265A367C1B28046F54F8FB3"
"sha1": "36104C47B776412EBF36AAA00D583180BF4507D5"
},
{
"name": "/Common.moon",
"url": "@{fileBaseUrl}@{fileName}",
"sha1": "7262886AEB9F106E95697E86FF0D44738415DBA6"
},
{
"name": "/ConfigHandler.moon",
"url": "@{fileBaseUrl}@{fileName}",
"sha1": "97BCD3207FE8158261FA7851057464535FCEFBC6"
"sha1": "1FEC3583C37E4A997E806D5B17A338390657BA53"
},
{
"name": "/FileOps.moon",
"url": "@{fileBaseUrl}@{fileName}",
"sha1": "D999D34DB93BA76EF0E991CEB1CD63F5CC5F8E68"
"sha1": "5A54D4B942F34C005ABC977B7655C2B849EC8889"
},
{
"name": "/Logger.moon",
"url": "@{fileBaseUrl}@{fileName}",
"sha1": "1E479FE95F0DFBEE8B098302AB589F32D0C40A00"
"sha1": "C4980A42A5AE9C8E24BE04DD12006D118606DBA1"
},
{
"name": "/ModuleLoader.moon",
"url": "@{fileBaseUrl}@{fileName}",
"sha1": "F35D88A9902FF9BC912D34299733D37FC15A36DF"
},
{
"name": "/Record.moon",
"url": "@{fileBaseUrl}@{fileName}",
"sha1": "796A430D14CACA3E2E15DBDD23F01DC4DC9E4B19"
},
{
"name": "/SemanticVersioning.moon",
"url": "@{fileBaseUrl}@{fileName}",
"sha1": "C8DE63A2BE75B1135CEED3ED4ADF7025C927706C"
},
{
"name": "/UnitTestSuite.moon",
"url": "@{fileBaseUrl}@{fileName}",
"sha1": "ADAB6EFB05E08A7828DCA01BC1FC43D6482979A1"
"sha1": "BF316812E9ACF6C73570337C2FCA89FD33189A2B"
},
{
"name": "/UpdateFeed.moon",
"url": "@{fileBaseUrl}@{fileName}",
"sha1": "1EE16D9D551FF82C2D7E448F2CD980E528874108"
"sha1": "7B64A01259AAA32E963708AE26BCF090AFC1E0DD"
},
{
"name": "/Updater.moon",
"url": "@{fileBaseUrl}@{fileName}",
"sha1": "A4AE061724E68B2EFBB7495A477263E1746E228A"
"sha1": "6647D7CAB70637E2B961EF334153718B06EA1027"
},
{
"name": ".moon",
"type": "test",
"url": "@{fileBaseUrl}/Tests.moon",
"sha1": "1ED8961CAFCADA7E4C04778227EECDC18E509B8D"
}
],
"requiredModules": [
Expand Down Expand Up @@ -141,6 +168,21 @@
}
},
"changelog": {
"0.7.0": [
"The previously monolithic `DependencyControl.moon` has been broken up into focused sub-modules as groundwork for a future SQLite-based script registry backend: `Record` (version record management), `ModuleLoader` (module loading and dependency resolution), `SemanticVersioning` (version number handling), and `Common` (shared enums and utilities).",
"Script types (automation macros vs. modules) and record types are now represented by proper enums (`ScriptType`, `RecordType`) instead of bare booleans, making the API more explicit and extensible.",
"UpdateFeed: Fixed two regressions caused by the refactoring, both of which caused the update process to fail.",
"Global initialization has been moved into a dedicated setup method, reducing implicit global state for loggers and configuration.",
"DepCtrl now refuses to load if the installed Moonscript is below the minimum required version with a helpful error message directing users to update their Aegisub build.",
"ModuleLoader: Fixed a regression where DepCtrl init hooks were called again on already-initialized modules, causing errors in modules that mutate their exported state on first call (e.g. BadMutex).",
"Common: Fixed a long-standing bug that guaranteed the `capitalize()` function to fail, that was never caught because it was unused until the refactoring.",
"Updater: Fixed a potential issue where a multi-assignment statement could corrupt record fields after an unsuccessful update."
],
"0.6.4": [
"Logger: Fixed a crash when `logEx()` is called without format arguments — `msg:format(...)` is now skipped when no varargs are supplied.",
"Logger: `fileBaseName` now falls back to `\"UNKNOWN\"` when `script_namespace` is nil, preventing errors during Logger initialization in contexts where no namespace is available.",
"Logger/UpdateFeed: Fixed chained method calls on file handles (`handle:write():flush()` and `handle:write():close()`) that could silently swallow errors"
],
"0.6.3": [
"Fixed a v0.6.2 regression that caused DependencyControl to fail loading the first time after a scheduled self-update."
],
Expand Down
54 changes: 33 additions & 21 deletions macros/l0.DependencyControl.Toolbox.moon
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export script_name = "DependencyControl Toolbox"
export script_description = "Provides DependencyControl maintenance and configuration tools."
export script_version = "0.1.3"
export script_version = "0.2.0"
export script_author = "line0"
export script_namespace = "l0.DependencyControl.Toolbox"

Expand All @@ -11,11 +11,12 @@ logger.usePrefixWindow = false

msgs = {
install: {
scanning: "Scanning %d available feeds..."
scanning: "Scanning %d available feeds...",
createScriptUpdateRecordFailed: "Failed to create an update record for %s '%s' from feed %s: %s"
}
uninstall: {
running: "Uninstalling %s '%s'..."
success: "%s '%s' was removed sucessfully. Reload your automation scripts or restart Aegisub for the changes to take effect."
success: "%s '%s' was removed successfully. Reload your automation scripts or restart Aegisub for the changes to take effect."
lockedFiles: "%s Some script files are still in use and will be deleted during the next restart/reload:\n%s"
error: "Error: %s"
}
Expand All @@ -37,7 +38,7 @@ buildInstalledDlgList = (scriptType, config, isUninstall) ->

for namespace, script in pairs config.c[scriptType]
continue if protectedModules[namespace]
item = "%s v%s%s"\format script.name, depRec\getVersionString(script.version),
item = "%s v%s%s"\format script.name, DepCtrl.SemanticVersioning\toString(script.version),
script.activeChannel and " [#{script.activeChannel}]" or ""
list[#list+1] = item
table.sort list, (a, b) -> a\lower! < b\lower!
Expand Down Expand Up @@ -77,29 +78,37 @@ getScriptListDlg = (macros, modules) ->
{name: "module", class: "dropdown", x: 1, y: 1, width: 1, height: 1, items: modules, value: "" }
}

runUpdaterTask = (scriptData, exhaustive) ->
runUpdaterTask = (scriptData, exhaustive, isInstall) ->
return unless scriptData
task, err = DepCtrl.updater\addTask scriptData, nil, nil, exhaustive, scriptData.channel
if task then task\run!
else logger\log err


task, code, extErr = DepCtrl.updater\addTask scriptData, nil, nil, exhaustive, scriptData.channel
return task\run! if task
with scriptData
logger\log DepCtrl.updater\getUpdaterErrorMsg code, .moduleName or .name,
.moduleName and DepCtrl.ScriptType.Module or DepCtrl.ScriptType.Automation, isInstall, extErr

-- Macros

install = ->
config = getConfig!

addAvailableToInstall = (tbl, feed, scriptType) ->
for namespace, data in pairs feed.data[scriptType]
scriptData = feed\getScript namespace, scriptType == "modules", nil, false
scriptTypeConfigAndFeedKeyName = DepCtrl.ScriptType.name.legacy[scriptType]

for namespace, data in pairs feed.data[scriptTypeConfigAndFeedKeyName]
scriptData, err = feed\getScript namespace, scriptType, nil, false
if err
logger\warn msgs.install.createScriptUpdateRecordFailed\format DepCtrl.terms.scriptType.singular[scriptType], namespace, feed.url, err
continue

channels, defaultChannel = scriptData\getChannels!
tbl[namespace] or= {}
for channel in *channels
record = scriptData.data.channels[channel]
verNum = depRec\getVersionNumber record.version
unless config.c[scriptType][namespace] or (tbl[namespace][channel] and verNum < tbl[namespace][channel].verNum)
verNum = DepCtrl.SemanticVersioning\toNumber record.version
unless config.c[scriptTypeConfigAndFeedKeyName][namespace] or (tbl[namespace][channel] and verNum < tbl[namespace][channel].verNum)
tbl[namespace][channel] = { name: scriptData.name, version: record.version, verNum: verNum, feed: feed.url,
default: defaultChannel == channel, moduleName: scriptType == "modules" and namespace }
default: defaultChannel == channel, moduleName: scriptType == DepCtrl.ScriptType.Module and namespace }
return tbl

buildDlgList = (tbl) ->
Expand All @@ -120,8 +129,8 @@ install = ->

logger\log msgs.install.scanning, #feeds
for feed in *feeds
macros = addAvailableToInstall macros, feed, "macros"
modules = addAvailableToInstall modules, feed, "modules"
macros = addAvailableToInstall macros, feed, DepCtrl.ScriptType.Automation
modules = addAvailableToInstall modules, feed, DepCtrl.ScriptType.Module

-- build macro and module lists as well as reverse mappings
moduleList, moduleMap = buildDlgList modules
Expand All @@ -132,8 +141,8 @@ install = ->

-- create and run the update tasks
macro, mdl = macroMap[res.macro], moduleMap[res.module]
runUpdaterTask mdl, false
runUpdaterTask macro, false
runUpdaterTask mdl, false, true
runUpdaterTask macro, false, true

uninstall = ->
doUninstall = (script) ->
Expand Down Expand Up @@ -183,8 +192,8 @@ update = ->

-- create and run the update tasks
macro, mdl = macroMap[res.macro], moduleMap[res.module]
runUpdaterTask mdl, res.exhaustive
runUpdaterTask macro, res.exhaustive
runUpdaterTask mdl, res.exhaustive, false
runUpdaterTask macro, res.exhaustive, false

macroConfig = ->
config = getConfig "macros"
Expand Down Expand Up @@ -213,9 +222,12 @@ macroConfig = ->

config\write!

-- required to register DepCtrl test suite
DepCtrl.__class.version\register DepCtrl

depRec\registerMacros{
{"Install Script", "Installs an automation script or module on your system.", install},
{"Update Script", "Manually check and perform updates to any installed script.", update},
{"Uninstall Script", "Removes an automation script or module from your system.", uninstall},
{"Macro Configuration", "Lets you change per-automation script settings.", macroConfig},
}, "DependencyControl"
}, "DependencyControl"
3 changes: 3 additions & 0 deletions modules/AegisubShims.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
aegisub = require "l0.AegisubShims.aegisub"

return {:aegisub}
12 changes: 6 additions & 6 deletions modules/DependencyControl.moon
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,26 @@ class DependencyControl extends Record
@Updater = Updater
@UnitTestSuite = UnitTestSuite
@FileOps = FileOps
@SemanticVersioning = SemanticVersioning


rec = DependencyControl{
name: "DependencyControl",
version: "0.6.3",
version: "0.7.0",
description: "Provides script management and auto-updating for Aegisub macros and modules.",
author: "line0",
url: "http://github.com/TypesettingTools/DependencyControl",
moduleName: "l0.DependencyControl",
feed: "https://raw.githubusercontent.com/TypesettingTools/DependencyControl/master/DependencyControl.json",
{
{"DM.DownloadManager", version: "0.3.1", feed: "https://raw.githubusercontent.com/torque/ffi-experiments/master/DependencyControl.json"},
{"BM.BadMutex", version: "0.1.3", feed: "https://raw.githubusercontent.com/torque/ffi-experiments/master/DependencyControl.json"},
{"PT.PreciseTimer", version: "0.1.5", feed: "https://raw.githubusercontent.com/torque/ffi-experiments/master/DependencyControl.json"},
{"requireffi.requireffi", version: "0.1.1", feed: "https://raw.githubusercontent.com/torque/ffi-experiments/master/DependencyControl.json"},
{"DM.DownloadManager", version: "0.3.1", feed: "https://raw.githubusercontent.com/torque/ffi-experiments/master/DependencyControl.json", optional: true},
{"BM.BadMutex", version: "0.1.3", feed: "https://raw.githubusercontent.com/torque/ffi-experiments/master/DependencyControl.json", optional: true},
{"requireffi.requireffi", version: "0.1.1", feed: "https://raw.githubusercontent.com/torque/ffi-experiments/master/DependencyControl.json", optional: true},
}
}
DependencyControl.__class.version = rec
LOADED_MODULES[rec.moduleName], package.loaded[rec.moduleName] = DependencyControl, DependencyControl
DependencyControl.updater\scheduleUpdate rec
rec\requireModules!

return DependencyControl
return DependencyControl
Loading