Skip to content

Commit ef9f458

Browse files
feat: storage service (#2816)
Add storage service to support the new HTTP API. The D-Bus API is adapted to provide the required information, using D-Bus as a transport layer.
2 parents 973191e + 034bece commit ef9f458

File tree

151 files changed

+4423
-8347
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

151 files changed

+4423
-8347
lines changed

rust/Cargo.lock

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ members = [
77
"agama-locale-data",
88
"agama-manager",
99
"agama-network",
10-
"agama-server",
10+
"agama-server", "agama-storage",
1111
"agama-utils",
1212
"xtask",
1313
]

rust/agama-l10n/src/message.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,23 @@ impl Message for GetConfig {
5555
}
5656

5757
pub struct SetConfig<T> {
58-
pub config: T,
58+
pub config: Option<T>,
5959
}
6060

6161
impl<T: Send + 'static> Message for SetConfig<T> {
6262
type Reply = ();
6363
}
6464

6565
impl<T> SetConfig<T> {
66-
pub fn new(config: T) -> Self {
66+
pub fn new(config: Option<T>) -> Self {
6767
Self { config }
6868
}
69+
70+
pub fn with(config: T) -> Self {
71+
Self {
72+
config: Some(config),
73+
}
74+
}
6975
}
7076

7177
pub struct GetProposal;

rust/agama-l10n/src/service.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ impl Service {
123123
details: None,
124124
source: IssueSource::Config,
125125
severity: IssueSeverity::Error,
126-
kind: "unknown_locale".to_string(),
126+
class: "unknown_locale".to_string(),
127127
});
128128
}
129129

@@ -133,7 +133,7 @@ impl Service {
133133
details: None,
134134
source: IssueSource::Config,
135135
severity: IssueSeverity::Error,
136-
kind: "unknown_keymap".to_string(),
136+
class: "unknown_keymap".to_string(),
137137
});
138138
}
139139

@@ -143,7 +143,7 @@ impl Service {
143143
details: None,
144144
source: IssueSource::Config,
145145
severity: IssueSeverity::Error,
146-
kind: "unknown_timezone".to_string(),
146+
class: "unknown_timezone".to_string(),
147147
});
148148
}
149149

@@ -195,16 +195,22 @@ impl MessageHandler<message::SetConfig<api::l10n::Config>> for Service {
195195
&mut self,
196196
message: message::SetConfig<api::l10n::Config>,
197197
) -> Result<(), Error> {
198-
let config = Config::new_from(&self.system);
199-
let merged = config.merge(&message.config)?;
200-
if merged == self.config {
198+
let base_config = Config::new_from(&self.system);
199+
200+
let config = if let Some(config) = &message.config {
201+
base_config.merge(config)?
202+
} else {
203+
base_config
204+
};
205+
206+
if config == self.config {
201207
return Ok(());
202208
}
203209

204-
self.config = merged;
210+
self.config = config;
205211
let issues = self.find_issues();
206212
self.issues
207-
.cast(issue::message::Update::new(Scope::L10n, issues))?;
213+
.cast(issue::message::Set::new(Scope::L10n, issues))?;
208214
self.events
209215
.send(Event::ProposalChanged { scope: Scope::L10n })?;
210216
Ok(())

rust/agama-l10n/src/start.rs

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,16 @@ mod tests {
7171
use crate::model::{KeymapsDatabase, LocalesDatabase, ModelAdapter, TimezonesDatabase};
7272
use crate::service::{self, Service};
7373
use agama_locale_data::{KeymapId, LocaleId};
74-
use agama_utils::actor::{self, Handler};
75-
use agama_utils::api;
76-
use agama_utils::api::event::{self, Event};
77-
use agama_utils::api::l10n::{Keymap, LocaleEntry, TimezoneEntry};
78-
use agama_utils::api::scope::Scope;
79-
use agama_utils::issue;
74+
use agama_utils::{
75+
actor::{self, Handler},
76+
api::{
77+
self,
78+
event::{self, Event},
79+
l10n::{Keymap, LocaleEntry, TimezoneEntry},
80+
scope::Scope,
81+
},
82+
issue, test,
83+
};
8084
use tokio::sync::broadcast;
8185

8286
pub struct TestModel {
@@ -145,7 +149,8 @@ mod tests {
145149
async fn start_testing_service() -> (event::Receiver, Handler<Service>, Handler<issue::Service>)
146150
{
147151
let (events_tx, events_rx) = broadcast::channel::<Event>(16);
148-
let issues = issue::start(events_tx.clone(), None).await.unwrap();
152+
let dbus = test::dbus::connection().await.unwrap();
153+
let issues = issue::start(events_tx.clone(), dbus).await.unwrap();
149154

150155
let model = build_adapter();
151156
let service = Service::new(model, issues.clone(), events_tx);
@@ -167,7 +172,7 @@ mod tests {
167172
timezone: Some("Atlantic/Canary".to_string()),
168173
};
169174
handler
170-
.call(message::SetConfig::new(input_config.clone()))
175+
.call(message::SetConfig::with(input_config.clone()))
171176
.await?;
172177

173178
let updated = handler.call(message::GetConfig).await?;
@@ -190,7 +195,7 @@ mod tests {
190195

191196
// Use system info for missing values.
192197
handler
193-
.call(message::SetConfig::new(input_config.clone()))
198+
.call(message::SetConfig::with(input_config.clone()))
194199
.await?;
195200

196201
let updated = handler.call(message::GetConfig).await?;
@@ -206,6 +211,25 @@ mod tests {
206211
Ok(())
207212
}
208213

214+
#[tokio::test]
215+
async fn test_reset_config() -> Result<(), Box<dyn std::error::Error>> {
216+
let (mut _events_rx, handler, _issues) = start_testing_service().await;
217+
218+
handler.call(message::SetConfig::new(None)).await?;
219+
220+
let config = handler.call(message::GetConfig).await?;
221+
assert_eq!(
222+
config,
223+
api::l10n::Config {
224+
locale: Some("en_US.UTF-8".to_string()),
225+
keymap: Some("us".to_string()),
226+
timezone: Some("Europe/Berlin".to_string()),
227+
}
228+
);
229+
230+
Ok(())
231+
}
232+
209233
#[tokio::test]
210234
async fn test_set_invalid_config() -> Result<(), Box<dyn std::error::Error>> {
211235
let (_events_rx, handler, _issues) = start_testing_service().await;
@@ -216,7 +240,7 @@ mod tests {
216240
};
217241

218242
let result = handler
219-
.call(message::SetConfig::new(input_config.clone()))
243+
.call(message::SetConfig::with(input_config.clone()))
220244
.await;
221245
assert!(matches!(result, Err(service::Error::InvalidLocale(_))));
222246
Ok(())
@@ -228,7 +252,7 @@ mod tests {
228252

229253
let config = handler.call(message::GetConfig).await?;
230254
assert_eq!(config.locale, Some("en_US.UTF-8".to_string()));
231-
let message = message::SetConfig::new(config.clone());
255+
let message = message::SetConfig::with(config.clone());
232256
handler.call(message).await?;
233257
// Wait until the action is dispatched.
234258
let _ = handler.call(message::GetConfig).await?;
@@ -247,7 +271,7 @@ mod tests {
247271
locale: Some("xx_XX.UTF-8".to_string()),
248272
timezone: Some("Unknown/Unknown".to_string()),
249273
};
250-
let _ = handler.call(message::SetConfig::new(config)).await?;
274+
let _ = handler.call(message::SetConfig::with(config)).await?;
251275

252276
let found_issues = issues.call(issue::message::Get).await?;
253277
let l10n_issues = found_issues.get(&Scope::L10n).unwrap();
@@ -277,7 +301,7 @@ mod tests {
277301
keymap: Some("es".to_string()),
278302
timezone: Some("Atlantic/Canary".to_string()),
279303
};
280-
let message = message::SetConfig::new(input_config.clone());
304+
let message = message::SetConfig::with(input_config.clone());
281305
handler.call(message).await?;
282306

283307
let proposal = handler

rust/agama-lib/share/examples/profile_tw.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"localization": {
33
"keyboard": "es",
44
"language": "es_ES.UTF-8",
5-
"keymap": "es_ES.UTF-8"
5+
"timezone": "Europe/Berlin"
66
},
77
"software": {
88
"patterns": ["gnome"],

rust/agama-lib/share/profile.schema.json

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -766,9 +766,33 @@
766766
}
767767
}
768768
},
769-
"localization": {
769+
"l10n": {
770770
"title": "Localization settings",
771771
"type": "object",
772+
"additionalProperties": false,
773+
"properties": {
774+
"locale": {
775+
"title": "Locale ID",
776+
"type": "string",
777+
"examples": ["en_US.UTF-8", "en_US"]
778+
},
779+
"keymap": {
780+
"title": "Keymap ID",
781+
"type": "string",
782+
"examples": ["us", "en", "es"]
783+
},
784+
"timezone": {
785+
"title": "Time zone ID",
786+
"type": "string",
787+
"examples": ["Europe/Berlin"]
788+
}
789+
}
790+
},
791+
"localization": {
792+
"deprecated": true,
793+
"title": "Localization settings (old schema)",
794+
"type": "object",
795+
"additionalProperties": false,
772796
"properties": {
773797
"language": {
774798
"title": "System language ID",

rust/agama-lib/src/questions/http_client.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
use std::time::Duration;
2222

2323
use agama_utils::api::{
24-
config::Patch,
24+
patch::{self, Patch},
2525
question::{
2626
Answer, AnswerRule, Config as QuestionsConfig, Policy, Question, QuestionSpec,
2727
UpdateQuestion,
@@ -38,6 +38,8 @@ pub enum QuestionsHTTPClientError {
3838
HTTP(#[from] BaseHTTPClientError),
3939
#[error("Unknown question with ID {0}")]
4040
UnknownQuestion(u32),
41+
#[error(transparent)]
42+
Patch(#[from] patch::Error),
4143
}
4244

4345
pub struct HTTPClient {
@@ -99,9 +101,7 @@ impl HTTPClient {
99101
..Default::default()
100102
};
101103

102-
let patch = Patch {
103-
update: Some(config),
104-
};
104+
let patch = Patch::with_update(&config)?;
105105

106106
_ = self.client.patch_void("/v2/config", &patch).await?;
107107
Ok(())
@@ -120,9 +120,7 @@ impl HTTPClient {
120120
..Default::default()
121121
};
122122

123-
let patch = Patch {
124-
update: Some(config),
125-
};
123+
let patch = Patch::with_update(&config)?;
126124
self.client.patch_void("/v2/config", &patch).await?;
127125
Ok(())
128126
}

rust/agama-manager/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ edition.workspace = true
77
[dependencies]
88
agama-utils = { path = "../agama-utils" }
99
agama-l10n = { path = "../agama-l10n" }
10+
agama-storage = { path = "../agama-storage" }
1011
thiserror = "2.0.12"
1112
tokio = { version = "1.40.0", features = ["macros", "rt-multi-thread", "sync"] }
1213
async-trait = "0.1.83"
1314
zbus = { version = "5", default-features = false, features = ["tokio"] }
1415
merge-struct = "0.1.0"
16+
serde_json = "1.0.140"
1517

1618
[dev-dependencies]
1719
tokio-test = "0.4.4"

rust/agama-manager/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@ pub use service::Service;
2727
pub mod message;
2828

2929
pub use agama_l10n as l10n;
30+
pub use agama_storage as storage;

0 commit comments

Comments
 (0)