downloader.nim 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. ## Helper that is run after Nim's installation.
  2. ## We download mirror'ed mingw packages. The originals came from:
  3. ##
  4. ## https://sourceforge.net/projects/mingw-w64/files/Toolchains%20
  5. ## targetting%20Win32/Personal%20Builds/mingw-builds/6.3.0/threads-win32/
  6. ## dwarf/i686-6.3.0-release-win32-dwarf-rt_v5-rev1.7z/download
  7. ## https://sourceforge.net/projects/mingw-w64/files/Toolchains%20
  8. ## targetting%20Win64/Personal%20Builds/mingw-builds/6.3.0/threads-win32/
  9. ## seh/x86_64-6.3.0-release-win32-seh-rt_v5-rev1.7z/download
  10. ##
  11. import
  12. ui, asyncdispatch, httpclient, os, finish, registry, strutils, osproc
  13. type
  14. Actions = object
  15. addToPath, startMenu, mingw, aporia: bool
  16. Controls = object
  17. apply: Button
  18. bar: ProgressBar
  19. lab: Label
  20. const arch = $(sizeof(int)*8)
  21. proc download(pkg: string; c: Controls) {.async.} =
  22. let z = r"..\dist" / pkg & ".7z"
  23. if fileExists(z):
  24. c.lab.text = z & " already exists"
  25. return
  26. c.bar.value = 0
  27. var client = newAsyncHttpClient()
  28. proc onProgressChanged(total, progress, speed: BiggestInt) {.async.} =
  29. c.lab.text = "Downloading " & pkg & " " & $(speed div 1000) & "kb/s"
  30. c.bar.value = clamp(int(progress*100 div total), 0, 100)
  31. client.onProgressChanged = onProgressChanged
  32. await client.downloadFile("https://nim-lang.org/download/" & pkg & ".7z", z)
  33. c.bar.value = 100
  34. let p = osproc.startProcess("7zG.exe", getCurrentDir() / r"..\dist",
  35. ["x", pkg & ".7z"])
  36. if p.waitForExit != 0:
  37. c.lab.text = "Unpacking failed: " & z
  38. proc apply(a: Actions; c: Controls) {.async.} =
  39. if a.mingw:
  40. await download("mingw" & arch, c)
  41. if a.aporia:
  42. await download("aporia-0.4.0", c)
  43. if a.addToPath:
  44. let desiredPath = expandFilename(getCurrentDir() / "bin")
  45. let p = getUnicodeValue(r"Environment", "Path",
  46. HKEY_CURRENT_USER)
  47. var alreadyInPath = false
  48. for x in p.split(';'):
  49. if x.len == 0: continue
  50. let y = try: expandFilename(if x[0] == '"' and x[^1] == '"':
  51. substr(x, 1, x.len-2) else: x)
  52. except: ""
  53. if y == desiredPath: alreadyInPath = true
  54. if not alreadyInPath:
  55. addToPathEnv(desiredPath)
  56. if a.startMenu:
  57. createStartMenuEntry()
  58. c.apply.text = "Quit"
  59. proc main() =
  60. var mainwin = newWindow("Nim installer", 640, 280, true)
  61. mainwin.margined = true
  62. mainwin.onClosing = (proc (): bool = return true)
  63. let box = newVerticalBox(true)
  64. mainwin.setChild(box)
  65. var groupA = newGroup("Actions", true)
  66. box.add(groupA, false)
  67. var innerA = newVerticalBox(true)
  68. groupA.child = innerA
  69. let cbAddToPath = newCheckbox("Add Nim to PATH")
  70. innerA.add cbAddToPath
  71. let cbStartMenu = newCheckbox("Create start menu entry")
  72. innerA.add cbStartMenu
  73. var groupB = newGroup("Optional Components", true)
  74. box.add(groupB, false)
  75. var innerB = newVerticalBox(true)
  76. groupB.child = innerB
  77. let cbMingw = newCheckbox("Download Mingw")
  78. innerB.add cbMingw
  79. let cbAporia = newCheckbox("Download Aporia")
  80. innerB.add cbAporia
  81. var c = Controls(
  82. apply: newButton("Apply"),
  83. bar: newProgressBar(),
  84. lab: newLabel(""))
  85. innerB.add c.apply
  86. innerB.add c.bar
  87. innerB.add c.lab
  88. proc apply() =
  89. c.apply.text = "Abort"
  90. asyncCheck apply(Actions(addToPath: cbAddToPath.checked,
  91. startMenu: cbStartMenu.checked,
  92. mingw: cbMingw.checked,
  93. aporia: cbAporia.checked), c)
  94. c.apply.onclick = proc () =
  95. ui.quit()
  96. system.quit()
  97. c.apply.onclick = apply
  98. show(mainwin)
  99. pollingMainLoop((proc (timeout: int) =
  100. if hasPendingOperations(): asyncdispatch.poll(timeout)), 10)
  101. init()
  102. main()