@@ -5,7 +5,7 @@ defmodule Mix.Tasks.Firmware.Patch do
5
5
Generate a firmware patch from a source and target firmware and output a new
6
6
firmware file with the patch contents. The source firmware file
7
7
8
- This requires fwup >= 1.6 .0
8
+ This requires fwup >= 1.10 .0
9
9
10
10
## Command line options
11
11
@@ -21,7 +21,7 @@ defmodule Mix.Tasks.Firmware.Patch do
21
21
alias Mix.Nerves.Preflight
22
22
alias Nerves.Utils.Shell
23
23
24
- @ fwup_semver "~> 1.6 or ~> 1.6.0-dev "
24
+ @ fwup_semver ">= 1.10.0 "
25
25
26
26
@ switches [ source: :string , target: :string , output: :string ]
27
27
@@ -56,27 +56,7 @@ defmodule Mix.Tasks.Firmware.Patch do
56
56
57
57
target_stats = File . stat! ( target )
58
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! ( Path . join ( output_work_dir , "data" ) )
66
-
67
- { _ , 0 } = shell ( "unzip" , [ "-qq" , source , "-d" , source_work_dir ] )
68
- { _ , 0 } = shell ( "unzip" , [ "-qq" , target , "-d" , target_work_dir ] )
69
-
70
- source_rootfs = Path . join ( [ source_work_dir , "data" , "rootfs.img" ] )
71
- target_rootfs = Path . join ( [ target_work_dir , "data" , "rootfs.img" ] )
72
- out_rootfs = Path . join ( [ output_work_dir , "data" , "rootfs.img" ] )
73
-
74
- { _ , 0 } = shell ( "xdelta3" , [ "-A" , "-S" , "-f" , "-s" , source_rootfs , target_rootfs , out_rootfs ] )
75
-
76
- File . mkdir_p! ( Path . dirname ( output ) )
77
- File . cp! ( target , output )
78
-
79
- { _ , 0 } = shell ( "zip" , [ "-qq" , output , "data/rootfs.img" ] , cd: output_work_dir )
59
+ _ = create ( source , target , output , work_dir )
80
60
81
61
output_stats = File . stat! ( output )
82
62
@@ -117,4 +97,80 @@ defmodule Mix.Tasks.Firmware.Patch do
117
97
Mix.Tasks.Firmware . run ( [ "--output" , out_fw ] )
118
98
out_fw
119
99
end
100
+
101
+ defp create ( source_path , target_path , output_path , work_dir ) do
102
+ source_work_dir = Path . join ( work_dir , "source" )
103
+ target_work_dir = Path . join ( work_dir , "target" )
104
+ output_work_dir = Path . join ( work_dir , "output" )
105
+
106
+ _ = File . mkdir_p ( source_work_dir )
107
+ _ = File . mkdir_p ( target_work_dir )
108
+ _ = File . mkdir_p ( output_work_dir )
109
+
110
+ { _ , 0 } = shell ( "unzip" , [ "-qq" , source_path , "-d" , source_work_dir ] )
111
+ { _ , 0 } = shell ( "unzip" , [ "-qq" , target_path , "-d" , target_work_dir ] )
112
+
113
+ for path <- Path . wildcard ( target_work_dir <> "/**" ) do
114
+ path = Regex . replace ( ~r/ ^#{ target_work_dir } \/ / , path , "" )
115
+
116
+ unless File . dir? ( Path . join ( target_work_dir , path ) ) do
117
+ :ok = handle_content ( path , source_work_dir , target_work_dir , output_work_dir )
118
+ end
119
+ end
120
+
121
+ # firmware archive files order matters:
122
+ # 1. meta.conf.ed25519 (optional)
123
+ # 2. meta.conf
124
+ # 3. other...
125
+ [
126
+ "meta.conf.*" ,
127
+ "meta.conf" ,
128
+ "data"
129
+ ]
130
+ |> Enum . each ( & add_to_zip ( & 1 , output_work_dir , output_path ) )
131
+
132
+ output_path
133
+ end
134
+
135
+ defp handle_content ( "meta." <> _ = path , _source_dir , target_dir , out_dir ) do
136
+ do_copy ( Path . join ( target_dir , path ) , Path . join ( out_dir , path ) )
137
+ end
138
+
139
+ defp handle_content ( path , source_dir , target_dir , out_dir ) do
140
+ do_delta ( Path . join ( source_dir , path ) , Path . join ( target_dir , path ) , Path . join ( out_dir , path ) )
141
+ end
142
+
143
+ defp do_copy ( source , target ) do
144
+ target |> Path . dirname ( ) |> File . mkdir_p! ( )
145
+ File . cp ( source , target )
146
+ end
147
+
148
+ defp do_delta ( source , target , out ) do
149
+ out |> Path . dirname ( ) |> File . mkdir_p! ( )
150
+
151
+ case shell ( "xdelta3" , [ "-A" , "-S" , "-f" , "-s" , source , target , out ] ) do
152
+ { _ , 0 } -> :ok
153
+ { _ , code } -> { :error , code }
154
+ end
155
+ end
156
+
157
+ defp add_to_zip ( glob , workdir , output ) do
158
+ workdir
159
+ |> Path . join ( glob )
160
+ |> Path . wildcard ( )
161
+ |> case do
162
+ [ ] ->
163
+ :ok
164
+
165
+ paths ->
166
+ { _ , 0 } =
167
+ System . cmd (
168
+ "zip" ,
169
+ [ "-r" , "-qq" , output | Enum . map ( paths , & Path . relative_to ( & 1 , workdir ) ) ] ,
170
+ cd: workdir
171
+ )
172
+
173
+ :ok
174
+ end
175
+ end
120
176
end
0 commit comments