Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSIS section sizes doubled due to use of SetOverwrite

Tags:

nsis

I've inherited an installer script, and I'm annoyed by it claiming to require twice as much space as it actually needs.

I found that this was due to how each section is using SetOverwrite (because they're re-used for a repair install?). I understand that it's necessary to keep the duplicated File commands in each of the If/Else blocks because of how SetOverwrite works (see below), but I have confirmed that it results in a doubling of the automatic section size calculations.

${MementoSection} $(APP_Section_SecHelp) SecHelp
  SetDetailsPrint textonly
  DetailPrint  $(APP_DetailPrint_SecHelp)
  SetDetailsPrint listonly

  SetOutPath $INSTDIR
  SectionIn 1 2
    ${If} $SetOverwriteOn == TRUE
      SetOverwrite ifnewer
      File /r "${APP_SOURCE_DIR}\Help"
    ${Else}
      SetOverwrite off
      File /r "${APP_SOURCE_DIR}\Help"
    ${EndIf}
  SectionGetFlags ${SecHelp} $SecHelp_GetFlag
${MementoSectionEnd}

Is this a bad design pattern that I should change? Do I need to add a hack to call SectionGetSize, divide by 2 and call SectionSetSize?

like image 395
tomlogic Avatar asked Oct 30 '22 07:10

tomlogic


1 Answers

Personally I would just use SetOverwrite ifnewer for both but if you absolutely want to do it your way then using SectionSetSize is one option.

Another thing you could do is to put the repair File /r instruction in a separate function that you call from the section. The downside of a function is that the progressbar does not move much during the extraction.

A third alternative is to put some of the repair tasks in a separate section that is unchecked by default and you enable it when you are in repair mode.

Edit: Here is a example that uses SectionSetSize:

!include LogicLib.nsh
InstallDir $Temp
Page Components InitComponentsPage
Page Directory
Page InstFiles  

!macro ModifySectionHack SID TEMPVAR
SectionGetSize ${SID} ${TEMPVAR}
IntOp ${TEMPVAR} ${TEMPVAR} / 2
SectionSetSize ${SID} ${TEMPVAR}
!macroend

Function InitComponentsPage
StrCpy $0 0
loop:
    ClearErrors
    SectionGetFlags $0 $1 ; The error flag is set if we try to access a section that does not exist
    IfErrors done
    !insertmacro ModifySectionHack $0 $1
    IntOp $0 $0 + 1
    Goto loop
done:
FunctionEnd

Section "Foo"
InitPluginsDir ; Need a place to extract to for this example
SetOutPath $PluginsDir

${If} 1 <> 2 ; Don't really care about the result
    SetOverwrite ifnewer
    File "${NSISDIR}\bin\makensis.exe" ; ~400kb
${Else}
    SetOverwrite off
    File "${NSISDIR}\bin\makensis.exe"
${EndIf}
SectionEnd

Section "Bar"
InitPluginsDir ; Need a place to extract to for this example
SetOutPath $PluginsDir

${If} 1 <> 2 ; Don't really care about the result
    SetOverwrite ifnewer
    File "${NSISDIR}\nsis.exe" ; ~700kb
${Else}
    SetOverwrite off
    File "${NSISDIR}\nsis.exe"
${EndIf}
SectionEnd

This loops through all the sections and adjusts all of them but I'm not sure if that is such a good idea. If this was my script then I would manually call ModifySectionHack on each section that has the SetOverwrite problem:

!include LogicLib.nsh
InstallDir $Temp
Page Components
Page Directory
Page InstFiles

!macro ModifySectionHack SID TEMPVAR
SectionGetSize ${SID} ${TEMPVAR}
IntOp ${TEMPVAR} ${TEMPVAR} / 2
SectionSetSize ${SID} ${TEMPVAR}
!macroend

Section "Foo" SID_FOO
InitPluginsDir ; Need a place to extract to for this example
SetOutPath $PluginsDir

${If} 1 <> 2 ; Don't really care about the result
    SetOverwrite ifnewer
    File "${NSISDIR}\bin\makensis.exe" ; ~400kb
${Else}
    SetOverwrite off
    File "${NSISDIR}\bin\makensis.exe"
${EndIf}
SectionEnd

Section "Bar"
${If} 1 = 2
  File /r "${NSISDIR}\stubs"
${EndIf}
SectionEnd

Section "Baz" SID_BAZ
InitPluginsDir ; Need a place to extract to for this example
SetOutPath $PluginsDir

${If} 1 <> 2 ; Don't really care about the result
    SetOverwrite ifnewer
    File "${NSISDIR}\nsis.exe" ; ~700kb
${Else}
    SetOverwrite off
    File "${NSISDIR}\nsis.exe"
${EndIf}
SectionEnd

Function .onInit
; Adjust the section size for the sections that use SetOverwrite:
!insertmacro ModifySectionHack ${SID_FOO} $1
!insertmacro ModifySectionHack ${SID_BAZ} $1
FunctionEnd
like image 162
Anders Avatar answered Nov 15 '22 10:11

Anders