|
15 | 15 | // with this program; if not, write to the Free Software Foundation, Inc.,
|
16 | 16 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
17 | 17 |
|
| 18 | +#[cfg(not(feature = "demo_mode"))] |
| 19 | +use std::convert::TryFrom; |
18 | 20 | use std::fs::{read_dir, read_to_string, DirEntry};
|
19 | 21 | use std::os::unix::ffi::OsStrExt;
|
20 | 22 | use std::path::Path;
|
@@ -64,6 +66,34 @@ pub struct ChannelFile {
|
64 | 66 | pub polling_interval: Option<String>,
|
65 | 67 | }
|
66 | 68 |
|
| 69 | +#[cfg(not(feature = "demo_mode"))] |
| 70 | +fn zvariant_walk_nested_dicts<'a, T>(map: &'a zvariant::Dict, path: &'a [&'a str]) -> Result<&'a T> |
| 71 | +where |
| 72 | + &'a T: TryFrom<&'a zvariant::Value<'a>>, |
| 73 | + <&'a T as TryFrom<&'a zvariant::Value<'a>>>::Error: Into<zvariant::Error>, |
| 74 | +{ |
| 75 | + let (key, rem) = path |
| 76 | + .split_first() |
| 77 | + .ok_or_else(|| anyhow!("Got an empty path to walk"))?; |
| 78 | + |
| 79 | + let value: &zvariant::Value = map |
| 80 | + .get(key)? |
| 81 | + .ok_or_else(|| anyhow!("Could not find key \"{key}\" in dict"))?; |
| 82 | + |
| 83 | + if rem.is_empty() { |
| 84 | + value.downcast_ref().map_err(|e| { |
| 85 | + let type_name = std::any::type_name::<T>(); |
| 86 | + anyhow!("Failed to convert value in dictionary for key \"{key}\" to {type_name}: {e}") |
| 87 | + }) |
| 88 | + } else { |
| 89 | + let value = value.downcast_ref().map_err(|e| { |
| 90 | + anyhow!("Failed to convert value in dictionary for key \"{key}\" to a dict: {e}") |
| 91 | + })?; |
| 92 | + |
| 93 | + zvariant_walk_nested_dicts(value, rem) |
| 94 | + } |
| 95 | +} |
| 96 | + |
67 | 97 | impl Channel {
|
68 | 98 | fn from_file(path: &Path) -> Result<Self> {
|
69 | 99 | let file_name = || {
|
@@ -177,4 +207,40 @@ impl Channels {
|
177 | 207 | pub(super) fn primary(&self) -> Option<&Channel> {
|
178 | 208 | self.0.iter().find(|ch| ch.primary)
|
179 | 209 | }
|
| 210 | + |
| 211 | + #[cfg(not(feature = "demo_mode"))] |
| 212 | + fn primary_mut(&mut self) -> Option<&mut Channel> { |
| 213 | + self.0.iter_mut().find(|ch| ch.primary) |
| 214 | + } |
| 215 | + |
| 216 | + #[cfg(not(feature = "demo_mode"))] |
| 217 | + pub(super) fn update_from_poll_status(&mut self, poll_status: zvariant::Dict) -> Result<bool> { |
| 218 | + let compatible: &zvariant::Str = |
| 219 | + zvariant_walk_nested_dicts(&poll_status, &["manifest", "update", "compatible"])?; |
| 220 | + let version: &zvariant::Str = |
| 221 | + zvariant_walk_nested_dicts(&poll_status, &["manifest", "update", "version"])?; |
| 222 | + let newer_than_installed: &bool = |
| 223 | + zvariant_walk_nested_dicts(&poll_status, &["update-available"])?; |
| 224 | + |
| 225 | + if let Some(pb) = self.0.iter().find_map(|ch| ch.bundle.as_ref()) { |
| 226 | + if compatible == pb.compatible.as_str() |
| 227 | + && version == pb.version.as_str() |
| 228 | + && *newer_than_installed == pb.newer_than_installed |
| 229 | + { |
| 230 | + return Ok(false); |
| 231 | + } |
| 232 | + } |
| 233 | + |
| 234 | + self.0.iter_mut().for_each(|ch| ch.bundle = None); |
| 235 | + |
| 236 | + if let Some(primary) = self.primary_mut() { |
| 237 | + primary.bundle = Some(UpstreamBundle { |
| 238 | + compatible: compatible.as_str().into(), |
| 239 | + version: version.as_str().into(), |
| 240 | + newer_than_installed: *newer_than_installed, |
| 241 | + }); |
| 242 | + } |
| 243 | + |
| 244 | + Ok(true) |
| 245 | + } |
180 | 246 | }
|
0 commit comments