1- use std:: io:: { Cursor , Read , Write } ;
1+ use std:: {
2+ io:: { Cursor , Read , Write } ,
3+ path:: { Path , PathBuf } ,
4+ } ;
25
36use backhand:: {
47 FilesystemCompressor , FilesystemReader , FilesystemWriter , InnerNode , NodeHeader ,
58 compression:: Compressor , kind:: Kind ,
69} ;
7- use fs_err:: tokio:: create_dir_all;
10+ use color_eyre:: { Section , eyre:: Context } ;
11+ use fs_err:: tokio:: { File , create_dir_all} ;
812use tokio:: io:: { AsyncReadExt , AsyncWriteExt } ;
913
1014use crate :: { commands:: build:: Builder , home_manager:: Target } ;
@@ -74,13 +78,17 @@ fn find_valid_squashfs_offset(data: &[u8]) -> Option<usize> {
7478
7579fn skip_file_from_squashfs < ' a > (
7680 reader : & FilesystemReader ,
77- skip_path : & ' a str ,
81+ skip_paths : Vec < PathBuf > ,
82+ skip_dir_icon : bool ,
7883) -> color_eyre:: Result < FilesystemWriter < ' a , ' a , ' a > > {
7984 let mut writer = FilesystemWriter :: default ( ) ;
8085
8186 for node in reader. files ( ) {
8287 // Skip the file we want to remove
83- if node. fullpath == std:: path:: Path :: new ( skip_path) {
88+ if skip_paths. contains ( & node. fullpath ) {
89+ continue ;
90+ }
91+ if node. fullpath . ends_with ( ".DirIcon" ) && skip_dir_icon {
8492 continue ;
8593 }
8694
@@ -140,14 +148,12 @@ pub async fn build_linux(builder: &Builder, data: &[u8]) -> color_eyre::Result<(
140148 . paths
141149 . dist
142150 . join ( Target :: LinuxAppImage . as_ref ( ) . to_string ( ) ) ;
143- let mut file = fs_err:: tokio:: File :: open (
144- builder
145- . home
146- . get_path ( & builder. config . love , Target :: LinuxAppImage )
147- . await
148- . join ( "love2d.AppImage" ) ,
149- )
150- . await ?;
151+ let original = builder
152+ . home
153+ . get_path ( & builder. config . love , Target :: LinuxAppImage )
154+ . await
155+ . join ( "love2d.AppImage" ) ;
156+ let mut file = fs_err:: tokio:: File :: open ( original) . await ?;
151157
152158 let mut image_data = vec ! [ ] ;
153159 file. read_to_end ( & mut image_data) . await ?;
@@ -171,7 +177,16 @@ pub async fn build_linux(builder: &Builder, data: &[u8]) -> color_eyre::Result<(
171177 }
172178 }
173179
174- let mut writer = skip_file_from_squashfs ( & reader, "/bin/love" ) . unwrap ( ) ;
180+ let mut to_skip = vec ! [
181+ Path :: new( "/bin/love" ) . to_path_buf( ) ,
182+ Path :: new( "/love.desktop" ) . to_path_buf( ) ,
183+ ] ;
184+ if builder. config . icon . is_some ( ) {
185+ to_skip. push ( Path :: new ( "/love.svg" ) . to_path_buf ( ) ) ;
186+ }
187+ // let icon_path = builder.paths.root.join(icon);
188+ let mut writer =
189+ skip_file_from_squashfs ( & reader, to_skip, builder. config . icon . is_some ( ) ) . unwrap ( ) ;
175190 // The AppImage of love2d doesn't support xz
176191 writer. set_compressor ( FilesystemCompressor :: new ( Compressor :: Zstd , None ) . unwrap ( ) ) ;
177192
@@ -185,9 +200,69 @@ pub async fn build_linux(builder: &Builder, data: &[u8]) -> color_eyre::Result<(
185200 ..Default :: default ( )
186201 } ,
187202 ) ?;
203+ let declaration = format ! (
204+ r#"[Desktop Entry]
205+ Name={}
206+ Comment={}
207+ MimeType=application/x-love-game;
208+ Exec=/home/runner/work/love/love/installdir/bin/love %f
209+ Type=Application
210+ Categories=Development;Game;
211+ Terminal=false
212+ Icon=love
213+ NoDisplay=true"# ,
214+ builder. config. project_name, builder. config. description
215+ ) ;
216+ writer. push_file (
217+ std:: io:: Cursor :: new ( declaration. as_bytes ( ) . to_vec ( ) ) ,
218+ "/love.desktop" ,
219+ NodeHeader :: default ( ) ,
220+ ) ?;
221+
222+ if let Some ( icon_pth) = & builder. config . icon {
223+ let mut icon = File :: open ( builder. paths . root . join ( icon_pth) ) . await ?;
224+ let mut data = vec ! [ ] ;
225+ icon. read_to_end ( & mut data) . await ?;
226+
227+ let pth = Path :: new ( icon_pth) ;
228+
229+ writer. push_file (
230+ std:: io:: Cursor :: new ( data) ,
231+ PathBuf :: new ( )
232+ . join ( "love" )
233+ . with_extension ( pth. extension ( ) . expect ( "Icon should have extension" ) ) ,
234+ NodeHeader :: default ( ) ,
235+ ) ?;
236+ writer. push_symlink (
237+ PathBuf :: new ( )
238+ . join ( "love" )
239+ . with_extension ( pth. extension ( ) . expect ( "Icon should have extension" ) ) ,
240+ PathBuf :: new ( ) . join ( ".DirIcon" ) ,
241+ NodeHeader :: default ( ) ,
242+ ) ?;
243+ }
244+
245+ for pattern in & builder. config . layout . external {
246+ for path in glob:: glob ( & builder. paths . root . join ( pattern) . to_string_lossy ( ) )
247+ . context ( "Building for windows" )
248+ . expect ( "Failed to parse glob" )
249+ . filter_map ( Result :: ok)
250+ {
251+ let output = PathBuf :: new ( ) . join ( "bin" ) . join (
252+ path. strip_prefix ( & builder. paths . root )
253+ . context ( "Building for windows" )
254+ . suggestion ( "Don't use assets outside the root of your project" )
255+ . expect ( "Failed to strip root" ) ,
256+ ) ;
257+ let data = fs_err:: tokio:: read ( & path) . await ?;
258+ writer. push_dir_all ( output. parent ( ) . unwrap ( ) , NodeHeader :: default ( ) ) ?;
259+ writer. push_file ( std:: io:: Cursor :: new ( data) , output, NodeHeader :: default ( ) ) ?;
260+ }
261+ }
188262
189263 create_dir_all ( & dists) . await ?;
190264
265+ fs_err:: tokio:: remove_file ( dists. join ( "love2d.AppImage" ) ) . await ?;
191266 let mut output_file = fs_err:: tokio:: File :: create (
192267 dists. join ( format ! ( "{}.AppImage" , builder. config. project_name) ) ,
193268 )
0 commit comments