@@ -2,9 +2,9 @@ import BluebirdPromise from "bluebird-lst"
22import { Arch , exec , log , debug } from "builder-util"
33import { UUID } from "builder-util-runtime"
44import { getBinFromGithub } from "builder-util/out/binDownload"
5- import { unlinkIfExists , copyOrLinkFile } from "builder-util/out/fs"
5+ import { unlinkIfExists , copyOrLinkFile , copyDir , USE_HARD_LINKS } from "builder-util/out/fs"
66import * as ejs from "ejs"
7- import { emptyDir , ensureDir , readFile , remove , writeFile } from "fs-extra-p"
7+ import { emptyDir , ensureDir , readFile , remove , symlink , writeFile } from "fs-extra-p"
88import { Lazy } from "lazy-val"
99import * as path from "path"
1010import { Target } from "../core"
@@ -45,24 +45,10 @@ export default class AppImageTarget extends Target {
4545 const stageDir = path . join ( this . outDir , `__appimage-${ Arch [ arch ] } ` )
4646 const appInStageDir = path . join ( stageDir , "app" )
4747 await emptyDir ( stageDir )
48- await copyDirUsingHardLinks ( appOutDir , appInStageDir , true )
49-
50- const iconNames = await BluebirdPromise . map ( this . helper . icons , it => {
51- let filename = `icon-${ it . size } .png`
52- if ( it . file === this . helper . maxIconPath ) {
53- // largest icon as package icon
54- filename = `${ this . packager . executableName } .png`
55- }
56- return copyOrLinkFile ( it . file , path . join ( stageDir , filename ) , null , true )
57- . then ( ( ) => ( { filename, size : it . size } ) )
58- } )
48+ await copyDirUsingHardLinks ( appOutDir , appInStageDir )
5949
6050 const resourceName = `appimagekit-${ this . packager . executableName } `
61-
62- let installIcons = ""
63- for ( const icon of iconNames ) {
64- installIcons += `xdg-icon-resource install --noupdate --context apps --size ${ icon . size } "$APPDIR/${ icon . filename } " "${ resourceName } "\n`
65- }
51+ const installIcons = await this . copyIcons ( stageDir , resourceName )
6652
6753 const finalDesktopFilename = `${ this . packager . executableName } .desktop`
6854 await BluebirdPromise . all ( [
@@ -88,7 +74,9 @@ export default class AppImageTarget extends Target {
8874 const vendorDir = await getBinFromGithub ( "appimage" , "9.0.1" , "mcme+7/krXSYb5C+6BpSt9qgajFYpn9dI1rjxzSW3YB5R/KrGYYrpZbVflEMG6pM7k9CL52poiOpGLBDG/jW3Q==" )
8975
9076 if ( arch === Arch . x64 || arch === Arch . ia32 ) {
91- await copyDirUsingHardLinks ( path . join ( vendorDir , "lib" , arch === Arch . x64 ? "x86_64-linux-gnu" : "i386-linux-gnu" ) , path . join ( stageDir , "usr/lib" ) , false )
77+ await copyDir ( path . join ( vendorDir , "lib" , arch === Arch . x64 ? "x86_64-linux-gnu" : "i386-linux-gnu" ) , path . join ( stageDir , "usr/lib" ) , {
78+ isUseHardLink : USE_HARD_LINKS ,
79+ } )
9280 }
9381
9482 if ( this . packager . packagerOptions . effectiveOptionComputed != null && await this . packager . packagerOptions . effectiveOptionComputed ( { desktop : await this . desktopEntry . value } ) ) {
@@ -116,15 +104,41 @@ export default class AppImageTarget extends Target {
116104 }
117105 packager . dispatchArtifactCreated ( resultFile , this , arch , packager . computeSafeArtifactName ( artifactName , "AppImage" , arch , false ) )
118106 }
107+
108+ private async copyIcons ( stageDir : string , resourceName : string ) : Promise < string > {
109+ const iconDirRelativePath = "usr/share/icons/hicolor"
110+ const iconDir = path . join ( stageDir , iconDirRelativePath )
111+ await ensureDir ( iconDir )
112+
113+ // https://github.com/AppImage/AppImageKit/issues/438#issuecomment-319094239
114+ // expects icons in the /usr/share/icons/hicolor
115+ const iconNames = await BluebirdPromise . map ( this . helper . icons , async icon => {
116+ const filename = `${ this . packager . executableName } .png`
117+ const iconSizeDir = `${ icon . size } x${ icon . size } /apps`
118+ const dir = path . join ( iconDir , iconSizeDir )
119+ await ensureDir ( dir )
120+ const finalIconFile = path . join ( dir , filename )
121+ await copyOrLinkFile ( icon . file , finalIconFile , null , true )
122+
123+ if ( icon . file === this . helper . maxIconPath ) {
124+ await symlink ( path . relative ( stageDir , finalIconFile ) , path . join ( stageDir , filename ) )
125+ }
126+ return { filename, iconSizeDir, size : icon . size }
127+ } )
128+
129+ let installIcons = ""
130+ for ( const icon of iconNames ) {
131+ installIcons += `xdg-icon-resource install --noupdate --context apps --size ${ icon . size } "$APPDIR/${ iconDirRelativePath } /${ icon . iconSizeDir } /${ icon . filename } " "${ resourceName } "\n`
132+ }
133+ return installIcons
134+ }
119135}
120136
121137// https://unix.stackexchange.com/questions/202430/how-to-copy-a-directory-recursively-using-hardlinks-for-each-file
122- function copyDirUsingHardLinks ( source : string , destination : string , useLink : boolean ) {
138+ function copyDirUsingHardLinks ( source : string , destination : string ) {
123139 if ( process . platform !== "darwin" ) {
124140 const args = [ "-d" , "--recursive" , "--preserve=mode" ]
125- if ( useLink ) {
126- args . push ( "--link" )
127- }
141+ args . push ( "--link" )
128142 args . push ( source + "/" , destination + "/" )
129143 return ensureDir ( path . dirname ( destination ) ) . then ( ( ) => exec ( "cp" , args ) )
130144 }
0 commit comments