@@ -5,8 +5,9 @@ use directories::ProjectDirs;
55use error_stack:: ResultExt ;
66use serde:: { Deserialize , Serialize } ;
77use std:: path:: PathBuf ;
8+ use std:: str:: FromStr ;
89use std:: sync:: LazyLock ;
9- use tracing :: { debug , trace } ;
10+ use toml :: de :: Error ;
1011
1112pub static PROJECT_DIRS : LazyLock < ProjectDirs > = LazyLock :: new ( || {
1213 ProjectDirs :: from ( "net" , "octyl" , "jpre" ) . expect ( "Could not determine project directories" )
@@ -54,12 +55,7 @@ impl JpreConfig {
5455 . attach_printable_lazy ( || {
5556 format ! ( "Could not open config file at {:?}" , * CONFIG_PATH )
5657 } ) ?;
57- let contents = std:: fs:: read_to_string ( & * CONFIG_PATH )
58- . change_context ( JpreError :: Unexpected )
59- . attach_printable_lazy ( || {
60- format ! ( "Could not read config file at {:?}" , * CONFIG_PATH )
61- } ) ?;
62- let config = toml:: from_str :: < JpreConfig > ( & contents) ;
58+ let ( contents, config) = Self :: read_config ( ) ?;
6359 match config {
6460 Ok ( mut config) => {
6561 if let Some ( distribution) = config. distribution {
@@ -90,19 +86,35 @@ impl JpreConfig {
9086 format ! ( "Could not parse config file at {:?}" , * CONFIG_PATH )
9187 } ) ;
9288 }
93- // jpre 0.2 config format
94- let new_config = JpreConfig {
95- default_jdk : Some ( VersionKey {
89+
90+ let mut new_config = toml_edit:: DocumentMut :: new ( ) ;
91+ new_config[ "default_jdk" ] = toml_edit:: value (
92+ VersionKey {
9693 major : * major as u32 ,
9794 pre_release : PreRelease :: None ,
98- } ) ,
99- distribution : None ,
100- distributions : default_distribution ( ) ,
101- forced_architecture : None ,
102- forced_os : None ,
103- } ;
104- new_config. save ( ) ?;
105- return Ok ( new_config) ;
95+ }
96+ . to_string ( ) ,
97+ ) ;
98+ let mut distributions = toml_edit:: Array :: new ( ) ;
99+ distributions. push ( "temurin" ) ;
100+ new_config[ "distributions" ] = toml_edit:: value ( distributions) ;
101+
102+ // Ensure whatever is in the config is valid.
103+ toml:: from_str :: < JpreConfig > ( & new_config. to_string ( ) )
104+ . expect ( "New config is invalid" ) ;
105+
106+ std:: fs:: write ( & * CONFIG_PATH , new_config. to_string ( ) )
107+ . change_context ( JpreError :: Unexpected )
108+ . attach_printable_lazy ( || {
109+ format ! ( "Could not write config file at {:?}" , * CONFIG_PATH )
110+ } ) ?;
111+
112+ return Self :: read_config ( ) ?
113+ . 1
114+ . change_context ( JpreError :: Unexpected )
115+ . attach_printable_lazy ( || {
116+ format ! ( "Could not parse config file at {:?}" , * CONFIG_PATH )
117+ } ) ;
106118 }
107119 Err ( e)
108120 . change_context ( JpreError :: Unexpected )
@@ -113,16 +125,36 @@ impl JpreConfig {
113125 }
114126 }
115127
116- pub fn save ( & self ) -> ESResult < ( ) , JpreError > {
117- let contents = toml:: to_string ( self )
128+ fn read_config ( ) -> ESResult < ( String , Result < JpreConfig , Error > ) , JpreError > {
129+ let contents = std:: fs:: read_to_string ( & * CONFIG_PATH )
130+ . change_context ( JpreError :: Unexpected )
131+ . attach_printable_lazy ( || {
132+ format ! ( "Could not read config file at {:?}" , * CONFIG_PATH )
133+ } ) ?;
134+ let config = toml:: from_str :: < JpreConfig > ( & contents) ;
135+ Ok ( ( contents, config) )
136+ }
137+
138+ pub fn edit_config < F : FnOnce ( & mut toml_edit:: DocumentMut ) > (
139+ & mut self ,
140+ editor : F ,
141+ ) -> ESResult < ( ) , JpreError > {
142+ let contents = Self :: read_config ( ) ?. 0 ;
143+ let mut config = toml_edit:: DocumentMut :: from_str ( & contents)
118144 . change_context ( JpreError :: Unexpected )
119- . attach_printable ( "Could not serialize config to TOML" ) ?;
120- debug ! ( "Writing config to {:?}" , * CONFIG_PATH ) ;
121- trace ! ( "Config: {}" , contents) ;
122- std:: fs:: write ( & * CONFIG_PATH , contents)
145+ . attach_printable_lazy ( || {
146+ format ! ( "Could not parse config file at {:?}" , * CONFIG_PATH )
147+ } ) ?;
148+ editor ( & mut config) ;
149+
150+ // Ensure whatever is in the config is valid, and update ourselves to it.
151+ * self = toml:: from_str :: < JpreConfig > ( & config. to_string ( ) )
152+ . unwrap_or_else ( |e| panic ! ( "Edited config is invalid: {}" , e) ) ;
153+
154+ std:: fs:: write ( & * CONFIG_PATH , config. to_string ( ) )
123155 . change_context ( JpreError :: Unexpected )
124156 . attach_printable_lazy ( || {
125- format ! ( "Could not write config file to {:?}" , * CONFIG_PATH )
157+ format ! ( "Could not write config file at {:?}" , * CONFIG_PATH )
126158 } ) ?;
127159 Ok ( ( ) )
128160 }
0 commit comments