iced_devtools/
comet.rs
1use crate::executor;
2use crate::runtime::Task;
3
4use std::process;
5
6pub const COMPATIBLE_REVISION: &str =
7 "20f9c9a897fecac5dce0977bbb5639fdce1f54b9";
8
9pub fn launch() -> Task<launch::Result> {
10 executor::try_spawn_blocking(|mut sender| {
11 let cargo_install = process::Command::new("cargo")
12 .args(["install", "--list"])
13 .output()?;
14
15 let installed_packages = String::from_utf8_lossy(&cargo_install.stdout);
16
17 for line in installed_packages.lines() {
18 if !line.starts_with("iced_comet ") {
19 continue;
20 }
21
22 let Some((_, revision)) = line.rsplit_once("?rev=") else {
23 return Err(launch::Error::Outdated { revision: None });
24 };
25
26 let Some((revision, _)) = revision.rsplit_once("#") else {
27 return Err(launch::Error::Outdated { revision: None });
28 };
29
30 if revision != COMPATIBLE_REVISION {
31 return Err(launch::Error::Outdated {
32 revision: Some(revision.to_owned()),
33 });
34 }
35
36 let _ = process::Command::new("iced_comet")
37 .stdin(process::Stdio::null())
38 .stdout(process::Stdio::null())
39 .stderr(process::Stdio::null())
40 .spawn()?;
41
42 let _ = sender.try_send(());
43 return Ok(());
44 }
45
46 Err(launch::Error::NotFound)
47 })
48}
49
50pub fn install() -> Task<install::Result> {
51 executor::try_spawn_blocking(|mut sender| {
52 use std::io::{BufRead, BufReader};
53 use std::process::{Command, Stdio};
54
55 let mut install = Command::new("cargo")
56 .args([
57 "install",
58 "--locked",
59 "--git",
60 "https://github.com/iced-rs/comet.git",
61 "--rev",
62 COMPATIBLE_REVISION,
63 ])
64 .stdin(Stdio::null())
65 .stdout(Stdio::null())
66 .stderr(Stdio::piped())
67 .spawn()?;
68
69 let mut stderr = BufReader::new(
70 install.stderr.take().expect("stderr must be piped"),
71 );
72
73 let mut log = String::new();
74
75 while let Ok(n) = stderr.read_line(&mut log) {
76 if n == 0 {
77 let status = install.wait()?;
78
79 if status.success() {
80 break;
81 } else {
82 return Err(install::Error::ProcessFailed(status));
83 }
84 }
85
86 let _ = sender.try_send(install::Event::Logged(log.clone()));
87 log.clear();
88 }
89
90 let _ = sender.try_send(install::Event::Finished);
91
92 Ok(())
93 })
94}
95
96pub mod launch {
97 use std::io;
98 use std::sync::Arc;
99
100 pub type Result = std::result::Result<(), Error>;
101
102 #[derive(Debug, Clone)]
103 pub enum Error {
104 NotFound,
105 Outdated { revision: Option<String> },
106 IoFailed(Arc<io::Error>),
107 }
108
109 impl From<io::Error> for Error {
110 fn from(error: io::Error) -> Self {
111 Self::IoFailed(Arc::new(error))
112 }
113 }
114}
115
116pub mod install {
117 use std::io;
118 use std::process;
119 use std::sync::Arc;
120
121 pub type Result = std::result::Result<Event, Error>;
122
123 #[derive(Debug, Clone)]
124 pub enum Event {
125 Logged(String),
126 Finished,
127 }
128
129 #[derive(Debug, Clone)]
130 pub enum Error {
131 ProcessFailed(process::ExitStatus),
132 IoFailed(Arc<io::Error>),
133 }
134
135 impl From<io::Error> for Error {
136 fn from(error: io::Error) -> Self {
137 Self::IoFailed(Arc::new(error))
138 }
139 }
140}