Module: Vcdeps::Manifest
- Defined in:
- lib/vcdeps/manifest.rb
Overview
Reads, validates, and canonically hashes a vcpkg manifest directory. The install key (§2.5) is SHA256 over the canonicalized vcpkg.json + vcpkg-configuration.json + triplet + tool version, so the same inputs always map to the same out-of-tree install root and any change forces a fresh one.
Constant Summary collapse
- MANIFEST_NAME =
"vcpkg.json"- CONFIGURATION_NAME =
"vcpkg-configuration.json"
Class Method Summary collapse
-
.canonical(value) ⇒ Object
Canonical JSON: recursively sort object keys, preserve array order, compact-generate.
- .configuration_path(dir) ⇒ Object
-
.key(dir, triplet, tool_version) ⇒ Object
The 16-hex install key for (manifest dir, triplet, tool version) (§2.5).
-
.load!(dir) ⇒ Object
Pre-flight check (§5.1/§5.2): the manifest exists, parses, and either pins "builtin-baseline" OR has a vcpkg-configuration.json beside it (git-registry instances hard-fail otherwise).
-
.manifest_path(dir) ⇒ Object
Absolute path to
\vcpkg.json (display-backslashed). -
.read_json(path) ⇒ Object
Read and JSON-parse a file with BOM tolerance (editors love BOMs).
- .sort_value(value) ⇒ Object
Class Method Details
.canonical(value) ⇒ Object
Canonical JSON: recursively sort object keys, preserve array order, compact-generate. Two textually different but semantically identical manifests canonicalize identically.
83 84 85 |
# File 'lib/vcdeps/manifest.rb', line 83 def canonical(value) JSON.generate(sort_value(value)) end |
.configuration_path(dir) ⇒ Object
22 23 24 |
# File 'lib/vcdeps/manifest.rb', line 22 def configuration_path(dir) File.join(dir, CONFIGURATION_NAME) end |
.key(dir, triplet, tool_version) ⇒ Object
The 16-hex install key for (manifest dir, triplet, tool version) (§2.5).
65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/vcdeps/manifest.rb', line 65 def key(dir, triplet, tool_version) manifest = read_json(File.join(dir, MANIFEST_NAME)) config_path = configuration_path(dir) config = File.exist?(config_path) ? read_json(config_path) : nil material = [ canonical(manifest), config ? canonical(config) : "", triplet.to_s, tool_version.to_s ].join("\0") Digest::SHA256.hexdigest(material)[0, 16] end |
.load!(dir) ⇒ Object
Pre-flight check (§5.1/§5.2): the manifest exists, parses, and either pins "builtin-baseline" OR has a vcpkg-configuration.json beside it (git-registry instances hard-fail otherwise). Returns the parsed manifest Hash.
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/vcdeps/manifest.rb', line 43 def load!(dir) path = File.join(dir, MANIFEST_NAME) manifest = read_json(path) unless manifest.is_a?(Hash) raise ManifestError, "vcdeps: #{MANIFEST_NAME} must be a JSON object." end has_baseline = manifest.key?("builtin-baseline") && !manifest["builtin-baseline"].to_s.empty? has_config = File.exist?(configuration_path(dir)) unless has_baseline || has_config raise ManifestError, "vcdeps: #{manifest_path(dir)} has no " \ "\"builtin-baseline\" (required by git-registry vcpkg instances). " \ "Add one with: vcdeps baseline --manifest #{dir.tr('/', '\\')}" end manifest end |
.manifest_path(dir) ⇒ Object
Absolute path to
18 19 20 |
# File 'lib/vcdeps/manifest.rb', line 18 def manifest_path(dir) File.join(dir, MANIFEST_NAME).tr("/", "\\") end |
.read_json(path) ⇒ Object
Read and JSON-parse a file with BOM tolerance (editors love BOMs). Returns the parsed Hash. Raises Vcdeps::ManifestError on a missing file or a JSON syntax error (carrying the parser's position message).
29 30 31 32 33 34 35 36 37 38 |
# File 'lib/vcdeps/manifest.rb', line 29 def read_json(path) raw = File.read(path, encoding: "BOM|UTF-8") JSON.parse(raw) rescue Errno::ENOENT raise ManifestError, "vcdeps: no manifest at #{path.tr('/', '\\')}. " \ "Create a vcpkg.json there (see `vcdeps doctor`)." rescue JSON::ParserError => e raise ManifestError, "vcdeps: #{File.basename(path)} is not valid JSON: " \ "#{e.}" end |
.sort_value(value) ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/vcdeps/manifest.rb', line 87 def sort_value(value) case value when Hash value.keys.sort.each_with_object({}) do |k, h| h[k] = sort_value(value[k]) end when Array value.map { |v| sort_value(v) } else value end end |