Skip to content
Merged
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
9 changes: 6 additions & 3 deletions Library/Homebrew/api/cask_struct.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,15 @@ def serialize
[prop.to_s, send(prop)]
end.to_h

hash["raw_artifacts"] = raw_artifacts.map do |artifact|
hash["raw_artifacts"] = ::Utils.deep_compact_blank(raw_artifacts.map do |artifact|
serialize_artifact_args(artifact)
end
end, compact_zero: false)

hash = ::Utils.deep_stringify_symbols(hash)
::Utils.deep_compact_blank(hash)
raw_artifacts = hash["raw_artifacts"]
hash = ::Utils.deep_compact_blank(hash)
hash["raw_artifacts"] = raw_artifacts if raw_artifacts.present?
hash
end

sig { params(hash: T::Hash[String, T.untyped]).returns(CaskStruct) }
Expand Down
26 changes: 26 additions & 0 deletions Library/Homebrew/test/api/cask_struct_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,32 @@
.to eq([:preflight, ["foo"], { bar: "baz" }, nil])
end

it "preserves zero values in serialized artifact arguments" do
struct = klass.new(
sha256: "abc123",
version: "1.0.0",
ruby_source_checksum: { sha256: "def456" },
raw_artifacts: [
[
:pkg,
["Test.pkg"],
{ choices: [{ choiceIdentifier: "choice1", choiceAttribute: "selected", attributeSetting: 0 }] },
nil,
],
],
)

expect(struct.serialize.fetch("raw_artifacts"))
.to eq([
[
":pkg",
["Test.pkg"],
{ ":choices" => [{ ":choiceIdentifier" => "choice1", ":choiceAttribute" => "selected",
":attributeSetting" => 0 }] },
],
])
end

specify "::deserialize_artifact_args", :aggregate_failures do
expect(klass.deserialize_artifact_args([:foo]))
.to eq([:foo, [], {}, nil])
Expand Down
10 changes: 5 additions & 5 deletions Library/Homebrew/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -185,21 +185,21 @@ def self.deep_unstringify_symbols(obj)

sig {
type_parameters(:U)
.params(obj: T.all(T.type_parameter(:U), Object))
.params(obj: T.all(T.type_parameter(:U), Object), compact_zero: T::Boolean)
.returns(T.nilable(T.type_parameter(:U)))
}
def self.deep_compact_blank(obj)
def self.deep_compact_blank(obj, compact_zero: true)
obj = case obj
when Hash
obj.transform_values { |v| deep_compact_blank(v) }
obj.transform_values { |v| deep_compact_blank(v, compact_zero:) }
.compact
when Array
obj.filter_map { |v| deep_compact_blank(v) }
obj.filter_map { |v| deep_compact_blank(v, compact_zero:) }
else
obj
end

return if obj.blank? || (obj.is_a?(Numeric) && obj.zero?)
return if obj.blank? || (compact_zero && obj.is_a?(Numeric) && obj.zero?)

obj
end
Expand Down
Loading