Skip to content

Commit 14e8dc7

Browse files
committed
Default delta updater can delta non-block resources
Replicating #886 for v2.0 See also #885
1 parent 3d99a9b commit 14e8dc7

File tree

3 files changed

+72
-27
lines changed

3 files changed

+72
-27
lines changed

lib/nerves_hub/devices.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ defmodule NervesHub.Devices do
2323
alias NervesHub.Repo
2424
alias NervesHub.TaskSupervisor, as: Tasks
2525

26-
@min_fwup_delta_updatable_version ">=1.6.0"
26+
@min_fwup_delta_updatable_version ">=1.10.0"
2727

2828
def get_device(device_id), do: Repo.get(Device, device_id)
2929
def get_device!(device_id), do: Repo.get!(Device, device_id)

lib/nerves_hub/firmwares/delta_updater/default.ex

Lines changed: 70 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,31 +31,9 @@ defmodule NervesHub.Firmwares.DeltaUpdater.Default do
3131
)
3232

3333
output_filename = uuid <> ".fw"
34-
output = Path.join(work_dir, output_filename) |> Path.expand()
34+
output_path = Path.join(work_dir, output_filename) |> Path.expand()
3535

36-
source_work_dir = Path.join(work_dir, "source")
37-
target_work_dir = Path.join(work_dir, "target")
38-
output_work_dir = Path.join(work_dir, "output")
39-
40-
File.mkdir_p(source_work_dir)
41-
File.mkdir_p(target_work_dir)
42-
File.mkdir_p(Path.join(output_work_dir, "data"))
43-
44-
{_, 0} = System.cmd("unzip", ["-qq", source_path, "-d", source_work_dir])
45-
{_, 0} = System.cmd("unzip", ["-qq", target_path, "-d", target_work_dir])
46-
47-
source_rootfs = Path.join([source_work_dir, "data", "rootfs.img"])
48-
target_rootfs = Path.join([target_work_dir, "data", "rootfs.img"])
49-
out_rootfs = Path.join([output_work_dir, "data", "rootfs.img"])
50-
51-
{_, 0} =
52-
System.cmd("xdelta3", ["-A", "-S", "-f", "-s", source_rootfs, target_rootfs, out_rootfs])
53-
54-
File.mkdir_p!(Path.dirname(output))
55-
File.cp!(target_path, output)
56-
57-
{_, 0} = System.cmd("zip", ["-qq", output, "data/rootfs.img"], cd: output_work_dir)
58-
output
36+
do_delta_file(source_path, target_path, output_path, work_dir)
5937
end
6038

6139
@impl NervesHub.Firmwares.DeltaUpdater
@@ -70,6 +48,73 @@ defmodule NervesHub.Firmwares.DeltaUpdater.Default do
7048
@impl NervesHub.Firmwares.DeltaUpdater
7149
def delta_updatable?(file_path) do
7250
{meta, 0} = System.cmd("unzip", ["-qqp", file_path, "meta.conf"])
73-
meta =~ "delta-source-raw-offset" && meta =~ "delta-source-raw-count"
51+
52+
(meta =~ "delta-source-raw-offset" && meta =~ "delta-source-raw-count") or
53+
(meta =~ "delta-source-fat-offset" && meta =~ "delta-source-fat-path")
54+
end
55+
56+
def do_delta_file(source_path, target_path, output_path, work_dir) do
57+
File.mkdir_p(work_dir)
58+
59+
source_work_dir = Path.join(work_dir, "source")
60+
target_work_dir = Path.join(work_dir, "target")
61+
output_work_dir = Path.join(work_dir, "output")
62+
63+
File.mkdir_p(source_work_dir)
64+
File.mkdir_p(target_work_dir)
65+
File.mkdir_p(output_work_dir)
66+
67+
{_, 0} = System.cmd("unzip", ["-qq", source_path, "-d", source_work_dir])
68+
{_, 0} = System.cmd("unzip", ["-qq", target_path, "-d", target_work_dir])
69+
70+
_ =
71+
for absolute <- Path.wildcard(target_work_dir <> "/**"), not File.dir?(absolute) do
72+
path = Path.relative_to(absolute, target_work_dir)
73+
74+
if String.starts_with?(path, "meta.") do
75+
File.cp!(Path.join(target_work_dir, path), Path.join(output_work_dir, path))
76+
else
77+
args = [
78+
"-A",
79+
"-S",
80+
"-f",
81+
"-s",
82+
Path.join(source_work_dir, path),
83+
Path.join(target_work_dir, path),
84+
Path.join(output_work_dir, path)
85+
]
86+
87+
{_, 0} = System.cmd("xdelta3", args)
88+
end
89+
end
90+
91+
# firmware archive files order matters:
92+
# 1. meta.conf.ed25519 (optional)
93+
# 2. meta.conf
94+
# 3. other...
95+
[
96+
"meta.conf.*",
97+
"meta.conf",
98+
"data"
99+
]
100+
|> Enum.each(&add_to_zip(&1, output_work_dir, output_path))
101+
102+
output_path
103+
end
104+
105+
defp add_to_zip(glob, workdir, output) do
106+
workdir
107+
|> Path.join(glob)
108+
|> Path.wildcard()
109+
|> case do
110+
[] ->
111+
:ok
112+
113+
paths ->
114+
args = ["-r", "-qq", output | Enum.map(paths, &Path.relative_to(&1, workdir))]
115+
{_, 0} = System.cmd("zip", args, cd: workdir)
116+
117+
:ok
118+
end
74119
end
75120
end

test/nerves_hub/devices_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ defmodule NervesHub.DevicesTest do
1111
alias NervesHub.Repo
1212
alias Ecto.Changeset
1313

14-
@valid_fwup_version "1.6.0"
14+
@valid_fwup_version "1.10.0"
1515

1616
setup do
1717
user = Fixtures.user_fixture()

0 commit comments

Comments
 (0)