@@ -183,7 +183,66 @@ pub struct CreateArgs {
183183 pub home_path : Option < String > ,
184184 pub image : String ,
185185 pub name : CreateArgName ,
186- pub volumes : Vec < String > ,
186+ pub volumes : Vec < Volume > ,
187+ }
188+
189+ #[ derive( Debug , Clone , PartialEq ) ]
190+ pub enum VolumeMode {
191+ ReadOnly ,
192+ }
193+
194+ impl std:: fmt:: Display for VolumeMode {
195+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
196+ match self {
197+ VolumeMode :: ReadOnly => write ! ( f, "ro" ) ,
198+ }
199+ }
200+ }
201+
202+ #[ derive( Debug , Clone , PartialEq ) ]
203+ pub struct Volume {
204+ pub host_path : String ,
205+ pub container_path : String ,
206+ pub mode : Option < VolumeMode > ,
207+ }
208+
209+ impl FromStr for Volume {
210+ type Err = Error ;
211+
212+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
213+ let parts: Vec < & str > = s. split ( ':' ) . collect ( ) ;
214+ match parts. as_slice ( ) {
215+ [ host] => Ok ( Volume {
216+ host_path : host. to_string ( ) ,
217+ container_path : host. to_string ( ) ,
218+ mode : None ,
219+ } ) ,
220+ [ host, target] => Ok ( Volume {
221+ host_path : host. to_string ( ) ,
222+ container_path : target. to_string ( ) ,
223+ mode : None ,
224+ } ) ,
225+ [ host, target, "ro" ] => Ok ( Volume {
226+ host_path : host. to_string ( ) ,
227+ container_path : target. to_string ( ) ,
228+ mode : Some ( VolumeMode :: ReadOnly ) ,
229+ } ) ,
230+ _ => Err ( Error :: InvalidField (
231+ "volume" . into ( ) ,
232+ format ! ( "Invalid volume descriptor: {}" , s) ,
233+ ) ) ,
234+ }
235+ }
236+ }
237+
238+ impl std:: fmt:: Display for Volume {
239+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
240+ write ! ( f, "{}:{}" , self . host_path, self . container_path) ?;
241+ if let Some ( mode) = & self . mode {
242+ write ! ( f, ":{}" , mode) ?;
243+ }
244+ Ok ( ( ) )
245+ }
187246}
188247
189248#[ derive( thiserror:: Error , Debug ) ]
@@ -688,7 +747,7 @@ impl Distrobox {
688747 cmd. arg ( "--home" ) . arg ( home_path) ;
689748 }
690749 for volume in args. volumes {
691- cmd. arg ( "--volume" ) . arg ( volume) ;
750+ cmd. arg ( "--volume" ) . arg ( volume. to_string ( ) ) ;
692751 }
693752 self . cmd_spawn ( cmd)
694753 }
@@ -932,12 +991,14 @@ Categories=Utility;Network;
932991 init : true ,
933992 nvidia : true ,
934993 home_path : Some ( "/home/me" . into ( ) ) ,
935- volumes : vec ! [ "/mnt/sdb1" . into( ) , "/mnt/sdb4" . into( ) ] ,
994+ volumes : vec ! [
995+ Volume :: from_str( "/mnt/sdb1:/mnt/sdb1" ) ?,
996+ Volume :: from_str( "/mnt/sdb4:/mnt/sdb4:ro" ) ?,
997+ ] ,
936998 ..Default :: default ( )
937999 } ;
938-
939- block_on ( db. create ( args) ) ?;
940- let expected = "\" distrobox\" [\" create\" , \" --yes\" , \" --image\" , \" docker.io/library/ubuntu:latest\" , \" --init\" , \" --nvidia\" , \" --home\" , \" /home/me\" , \" --volume\" , \" /mnt/sdb1\" , \" --volume\" , \" /mnt/sdb4\" ]" ;
1000+ smol:: block_on ( db. create ( args) ) ?;
1001+ let expected = "\" distrobox\" [\" create\" , \" --yes\" , \" --image\" , \" docker.io/library/ubuntu:latest\" , \" --init\" , \" --nvidia\" , \" --home\" , \" /home/me\" , \" --volume\" , \" /mnt/sdb1:/mnt/sdb1\" , \" --volume\" , \" /mnt/sdb4:/mnt/sdb4:ro\" ]" ;
9411002 assert_eq ! ( output_tracker. items( ) [ 0 ] , expected) ;
9421003 Ok ( ( ) )
9431004 }
0 commit comments