Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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"
5 changes: 3 additions & 2 deletions modules/DependencyControl.moon
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ 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",
Expand All @@ -46,4 +47,4 @@ LOADED_MODULES[rec.moduleName], package.loaded[rec.moduleName] = DependencyContr
DependencyControl.updater\scheduleUpdate rec
rec\requireModules!

return DependencyControl
return DependencyControl
84 changes: 42 additions & 42 deletions modules/DependencyControl/Common.moon
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
ffi = require "ffi"
class DependencyControlCommon
-- Some terms are shared across components
@platform = "#{ffi.os}-#{ffi.arch}"
@terms = {
scriptType: {
singular: { "automation script", "module" }
plural: { "automation scripts", "modules" }
}
isInstall: {
[true]: "installation"
[false]: "update"
}
capitalize: (str) -> str[1]\upper! .. str\sub 2
}
-- Common enums
@RecordType = {
Managed: 1
Unmanaged: 2
}
@ScriptType = {
Automation: 1
Module: 2
name: {
legacy: { "macros", "modules" }
canonical: {"automation", "modules"}
}
}
automationDir: {
aegisub.decode_path("?user/automation/autoload"),
aegisub.decode_path("?user/automation/include")
}
@testDir = {aegisub.decode_path("?user/automation/tests/DepUnit/macros"),
aegisub.decode_path("?user/automation/tests/DepUnit/modules")}
ffi = require "ffi"

class DependencyControlCommon
-- Some terms are shared across components
@platform = "#{ffi.os}-#{ffi.arch}"

@terms = {
scriptType: {
singular: { "automation script", "module" }
plural: { "automation scripts", "modules" }
}

isInstall: {
[true]: "installation"
[false]: "update"
}

capitalize: (str) -> (str\sub 1, 1)\upper! .. str\sub 2
}

-- Common enums
@RecordType = {
Managed: 1
Unmanaged: 2
}

@ScriptType = {
Automation: 1
Module: 2
name: {
legacy: { "macros", "modules" }
canonical: {"automation", "modules"}
}
}

automationDir: {
aegisub.decode_path("?user/automation/autoload"),
aegisub.decode_path("?user/automation/include")
}

@testDir = {aegisub.decode_path("?user/automation/tests/DepUnit/macros"),
aegisub.decode_path("?user/automation/tests/DepUnit/modules")}
2 changes: 1 addition & 1 deletion modules/DependencyControl/ConfigHandler.moon
Original file line number Diff line number Diff line change
Expand Up @@ -327,4 +327,4 @@ Reload your automation scripts to generate a new configuration file.]]
@userConfig[k] = isTable and @deepCopy(v) or v
changesMade = true

return changesMade
return changesMade
Loading