summary refs log tree commit diff stats
path: root/tools
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2014-10-20 08:44:00 +0200
committerAraq <rumpf_a@web.de>2014-10-20 08:44:00 +0200
commit53a9d6f5cd199382957188cd8a1a7f0aa5035033 (patch)
tree9873032461904538e21cbff3417882d1b54ef881 /tools
parentc7570dcd3e4202bd339a2ebbc09952a546c62269 (diff)
parentb0179f9af5c5ed3cc63c5cd3b9d1055b742a3b79 (diff)
downloadNim-53a9d6f5cd199382957188cd8a1a7f0aa5035033.tar.gz
Merge branch 'devel' into bigbreak
Conflicts:
	compiler/nim.ini
	doc/manual.txt
	doc/tut2.txt
	koch.nim
	lib/system/channels.nim
	readme.txt
	tools/niminst/niminst.nim
	tools/nimweb.nim
	web/download.txt
	web/news.txt
Diffstat (limited to 'tools')
-rw-r--r--tools/niminst/EnvVarUpdate.nsh346
-rw-r--r--tools/niminst/inno.tmpl6
-rw-r--r--tools/niminst/niminst.nim49
-rw-r--r--tools/niminst/nsis.tmpl255
-rw-r--r--tools/nimweb.nim18
5 files changed, 654 insertions, 20 deletions
diff --git a/tools/niminst/EnvVarUpdate.nsh b/tools/niminst/EnvVarUpdate.nsh
new file mode 100644
index 000000000..4340b8f3c
--- /dev/null
+++ b/tools/niminst/EnvVarUpdate.nsh
@@ -0,0 +1,346 @@
+/**
+ *  EnvVarUpdate.nsh
+ *    : Environmental Variables: append, prepend, and remove entries
+ *
+ *     WARNING: If you use StrFunc.nsh header then include it before this file
+ *              with all required definitions. This is to avoid conflicts
+ *
+ *  Usage:
+ *    ${EnvVarUpdate} "ResultVar" "EnvVarName" "Action" "RegLoc" "PathString"
+ *
+ *  Credits:
+ *  Version 1.0 
+ *  * Cal Turney (turnec2)
+ *  * Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this
+ *    function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar,
+ *    WriteEnvStr, and un.DeleteEnvStr
+ *  * Diego Pedroso (deguix) for StrTok
+ *  * Kevin English (kenglish_hi) for StrContains
+ *  * Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry  
+ *    (dandaman32) for StrReplace
+ *
+ *  Version 1.1 (compatibility with StrFunc.nsh)
+ *  * techtonik
+ *
+ *  http://nsis.sourceforge.net/Environmental_Variables:_append%2C_prepend%2C_and_remove_entries
+ *
+ */
+
+
+!ifndef ENVVARUPDATE_FUNCTION
+!define ENVVARUPDATE_FUNCTION
+!verbose push
+!verbose 3
+!include "LogicLib.nsh"
+!include "WinMessages.NSH"
+!include "StrFunc.nsh"
+
+; ---- Fix for conflict if StrFunc.nsh is already includes in main file -----------------------
+!macro _IncludeStrFunction StrFuncName
+  !ifndef ${StrFuncName}_INCLUDED
+    ${${StrFuncName}}
+  !endif
+  !ifndef Un${StrFuncName}_INCLUDED
+    ${Un${StrFuncName}}
+  !endif
+  !define un.${StrFuncName} "${Un${StrFuncName}}"
+!macroend
+
+!insertmacro _IncludeStrFunction StrTok
+!insertmacro _IncludeStrFunction StrStr
+!insertmacro _IncludeStrFunction StrRep
+
+; ---------------------------------- Macro Definitions ----------------------------------------
+!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString
+  Push "${EnvVarName}"
+  Push "${Action}"
+  Push "${RegLoc}"
+  Push "${PathString}"
+    Call EnvVarUpdate
+  Pop "${ResultVar}"
+!macroend
+!define EnvVarUpdate '!insertmacro "_EnvVarUpdateConstructor"'
+ 
+!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString
+  Push "${EnvVarName}"
+  Push "${Action}"
+  Push "${RegLoc}"
+  Push "${PathString}"
+    Call un.EnvVarUpdate
+  Pop "${ResultVar}"
+!macroend
+!define un.EnvVarUpdate '!insertmacro "_unEnvVarUpdateConstructor"'
+; ---------------------------------- Macro Definitions end-------------------------------------
+ 
+;----------------------------------- EnvVarUpdate start----------------------------------------
+!define hklm_all_users     'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
+!define hkcu_current_user  'HKCU "Environment"'
+ 
+!macro EnvVarUpdate UN
+ 
+Function ${UN}EnvVarUpdate
+ 
+  Push $0
+  Exch 4
+  Exch $1
+  Exch 3
+  Exch $2
+  Exch 2
+  Exch $3
+  Exch
+  Exch $4
+  Push $5
+  Push $6
+  Push $7
+  Push $8
+  Push $9
+  Push $R0
+ 
+  /* After this point:
+  -------------------------
+     $0 = ResultVar     (returned)
+     $1 = EnvVarName    (input)
+     $2 = Action        (input)
+     $3 = RegLoc        (input)
+     $4 = PathString    (input)
+     $5 = Orig EnvVar   (read from registry)
+     $6 = Len of $0     (temp)
+     $7 = tempstr1      (temp)
+     $8 = Entry counter (temp)
+     $9 = tempstr2      (temp)
+     $R0 = tempChar     (temp)  */
+ 
+  ; Step 1:  Read contents of EnvVarName from RegLoc
+  ;
+  ; Check for empty EnvVarName
+  ${If} $1 == ""
+    SetErrors
+    DetailPrint "ERROR: EnvVarName is blank"
+    Goto EnvVarUpdate_Restore_Vars
+  ${EndIf}
+ 
+  ; Check for valid Action
+  ${If}    $2 != "A"
+  ${AndIf} $2 != "P"
+  ${AndIf} $2 != "R"
+    SetErrors
+    DetailPrint "ERROR: Invalid Action - must be A, P, or R"
+    Goto EnvVarUpdate_Restore_Vars
+  ${EndIf}
+ 
+  ${If} $3 == HKLM
+    ReadRegStr $5 ${hklm_all_users} $1     ; Get EnvVarName from all users into $5
+  ${ElseIf} $3 == HKCU
+    ReadRegStr $5 ${hkcu_current_user} $1  ; Read EnvVarName from current user into $5
+  ${Else}
+    SetErrors
+    DetailPrint 'ERROR: Action is [$3] but must be "HKLM" or HKCU"'
+    Goto EnvVarUpdate_Restore_Vars
+  ${EndIf}
+ 
+  ; Check for empty PathString
+  ${If} $4 == ""
+    SetErrors
+    DetailPrint "ERROR: PathString is blank"
+    Goto EnvVarUpdate_Restore_Vars
+  ${EndIf}
+ 
+  Push $6
+  Push $7
+  Push $8
+  StrLen $7 $4  
+  StrLen $6 $5
+  IntOp $8 $6 + $7
+  ${If} $5 == ""
+  ${OrIf} $8 >= ${NSIS_MAX_STRLEN}
+    SetErrors
+    DetailPrint "Current $1 length ($6) too long to modify in NSIS; set manually if needed"
+    Pop $8
+    Pop $7
+    Pop $6
+    Goto EnvVarUpdate_Restore_Vars
+  ${EndIf}
+  Pop $8
+  Pop $7
+  Pop $6
+
+  ; Make sure we've got some work to do
+  ${If} $5 == ""
+  ${AndIf} $2 == "R"
+    SetErrors
+    DetailPrint "$1 is empty - Nothing to remove"
+    Goto EnvVarUpdate_Restore_Vars
+  ${EndIf}
+ 
+  ; Step 2: Scrub EnvVar
+  ;
+  StrCpy $0 $5                             ; Copy the contents to $0
+  ; Remove spaces around semicolons (NOTE: spaces before the 1st entry or
+  ; after the last one are not removed here but instead in Step 3)
+  ${If} $0 != ""                           ; If EnvVar is not empty ...
+    ${Do}
+      ${${UN}StrStr} $7 $0 " ;"
+      ${If} $7 == ""
+        ${ExitDo}
+      ${EndIf}
+      ${${UN}StrRep} $0  $0 " ;" ";"         ; Remove '<space>;'
+    ${Loop}
+    ${Do}
+      ${${UN}StrStr} $7 $0 "; "
+      ${If} $7 == ""
+        ${ExitDo}
+      ${EndIf}
+      ${${UN}StrRep} $0  $0 "; " ";"         ; Remove ';<space>'
+    ${Loop}
+    ${Do}
+      ${${UN}StrStr} $7 $0 ";;" 
+      ${If} $7 == ""
+        ${ExitDo}
+      ${EndIf}
+      ${${UN}StrRep} $0  $0 ";;" ";"
+    ${Loop}
+ 
+    ; Remove a leading or trailing semicolon from EnvVar
+    StrCpy  $7  $0 1 0
+    ${If} $7 == ";"
+      StrCpy $0  $0 "" 1                   ; Change ';<EnvVar>' to '<EnvVar>'
+    ${EndIf}
+    StrLen $6 $0
+    IntOp $6 $6 - 1
+    StrCpy $7  $0 1 $6
+    ${If} $7 == ";"
+     StrCpy $0  $0 $6                      ; Change ';<EnvVar>' to '<EnvVar>'
+    ${EndIf}
+    ; DetailPrint "Scrubbed $1: [$0]"      ; Uncomment to debug
+  ${EndIf}
+ 
+  /* Step 3. Remove all instances of the target path/string (even if "A" or "P")
+     $6 = bool flag (1 = found and removed PathString)
+     $7 = a string (e.g. path) delimited by semicolon(s)
+     $8 = entry counter starting at 0
+     $9 = copy of $0
+     $R0 = tempChar      */
+ 
+  ${If} $5 != ""                           ; If EnvVar is not empty ...
+    StrCpy $9 $0
+    StrCpy $0 ""
+    StrCpy $8 0
+    StrCpy $6 0
+ 
+    ${Do}
+      ${${UN}StrTok} $7 $9 ";" $8 "0"      ; $7 = next entry, $8 = entry counter
+ 
+      ${If} $7 == ""                       ; If we've run out of entries,
+        ${ExitDo}                          ;    were done
+      ${EndIf}                             ;
+ 
+      ; Remove leading and trailing spaces from this entry (critical step for Action=Remove)
+      ${Do}
+        StrCpy $R0  $7 1
+        ${If} $R0 != " "
+          ${ExitDo}
+        ${EndIf}
+        StrCpy $7   $7 "" 1                ;  Remove leading space
+      ${Loop}
+      ${Do}
+        StrCpy $R0  $7 1 -1
+        ${If} $R0 != " "
+          ${ExitDo}
+        ${EndIf}
+        StrCpy $7   $7 -1                  ;  Remove trailing space
+      ${Loop}
+      ${If} $7 == $4                       ; If string matches, remove it by not appending it
+        StrCpy $6 1                        ; Set 'found' flag
+      ${ElseIf} $7 != $4                   ; If string does NOT match
+      ${AndIf}  $0 == ""                   ;    and the 1st string being added to $0,
+        StrCpy $0 $7                       ;    copy it to $0 without a prepended semicolon
+      ${ElseIf} $7 != $4                   ; If string does NOT match
+      ${AndIf}  $0 != ""                   ;    and this is NOT the 1st string to be added to $0,
+        StrCpy $0 $0;$7                    ;    append path to $0 with a prepended semicolon
+      ${EndIf}                             ;
+ 
+      IntOp $8 $8 + 1                      ; Bump counter
+    ${Loop}                                ; Check for duplicates until we run out of paths
+  ${EndIf}
+ 
+  ; Step 4:  Perform the requested Action
+  ;
+  ${If} $2 != "R"                          ; If Append or Prepend
+    ${If} $6 == 1                          ; And if we found the target
+      DetailPrint "Target is already present in $1. It will be removed and"
+    ${EndIf}
+    ${If} $0 == ""                         ; If EnvVar is (now) empty
+      StrCpy $0 $4                         ;   just copy PathString to EnvVar
+      ${If} $6 == 0                        ; If found flag is either 0
+      ${OrIf} $6 == ""                     ; or blank (if EnvVarName is empty)
+        DetailPrint "$1 was empty and has been updated with the target"
+      ${EndIf}
+    ${ElseIf} $2 == "A"                    ;  If Append (and EnvVar is not empty),
+      StrCpy $0 $0;$4                      ;     append PathString
+      ${If} $6 == 1
+        DetailPrint "appended to $1"
+      ${Else}
+        DetailPrint "Target was appended to $1"
+      ${EndIf}
+    ${Else}                                ;  If Prepend (and EnvVar is not empty),
+      StrCpy $0 $4;$0                      ;     prepend PathString
+      ${If} $6 == 1
+        DetailPrint "prepended to $1"
+      ${Else}
+        DetailPrint "Target was prepended to $1"
+      ${EndIf}
+    ${EndIf}
+  ${Else}                                  ; If Action = Remove
+    ${If} $6 == 1                          ;   and we found the target
+      DetailPrint "Target was found and removed from $1"
+    ${Else}
+      DetailPrint "Target was NOT found in $1 (nothing to remove)"
+    ${EndIf}
+    ${If} $0 == ""
+      DetailPrint "$1 is now empty"
+    ${EndIf}
+  ${EndIf}
+ 
+  ; Step 5:  Update the registry at RegLoc with the updated EnvVar and announce the change
+  ;
+  ClearErrors
+  ${If} $3  == HKLM
+    WriteRegExpandStr ${hklm_all_users} $1 $0     ; Write it in all users section
+  ${ElseIf} $3 == HKCU
+    WriteRegExpandStr ${hkcu_current_user} $1 $0  ; Write it to current user section
+  ${EndIf}
+ 
+  IfErrors 0 +4
+    MessageBox MB_OK|MB_ICONEXCLAMATION "Could not write updated $1 to $3"
+    DetailPrint "Could not write updated $1 to $3"
+    Goto EnvVarUpdate_Restore_Vars
+ 
+  ; "Export" our change
+  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
+ 
+  EnvVarUpdate_Restore_Vars:
+  ;
+  ; Restore the user's variables and return ResultVar
+  Pop $R0
+  Pop $9
+  Pop $8
+  Pop $7
+  Pop $6
+  Pop $5
+  Pop $4
+  Pop $3
+  Pop $2
+  Pop $1
+  Push $0  ; Push my $0 (ResultVar)
+  Exch
+  Pop $0   ; Restore his $0
+ 
+FunctionEnd
+ 
+!macroend   ; EnvVarUpdate UN
+!insertmacro EnvVarUpdate ""
+!insertmacro EnvVarUpdate "un."
+;----------------------------------- EnvVarUpdate end----------------------------------------
+ 
+!verbose pop
+!endif
diff --git a/tools/niminst/inno.tmpl b/tools/niminst/inno.tmpl
index b9d04755e..3460c22a2 100644
--- a/tools/niminst/inno.tmpl
+++ b/tools/niminst/inno.tmpl
@@ -44,9 +44,9 @@ Name: modifypath; Description: &Add $c.displayName to your system path (if not i
 [Code]
 function GiveMeAPath(const DefaultPathName: string): string;
 begin
-  if IsAdminLoggedOn then Result := ExpandConstant('{pf}')
-  else Result := ExpandConstant('{userdocs}');
-  Result := Result + '\' + DefaultPathName;
+  if IsAdminLoggedOn then result := ExpandConstant('{pf}')
+  else result := ExpandConstant('{userdocs}');
+  result := result + '\' + DefaultPathName;
 end;
 
   #if c.binPaths.len > 0:
diff --git a/tools/niminst/niminst.nim b/tools/niminst/niminst.nim
index 614009c24..022b14209 100644
--- a/tools/niminst/niminst.nim
+++ b/tools/niminst/niminst.nim
@@ -31,6 +31,7 @@ type
     actionNone,   # action not yet known
     actionCSource # action: create C sources
     actionInno,   # action: create Inno Setup installer
+    actionNsis,   # action: create NSIS installer
     actionScripts # action: create install and deinstall scripts
     actionZip,    # action: create zip file
     actionDeb     # action: prepare deb package
@@ -50,10 +51,10 @@ type
   TConfigData = object of TObject
     actions: set[TAction]
     cat: array[TFileCategory, seq[string]]
-    binPaths, authors, oses, cpus: seq[string]
+    binPaths, authors, oses, cpus, downloads: seq[string]
     cfiles: array[1..maxOS, array[1..maxCPU, seq[string]]]
     platforms: array[1..maxOS, array[1..maxCPU, bool]]
-    ccompiler, linker, innosetup: tuple[path, flags: string]
+    ccompiler, linker, innosetup, nsisSetup: tuple[path, flags: string]
     name, displayName, version, description, license, infile, outdir: string
     libpath: string
     innoSetupFlag, installScript, uninstallScript: bool
@@ -75,9 +76,11 @@ proc initConfigData(c: var TConfigData) =
   c.authors = @[]
   c.oses = @[]
   c.cpus = @[]
+  c.downloads = @[]
   c.ccompiler = ("", "")
   c.linker = ("", "")
   c.innosetup = ("", "")
+  c.nsisSetup = ("", "")
   c.name = ""
   c.displayName = ""
   c.version = ""
@@ -117,6 +120,7 @@ proc skipRoot(f: string): string =
   if result.len == 0: result = f
 
 include "inno.tmpl"
+include "nsis.tmpl"
 include "buildsh.tmpl"
 include "buildbat.tmpl"
 include "install.tmpl"
@@ -125,10 +129,10 @@ include "deinstall.tmpl"
 # ------------------------- configuration file -------------------------------
 
 const
-  Version = "0.9"
+  Version = "1.0"
   Usage = "niminst - Nim Installation Generator Version " & Version & """
 
-  (c) 2013 Andreas Rumpf
+  (c) 2014 Andreas Rumpf
 Usage:
   niminst [options] command[;command2...] ini-file[.ini] [compile_options]
 Command:
@@ -136,6 +140,7 @@ Command:
   scripts             build install and deinstall scripts
   zip                 build the ZIP file
   inno                build the Inno Setup installer
+  nsis                build the NSIS Setup installer
   deb                 create files for debhelper
 Options:
   -o, --output:dir    set the output directory
@@ -162,6 +167,7 @@ proc parseCmdLine(c: var TConfigData) =
           of "scripts": incl(c.actions, actionScripts)
           of "zip": incl(c.actions, actionZip)
           of "inno": incl(c.actions, actionInno)
+          of "nsis": incl(c.actions, actionNsis)
           of "deb": incl(c.actions, actionDeb)
           else: quit(Usage)
       else:
@@ -190,7 +196,7 @@ proc walkDirRecursively(s: var seq[string], root: string) =
     case k
     of pcFile, pcLinkToFile: add(s, unixToNativePath(f))
     of pcDir: walkDirRecursively(s, f)
-    of pcLinkToDir: nil
+    of pcLinkToDir: discard
 
 proc addFiles(s: var seq[string], patterns: seq[string]) =
   for p in items(patterns):
@@ -288,7 +294,7 @@ proc parseIniFile(c: var TConfigData) =
             else: quit(errorStr(p, "expected: console or gui"))
           of "license": c.license = unixToNativePath(k.value)
           else: quit(errorStr(p, "unknown variable: " & k.key))
-        of "var": nil
+        of "var": discard
         of "winbin": filesOnly(p, k.key, v, c.cat[fcWinBin])
         of "config": filesOnly(p, k.key, v, c.cat[fcConfig])
         of "data": filesOnly(p, k.key, v, c.cat[fcData])
@@ -304,6 +310,7 @@ proc parseIniFile(c: var TConfigData) =
           of "files": addFiles(c.cat[fcWindows], split(v, {';'}))
           of "binpath": c.binPaths = split(v, {';'})
           of "innosetup": c.innoSetupFlag = yesno(p, v)
+          of "download": c.downloads.add(v)
           else: quit(errorStr(p, "unknown variable: " & k.key))
         of "unix":
           case normalize(k.key)
@@ -313,6 +320,7 @@ proc parseIniFile(c: var TConfigData) =
           else: quit(errorStr(p, "unknown variable: " & k.key))
         of "unixbin": filesOnly(p, k.key, v, c.cat[fcUnixBin])
         of "innosetup": pathFlags(p, k.key, v, c.innosetup)
+        of "nsis": pathFlags(p, k.key, v, c.nsisSetup)
         of "ccompiler": pathFlags(p, k.key, v, c.ccompiler)
         of "linker": pathFlags(p, k.key, v, c.linker)
         of "deb":
@@ -479,14 +487,14 @@ proc srcdist(c: var TConfigData) =
 
 # --------------------- generate inno setup -----------------------------------
 proc setupDist(c: var TConfigData) =
-  var scrpt = generateInnoSetup(c)
-  var n = "build" / "install_$#_$#.iss" % [toLower(c.name), c.version]
+  let scrpt = generateInnoSetup(c)
+  let n = "build" / "install_$#_$#.iss" % [toLower(c.name), c.version]
   writeFile(n, scrpt, "\13\10")
   when defined(windows):
     if c.innosetup.path.len == 0:
       c.innosetup.path = "iscc.exe"
-    var outcmd = if c.outdir.len == 0: "build" else: c.outdir
-    var cmd = "$# $# /O$# $#" % [quoteShell(c.innosetup.path),
+    let outcmd = if c.outdir.len == 0: "build" else: c.outdir
+    let cmd = "$# $# /O$# $#" % [quoteShell(c.innosetup.path),
                                  c.innosetup.flags, outcmd, n]
     echo(cmd)
     if execShellCmd(cmd) == 0:
@@ -494,6 +502,23 @@ proc setupDist(c: var TConfigData) =
     else:
       quit("External program failed")
 
+# --------------------- generate NSIS setup -----------------------------------
+proc setupDist2(c: var TConfigData) =
+  let scrpt = generateNsisSetup(c)
+  let n = "build" / "install_$#_$#.nsi" % [toLower(c.name), c.version]
+  writeFile(n, scrpt, "\13\10")
+  when defined(windows):
+    if c.nsisSetup.path.len == 0:
+      c.nsisSetup.path = "makensis.exe"
+    let outcmd = if c.outdir.len == 0: "build" else: c.outdir
+    let cmd = "$# $# /O$# $#" % [quoteShell(c.nsisSetup.path),
+                                 c.nsisSetup.flags, outcmd, n]
+    echo(cmd)
+    if execShellCmd(cmd) == 0:
+      removeFile(n)
+    else:
+      quit("External program failed")
+
 # ------------------ generate ZIP file ---------------------------------------
 when haveZipLib:
   proc zipDist(c: var TConfigData) =
@@ -509,7 +534,7 @@ when haveZipLib:
       addFile(z, proj / installShFile, installShFile)
       addFile(z, proj / deinstallShFile, deinstallShFile)
       for f in walkFiles(c.libpath / "lib/*.h"):
-        addFile(z, proj / "build" / extractFilename(f), f)
+        addFile(z, proj / "c_code" / extractFilename(f), f)
       for osA in 1..c.oses.len:
         for cpuA in 1..c.cpus.len:
           var dir = buildDir(osA, cpuA)
@@ -576,6 +601,8 @@ parseCmdLine(c)
 parseIniFile(c)
 if actionInno in c.actions:
   setupDist(c)
+if actionNsis in c.actions:
+  setupDist2(c)
 if actionCSource in c.actions:
   srcdist(c)
 if actionScripts in c.actions:
diff --git a/tools/niminst/nsis.tmpl b/tools/niminst/nsis.tmpl
new file mode 100644
index 000000000..c4270081e
--- /dev/null
+++ b/tools/niminst/nsis.tmpl
@@ -0,0 +1,255 @@
+#! stdtmpl(subsChar='?') | standard
+#proc generateNsisSetup(c: TConfigData): string = 
+#  result = "; NSIS script generated by niminst\n" &
+#           "; To regenerate run ``niminst nsis`` or ``koch nsis``\n"
+
+;--------------------------------
+; Included headers
+  ; Modern User Interface 2.0 Header
+  !include "MUI2.nsh"
+
+  ; File Functions Header, used to get the current drive root.
+  !include "FileFunc.nsh"
+
+  ; *Patched* Environment Variable Manipulation Header, used to add
+  ; tools to the user's PATH environment variable.
+  !include "EnvVarUpdate.nsh"
+
+;--------------------------------
+; Global variables and defines
+  !define PRODUCT_NAME "?c.displayName"
+  !define PRODUCT_VERSION "?c.version"
+  !define PRODUCT_PUBLISHER "?c.authors"
+  !define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\?{c.name}.exe"
+  !define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
+  !define PRODUCT_UNINST_ROOT_KEY "HKCU"
+  !define PRODUCT_STARTMENU_REGVAL "NSIS:StartMenuDir"
+
+
+;--------------------------------
+; General Setup Information
+
+  ; Name and output file
+  Name "?{c.name} ?{c.version}"
+  OutFile "?{c.name}_?{c.version}.exe"
+
+  ; Default installation folder
+  ; This is changed later (in .onInit) to the root directory, if possible.
+  InstallDir "$LOCALAPPDATA\?{c.name}"
+  
+  ; Get installation folder from registry if available
+  InstallDirRegKey HKCU "Software\c.name\c.version" ""
+
+  ; Request user level application privileges.
+  RequestExecutionLevel user
+
+  ; Allow installation to the root drive directory.
+  AllowRootDirInstall true
+
+  ; Maximum compression!
+  SetCompressor /SOLID /FINAL lzma
+
+  ; Installer and Uninstaller Icons
+  ; Icon "nimrod.ico"
+  ; UninstallIcon "nimrod.ico"
+
+  ; Set installation details to be shown by default
+  ShowInstDetails show
+  ShowUnInstDetails show
+
+;--------------------------------
+; Interface Settings
+
+  ; Warn the user if aborting during installation/uninstallation
+  !define MUI_ABORTWARNING
+  !define MUI_UNABORTWARNING
+
+  ; Don't show a description for sections
+  !define MUI_COMPONENTSPAGE_NODESC
+
+;--------------------------------
+; Pages
+
+  ; Setup the installer pages
+  !insertmacro MUI_PAGE_WELCOME
+  !insertmacro MUI_PAGE_LICENSE "?{expandFilename(c.license)}"
+  !insertmacro MUI_PAGE_COMPONENTS
+  !insertmacro MUI_PAGE_DIRECTORY
+
+  ; Setup the start menu entry page
+  var ICONS_GROUP
+  !define MUI_STARTMENUPAGE_DEFAULTFOLDER "?{c.displayName}"
+  !define MUI_STARTMENUPAGE_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}"
+  !define MUI_STARTMENUPAGE_REGISTRY_KEY "${PRODUCT_UNINST_KEY}"
+  !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${PRODUCT_STARTMENU_REGVAL}"
+  !insertmacro MUI_PAGE_STARTMENU Application $ICONS_GROUP
+
+  !insertmacro MUI_PAGE_INSTFILES
+  !insertmacro MUI_PAGE_FINISH
+  
+  ; Setup the uninstaller pages
+  !insertmacro MUI_UNPAGE_CONFIRM
+  !insertmacro MUI_UNPAGE_INSTFILES
+  
+;--------------------------------
+;Languages
+ 
+  !insertmacro MUI_LANGUAGE "English"
+
+;--------------------------------
+;Installer Sections
+
+  ; The core section. This is comprised of a base Nim installation,
+  ; such as what would be retrieved via git, and an already bootstrapped
+  ; Nim binary.
+  Section "Core Files" CoreSection
+    ; This is a mandotory section
+    SectionIn RO 
+
+    ; Output files to the base installation directory
+    SetOutPath "$INSTDIR"
+
+    ; Only overwrite newer files
+    SetOverwrite ifnewer
+
+    ; Write all the files to the output directory.
+    #for i in low(TFileCategory)..fcWindows:
+    #  for f in items(c.cat[i]):
+         SetOutPath "$INSTDIR\?{splitFile(f).dir.toWin}"
+         File "?{expandFilename(f).toWin}"
+    #  end for
+    #end for
+
+    ; Write out the uninstaller
+    WriteUninstaller "$INSTDIR\uninstaller.exe"
+  SectionEnd
+
+  Section "-Add Registry Keys" RegistrySection
+    ; Write application registry keys
+    WriteRegStr HKCU "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\bin\?{c.name}.exe"
+    WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
+    WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
+    WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\bin\?{c.name}.exe"
+    WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
+    WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
+    ; Reset the output path
+    SetOutPath "$INSTDIR"
+  SectionEnd
+
+  ; Section for adding the shortcuts related to files and applications
+  Section "-Setup Shortcuts" ShortcutsSection
+    !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+      CreateDirectory "$SMPROGRAMS\$ICONS_GROUP"
+
+      #if c.app == appConsole:
+        CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{c.displayName}.lnk" "$INSTDIR\start.bat"
+        CreateShortCut "$DESKTOP\?{c.displayName}.lnk" "$INSTDIR\start.bat"
+      #else:
+        CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{c.displayName}.lnk" "$INSTDIR\?{c.name}.exe"
+        CreateShortCut "$DESKTOP\?{c.displayName}.lnk" "$INSTDIR\?{c.name}.exe"
+      #end if
+
+      ; Add shortcuts for the documentation
+      #for f in items(c.cat[fcDocStart]):
+        CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{splitFile(f).name}.lnk" "$INSTDIR\?{f.toWin}"
+      #end for
+
+      ; Write the shortcut to the uninstaller
+      CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk" "$INSTDIR\uninstaller.exe"
+    !insertmacro MUI_STARTMENU_WRITE_END
+  SectionEnd
+
+  ; Section for adding tools to the PATH variable
+  Section "Setup Path Environment" PathSection
+     ${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\dist\mingw"
+     ${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\bin"
+     ${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\dist\babel"
+  SectionEnd
+
+  ; The downloadable sections. These sections are automatically generated by
+  ; niminst and the template filters.
+  #var i = 0 
+  #for download in c.downloads:
+  #  inc i
+  #  let d = download.split('|')
+  #  if d.len != 5 and d.len != 6:
+  #    quit("download string needs 5..6 parts: " & download)
+  #  end if
+  #  let sectionName = d[0]
+  #  let dir = d[1]
+  #  let zipName = d[2]
+  #  let size = d[3]
+  #  let url = d[4]
+  Section /o "?sectionName" ?{i}Section
+    ; Add the section size to the total size.
+    AddSize ?size
+
+    ; Download the file, and if successful, extract it to the given directory
+    ; otherwise,
+    retry:
+    NSISdl::download "?url" "$TEMP\?zipName"
+    Pop $0
+    ${If} $0 == "success"
+      ZipDLL::extractall "$TEMP\?zipName" "$INSTDIR\?dir"
+      Delete "$TEMP\?zipName"
+    ${Else}
+      MessageBox MB_ICONSTOP|MB_ABORTRETRYIGNORE "Error: $0" IDRETRY retry IDIGNORE ignore
+      abort
+    ${EndIf}
+
+    #  if d.len >= 6:
+    #    let startMenuEntry = d[5]
+    #    let e = splitFile(startMenuEntry).name.capitalize
+      CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{e}.lnk" "$INSTDIR\?dir\?{startMenuEntry.toWin}"
+    #  end if
+
+    ; Shortcuts
+      !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+      !insertmacro MUI_STARTMENU_WRITE_END
+    ignore:
+  SectionEnd
+  #end
+
+;--------------------------------
+; Section Descriptions
+  ; Series of strings describing each section
+  ; LangString DESC_CoreSection ${LANG_ENGLISH} "Core Nim files"
+
+  ; The macros to actually insert the descriptions into the sections.
+  ; Each description above should have a corresponding MUI_DESCRIPTION_TEXT
+  ; macro linking the section to the description.
+  ; !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+  ;   !insertmacro MUI_DESCRIPTION_TEXT ${CoreSection} $(DESC_CoreSection)
+  ; !insertmacro MUI_FUNCTION_DESCRIPTION_END
+
+
+;--------------------------------
+; Uninstaller Sections
+
+  Section "Uninstall"
+    ; Remove previously created shortcuts
+    !insertmacro MUI_STARTMENU_GETFOLDER "Application" $ICONS_GROUP
+    Delete "$DESKTOP\?{c.displayName}.lnk"
+
+    ; Remove installed application files
+    RMDir /r "$SMPROGRAMS\$ICONS_GROUP"
+    RMDir /r "$INSTDIR"
+
+    ; Remove the previously created registry key
+    DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
+    DeleteRegKey HKCU "${PRODUCT_DIR_REGKEY}"
+    SetAutoClose true
+
+    ; Remove entries from the PATH environment variable
+    ${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\dist\mingw"
+    ${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\bin"
+    ${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\dist\babel"
+  SectionEnd
+
+;--------------------------------
+; Function hooks
+
+  Function .onInit
+    ${GetRoot} "$EXEDIR" $R0
+    strCpy $INSTDIR "$R0\?{c.name}"
+  FunctionEnd
\ No newline at end of file
diff --git a/tools/nimweb.nim b/tools/nimweb.nim
index 24ade58fc..6312dace4 100644
--- a/tools/nimweb.nim
+++ b/tools/nimweb.nim
@@ -45,9 +45,10 @@ proc initConfigData(c: var TConfigData) =
   c.gitCommit = "master"
   c.numProcessors = countProcessors()
   # Attempts to obtain the git current commit.
-  let (output, code) = execCmdEx("git log -n 1 --format=%H")
-  if code == 0 and output.strip.len == 40:
-    c.gitCommit = output.strip
+  when false:
+    let (output, code) = execCmdEx("git log -n 1 --format=%H")
+    if code == 0 and output.strip.len == 40:
+      c.gitCommit = output.strip
   c.quotations = initTable[string, tuple[quote, author: string]]()
 
 include "website.tmpl"
@@ -285,8 +286,10 @@ proc buildPdfDoc(c: var TConfigData, destPath: string) =
       exec("pdflatex " & changeFileExt(d, "tex"))
       exec("pdflatex " & changeFileExt(d, "tex"))
       # delete all the crappy temporary files:
-      var pdf = splitFile(d).name & ".pdf"
-      moveFile(dest=destPath / pdf, source=pdf)
+      let pdf = splitFile(d).name & ".pdf"
+      let dest = destPath / pdf
+      removeFile(dest)
+      moveFile(dest=dest, source=pdf)
       removeFile(changeFileExt(pdf, "aux"))
       if existsFile(changeFileExt(pdf, "toc")):
         removeFile(changeFileExt(pdf, "toc"))
@@ -428,4 +431,7 @@ var c: TConfigData
 initConfigData(c)
 parseCmdLine(c)
 parseIniFile(c)
-main(c)
+when false:
+  buildPdfDoc(c, "doc")
+else:
+  main(c)