• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nightconcept / almandine / 14715174283

28 Apr 2025 06:32PM UTC coverage: 37.748%. First build
14715174283

push

github

web-flow
Merge 789647aa5 into 78f97e22e

477 of 566 new or added lines in 14 files covered. (84.28%)

1693 of 4485 relevant lines covered (37.75%)

11.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

40.24
/src/modules/install.lua
1
--[[
2
  Install Command Module
3

4
  Provides functionality to install all dependencies listed in project.lua or a specific dependency.
5
]]--
6

7
---
8
-- Installs dependencies from the manifest or lockfile.
9
-- If dep_name is provided, only installs that dependency.
10
-- @param dep_name string|nil Dependency name to install (or all if nil).
11
-- @param load_manifest function Function to load the manifest.
12
-- @param ensure_lib_dir function Function to ensure lib dir exists.
13
-- @param downloader table utils.downloader module.
14
-- @param utils table Utils module (must provide .downloader).
15
-- @param lockfile_deps table|nil Lockfile dependency table (optional)
16
local function install_dependencies(dep_name, load_manifest, ensure_lib_dir, downloader, utils, lockfile_deps)
17
  ensure_lib_dir()
2✔
18
  if lockfile_deps then
2✔
NEW
19
    local deps = lockfile_deps
×
NEW
20
    for name, source in pairs(deps) do
×
NEW
21
      if (not dep_name) or (dep_name == name) then
×
22
        local out_path
23
        local url
NEW
24
        if type(source) == "table" and source.url and source.path then
×
NEW
25
          url = source.url
×
NEW
26
          out_path = source.path
×
27
        else
NEW
28
          url = source
×
NEW
29
          local filesystem_utils = require("utils.filesystem")
×
NEW
30
          out_path = filesystem_utils.join_path(
×
31
            "src",
32
            "lib",
NEW
33
            name .. ".lua"
×
34
          )
35
        end
NEW
36
        local ok3, err3 = (utils or {downloader=downloader}).downloader.download(url, out_path)
×
NEW
37
        if ok3 then
×
NEW
38
          print(string.format("Downloaded %s to %s", name, out_path))
×
39
        else
NEW
40
          print(string.format("Failed to download %s: %s", name, err3))
×
41
        end
42
      end
43
    end
44
  else
45
    local manifest, err = load_manifest()
2✔
46
    if not manifest then print(err) return end
2✔
47
    local deps = manifest.dependencies or {}
2✔
48
    for name, source in pairs(deps) do
6✔
49
      if (not dep_name) or (dep_name == name) then
4✔
50
        local out_path
51
        local url
52
        if type(source) == "table" and source.url and source.path then
3✔
53
          url = source.url
1✔
54
          out_path = source.path
1✔
55
        else
56
          url = source
2✔
57
          local filesystem_utils = require("utils.filesystem")
2✔
58
          out_path = filesystem_utils.join_path(
4✔
59
            "src",
2✔
60
            "lib",
2✔
61
            name .. ".lua"
2✔
62
          )
2✔
63
        end
64
        local ok3, err3 = (utils or {downloader=downloader}).downloader.download(url, out_path)
3✔
65
        if ok3 then
3✔
66
          print(string.format("Downloaded %s to %s", name, out_path))
3✔
67
        else
NEW
68
          print(string.format("Failed to download %s: %s", name, err3))
×
69
        end
70
      end
71
    end
72
  end
73
end
74

75
--[[
76
  Lockfile Management Module (migrated from src/lib/lockfile.lua)
77
  Provides functions to generate, serialize, and write the Almandine lockfile (`almd-lock.lua`).
78
  The lockfile captures exact dependency versions and hashes for reproducible builds.
79
]]--
80

81
local lockfile = {}
1✔
82

83
local io = io
1✔
84
local table = table
1✔
85
local tostring = tostring
1✔
86

87
--- Lockfile schema version (increment if schema changes)
88
local API_VERSION = "1"
1✔
89

90
---
91
-- Generates a lockfile table from resolved dependencies.
92
-- @param resolved_deps table Table of resolved dependencies. Each key is a package name, value is a table with fields:
93
--                          - version (string, optional)
94
--                          - hash (string, required)
95
--                          - source (string, optional)
96
-- @return table Lockfile table matching the schema
97
function lockfile.generate_lockfile_table(resolved_deps)
1✔
NEW
98
  assert(type(resolved_deps) == "table", "resolved_deps must be a table")
×
NEW
99
  local pkgs = {}
×
NEW
100
  for name, dep in pairs(resolved_deps) do
×
NEW
101
    assert(type(dep) == "table", "Dependency entry must be a table")
×
NEW
102
    assert(dep.hash, "Dependency '" .. name .. "' must have a hash")
×
NEW
103
    local entry = { hash = dep.hash }
×
NEW
104
    if dep.version then entry.version = dep.version end
×
NEW
105
    if dep.source then entry.source = dep.source end
×
NEW
106
    pkgs[name] = entry
×
107
  end
NEW
108
  return {
×
109
    api_version = API_VERSION,
NEW
110
    package = pkgs
×
111
  }
112
end
113

114
---
115
-- Serializes a lockfile table to a string (Lua syntax).
116
-- @param lockfile_table table Lockfile table
117
-- @return string Lua code as string
118
function lockfile.serialize_lockfile(lockfile_table)
1✔
NEW
119
  assert(type(lockfile_table) == "table", "lockfile_table must be a table")
×
120
  local function serialize(tbl, indent)
NEW
121
    indent = indent or 0
×
NEW
122
    local pad = string.rep("  ", indent)
×
NEW
123
    local lines = {"{"}
×
NEW
124
    for k, v in pairs(tbl) do
×
NEW
125
      local key = (type(k) == "string" and string.format("%s = ", k)) or ("[" .. tostring(k) .. "] = ")
×
NEW
126
      if type(v) == "table" then
×
NEW
127
        table.insert(lines, pad .. "  " .. key .. serialize(v, indent + 1) .. ",")
×
NEW
128
      elseif type(v) == "string" then
×
NEW
129
        table.insert(lines, pad .. "  " .. key .. string.format('"%s"', v) .. ",")
×
130
      else
NEW
131
        table.insert(lines, pad .. "  " .. key .. tostring(v) .. ",")
×
132
      end
133
    end
NEW
134
    table.insert(lines, pad .. "}")
×
NEW
135
    return table.concat(lines, "\n")
×
136
  end
NEW
137
  return "return " .. serialize(lockfile_table, 0) .. "\n"
×
138
end
139

140
---
141
-- Writes the lockfile to disk as `almd-lock.lua`.
142
-- @param lockfile_table table Lockfile table
143
-- @param path string (optional) Path to write to (default: "almd-lock.lua" in project root)
144
-- @return boolean, string True and path if successful, false and error message otherwise
145
function lockfile.write_lockfile(lockfile_table, path)
1✔
NEW
146
  path = path or "almd-lock.lua"
×
NEW
147
  local content = lockfile.serialize_lockfile(lockfile_table)
×
NEW
148
  local file, err = io.open(path, "w")
×
NEW
149
  if not file then return false, err end
×
NEW
150
  file:write(content)
×
NEW
151
  file:close()
×
NEW
152
  return true, path
×
153
end
154

155
---
156
-- Prints usage/help information for the `install` command.
157
-- Usage: almd install [<dep_name>]
158
-- Installs all dependencies listed in project.lua, or only <dep_name> if specified.
159
local function help_info()
NEW
160
  print([[\nUsage: almd install [<dep_name>]
×
161

162
Installs all dependencies listed in project.lua, or only <dep_name> if specified.
163
Example:
164
  almd install
165
  almd install lunajson
NEW
166
]])
×
167
end
168

169
return {
1✔
170
  install_dependencies = install_dependencies,
1✔
171
  lockfile = lockfile,
1✔
172
  help_info = help_info
1✔
173
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc