satkit/utils/
update_data.rs1use super::download_file_async;
2use super::download_to_string;
3use crate::utils::datadir;
4use json::JsonValue;
5use std::path::PathBuf;
6use std::thread::JoinHandle;
7
8use anyhow::{bail, Result};
9
10fn download_from_url_json(json_url: String, basedir: &std::path::Path) -> Result<()> {
12 let json_base: JsonValue = json::parse(download_to_string(json_url.as_str())?.as_str())?;
13 let vresult: Vec<std::thread::JoinHandle<Result<bool>>> = json_base
14 .members()
15 .map(|url| -> JoinHandle<Result<bool>> {
16 download_file_async(url.to_string(), basedir, true)
17 })
18 .collect();
19 for jh in vresult {
21 jh.join().unwrap()?;
22 }
23
24 Ok(())
25}
26
27fn download_from_json(
29 v: &JsonValue,
30 basedir: std::path::PathBuf,
31 baseurl: String,
32 overwrite: &bool,
33 thandles: &mut Vec<JoinHandle<Result<bool>>>,
34) -> Result<()> {
35 if v.is_object() {
36 let r1: Vec<Result<()>> = v
37 .entries()
38 .map(|entry: (&str, &JsonValue)| -> Result<()> {
39 let pbnew = basedir.join(entry.0);
40 if !pbnew.is_dir() {
41 std::fs::create_dir_all(pbnew.clone())?;
42 }
43 let mut newurl = baseurl.clone();
44 newurl.push_str(format!("/{}", entry.0).as_str());
45 download_from_json(entry.1, pbnew, newurl, overwrite, thandles)?;
46 Ok(())
47 })
48 .filter(|res| res.is_err())
49 .collect();
50 if !r1.is_empty() {
51 bail!("Could not parse entries");
52 }
53 } else if v.is_array() {
54 let r2: Vec<Result<()>> = v
55 .members()
56 .map(|val| -> Result<()> {
57 download_from_json(val, basedir.clone(), baseurl.clone(), overwrite, thandles)?;
58 Ok(())
59 })
60 .filter(|res| res.is_err())
61 .collect();
62 if !r2.is_empty() {
63 bail!("could not parse array entries");
64 }
65 } else if v.is_string() {
66 let mut newurl = baseurl;
67 newurl.push_str(format!("/{}", v).as_str());
68 thandles.push(download_file_async(newurl, &basedir, *overwrite));
69 } else {
70 bail!("invalid json for downloading files??!!");
71 }
72
73 Ok(())
74}
75
76fn download_datadir(basedir: PathBuf, baseurl: String, overwrite: &bool) -> Result<()> {
77 if !basedir.is_dir() {
78 std::fs::create_dir_all(basedir.clone())?;
79 }
80
81 let mut fileurl = baseurl.clone();
82 fileurl.push_str("/files.json");
83
84 let json_base: JsonValue = json::parse(download_to_string(fileurl.as_str())?.as_str())?;
85 let mut thandles: Vec<JoinHandle<Result<bool>>> = Vec::new();
86 download_from_json(&json_base, basedir, baseurl, overwrite, &mut thandles)?;
87 for jh in thandles {
89 jh.join().unwrap()?;
90 }
91 Ok(())
92}
93
94pub fn update_datafiles(dir: Option<PathBuf>, overwrite_if_exists: bool) -> Result<()> {
114 let downloaddir = match dir {
115 Some(d) => d,
116 None => datadir()?,
117 };
118 if downloaddir.metadata()?.permissions().readonly() {
119 bail!(
120 r#"
121 Data directory is read-only.
122 Try setting SATKIT_DATA environment
123 variable to a writeable directory and re-starting
124 "#
125 );
126 }
127
128 println!(
129 "Downloading data files to {}",
130 downloaddir.to_str().unwrap()
131 );
132 download_datadir(
134 downloaddir.clone(),
135 String::from("https://storage.googleapis.com/astrokit-astro-data"),
136 &overwrite_if_exists,
137 )?;
138
139 println!("Now downloading files that are regularly updated:");
140 println!(" Space Weather & Earth Orientation Parameters");
141 download_from_url_json(
143 String::from("https://storage.googleapis.com/astrokit-astro-data/files_refresh.json"),
144 &downloaddir,
145 )?;
146 Ok(())
147}