Advertisement
joebodo

Forums.Installer.lua

Nov 19th, 2016
4,016
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.62 KB | None | 0 0
  1. if not install.testing then
  2.   requireInjector = load(http.get('https://raw.githubusercontent.com/kepler155c/opus/master/sys/apis/injector.lua').readAll())()
  3. end
  4.  
  5. require = requireInjector(getfenv(1))
  6. if package then
  7.   for i = 1, 4 do
  8.     table.remove(package.loaders, 1)
  9.   end
  10. end
  11.  
  12. local Util = require('util')
  13. local Git = require('git')
  14. local UI = require('ui')
  15.  
  16. local currentFile = ''
  17. local currentProgress = 0
  18. local cancelEvent
  19.  
  20. local args = { ... }
  21. local steps = install.steps[args[1] or 'install']
  22.  
  23. if not steps then
  24.   error('Invalid install type')
  25. end
  26.  
  27. local mode = steps[#steps]
  28.  
  29. if UI.term.width < 32 then
  30.   cancelEvent = 'quit'
  31. end
  32.  
  33. local page = UI.Page {
  34.   backgroundColor = colors.cyan,
  35.   titleBar = UI.TitleBar {
  36.     event = cancelEvent,
  37.   },
  38.   scroller = UI.WindowScroller {
  39.     x = 2, y = 3, ey = -4, ex = -2,
  40.   },
  41.   cancelButton = UI.Button {
  42.     x = 2, y = -2,
  43.     text = ' Cancel ',
  44.     event = 'quit',
  45.   },
  46.   previousButton = UI.Button {
  47.     x = -20, y = -2,
  48.     text = '<< Back',
  49.     event = 'previous',
  50.   },
  51.   nextButton = UI.Button {
  52.     x = -10, y = -2,
  53.     text = 'Next >>',
  54.     event = 'next',
  55.   },
  56.   notification = UI.Notification(),
  57.   accelerators = {
  58.     q = 'quit',
  59.   },
  60. }
  61.  
  62. local pages = {
  63.   splash  = UI.ViewportWindow { },
  64.   review  = UI.ViewportWindow { },
  65.   license = UI.ViewportWindow {
  66.     backgroundColor = colors.black,
  67.   },
  68.   files   = UI.Window {
  69.     grid = UI.ScrollingGrid {
  70.       rey = -3,
  71.       columns = {
  72.         { heading = 'Files', key = 'file' },
  73.       },
  74.       sortColumn = 'file',
  75.     },
  76.   },
  77.   install = UI.Window {
  78.     progressBar = UI.ProgressBar {
  79.       y = -1,
  80.     },
  81.   },
  82.   uninstall = UI.Window {
  83.     progressBar = UI.ProgressBar {
  84.       y = -1,
  85.     },
  86.   },
  87. }
  88.  
  89. --[[ Splash ]]--
  90. function pages.splash:enable()
  91.   page.titleBar.title = 'Installer v1.0'
  92.   page.nextButton.text = 'Next >>'
  93.   UI.ViewportWindow.enable(self)
  94. end
  95.  
  96. function pages.splash:draw()
  97.   self:clear()
  98.   self:setCursorPos(1, 1)
  99.   self:print(
  100.     string.format('%s v%s\n', install.title, install.version), nil, colors.yellow)
  101.   self:print(
  102.     string.format('By: %s\n\n%s\n', install.author, install.description))
  103.  
  104.   self.ymax = self.cursorY
  105. end
  106.  
  107. --[[ License ]]--
  108. function pages.license:enable()
  109.   page.titleBar.title = 'License Review'
  110.   page.nextButton.text = 'Accept'
  111.   UI.ViewportWindow.enable(self)
  112. end
  113.  
  114. function pages.license:draw()
  115.   self:clear()
  116.   self:setCursorPos(1, 1)
  117.   self:print(
  118.     string.format('Copyright (c) %s %s\n\n', install.copyrightYear,
  119.                                              install.copyrightHolders),
  120.       nil, colors.yellow)
  121.   self:print(install.license)
  122.  
  123.   self.ymax = self.cursorY + 1
  124. end
  125.  
  126. --[[ Review ]]--
  127. function pages.review:enable()
  128.   if mode == 'uninstall' then
  129.     page.nextButton.text = 'Remove'
  130.     page.titleBar.title = 'Remove Installed Files'
  131.   else
  132.     page.nextButton.text = 'Install'
  133.     page.titleBar.title = 'Download and Install'
  134.   end
  135.   UI.ViewportWindow.enable(self)
  136. end
  137.  
  138. function pages.review:draw()
  139.   self:clear()
  140.   self:setCursorPos(1, 1)
  141.   local y = 1
  142.  
  143.   local text = 'Ready to begin installation.\n\nProceeding will download and install the files to the hard drive.'
  144.   if mode == 'uninstall' then
  145.     text = 'Ready to begin.\n\nProceeding will remove the files previously installed.'
  146.   end
  147.   self:print(text)
  148.  
  149.   self.ymax = self.cursorY + 1
  150. end
  151.  
  152. --[[ Files ]]--
  153. function pages.files:enable()
  154.   page.titleBar.title = 'Review Files'
  155.   page.nextButton.text = 'Next >>'
  156.   self.grid.values = { }
  157.   for k,v in pairs(install.files) do
  158.     table.insert(self.grid.values, { file = k, code = v })
  159.   end
  160.   self.grid:update()
  161.   UI.Window.enable(self)
  162. end
  163.  
  164. function pages.files:draw()
  165.   self:clear()
  166.  
  167.   local function formatSize(size)
  168.     if size >= 1000000 then
  169.       return string.format('%dM', math.floor(size/1000000, 2))
  170.     elseif size >= 1000 then
  171.       return string.format('%dK', math.floor(size/1000, 2))
  172.     end
  173.     return size
  174.   end
  175.  
  176.   if install.diskspace then
  177.  
  178.     local bg = self.backgroundColor
  179.  
  180.     local diskFree = fs.getFreeSpace('/')
  181.     if install.diskspace > diskFree then
  182.       bg = colors.red
  183.     end
  184.  
  185.     local text = string.format('Space Required: %s, Free: %s',
  186.         formatSize(install.diskspace), formatSize(diskFree))
  187.  
  188.     if #text > self.width then
  189.       text = string.format('Space: %s Free: %s',
  190.         formatSize(install.diskspace), formatSize(diskFree))
  191.     end
  192.  
  193.     self:write(1, self.height, Util.widthify(text, self.width), bg)
  194.   end
  195.   self.grid:draw()
  196. end
  197.  
  198. function pages.files:view(url)
  199.  
  200.   local s, m = pcall(function()
  201.     page.notification:info('Downloading')
  202.     page:sync()
  203.     Util.download(url, '/.source')
  204.   end)
  205.   page.notification:disable()
  206.   if s then
  207.     shell.run('edit /.source')
  208.     fs.delete('/.source')
  209.     page:draw()
  210.     page.notification:cancel()
  211.   else
  212.     page.notification:error(m:gsub('.*: (.*)', '%1'))
  213.   end
  214. end
  215.  
  216. function pages.files:eventHandler(event)
  217.   if event.type == 'grid_select' then
  218.     self:view(event.selected.code)
  219.     return true
  220.   end
  221. end
  222.  
  223. local function drawCommon(self)
  224.  
  225.   if currentFile then
  226.     self:write(1, 3, 'File:')
  227.     self:write(1, 4, Util.widthify(currentFile, self.width))
  228.   else
  229.     self:write(1, 3, 'Finished')
  230.   end
  231.   if self.failed then
  232.     self:write(1, 5, Util.widthify(self.failed, self.width), colors.red)
  233.   end
  234.   self:write(1, self.height - 1, 'Progress')
  235.  
  236.   self.progressBar.value = currentProgress
  237.   self.progressBar:draw()
  238.   self:sync()
  239. end
  240.  
  241. --[[ Install ]]--
  242. function pages.install:enable()
  243.  
  244.   page.cancelButton:disable()
  245.   page.previousButton:disable()
  246.   page.nextButton:disable()
  247.  
  248.   page.titleBar.title = 'Installing...'
  249.   page.titleBar.event = nil
  250.  
  251.   UI.Window.enable(self)
  252.  
  253.   page:draw()
  254.   page:sync()
  255.  
  256.   local i = 0
  257.   local numFiles = Util.size(install.files)
  258.   for filename,url in pairs(install.files) do
  259.     currentFile = filename
  260.     currentProgress = i / numFiles * 100
  261.     self:draw(self)
  262.     self:sync()
  263.     local s, m = pcall(function()
  264.       Util.download(url, fs.combine(install.directory or '', filename))
  265.     end)
  266.     if not s then
  267.       self.failed = m:gsub('.*: (.*)', '%1')
  268.       break
  269.     end
  270.     i = i + 1
  271.   end
  272.  
  273.   if not self.failed then
  274.     currentProgress = 100
  275.     currentFile = nil
  276.  
  277.     if install.postInstall then
  278.       local s, m = pcall(function() install.postInstall(page, UI) end)
  279.       if not s then
  280.         self.failed = m:gsub('.*: (.*)', '%1')
  281.       end
  282.     end
  283.   end
  284.  
  285.   page.nextButton.text = 'Exit'
  286.   page.nextButton.event = 'quit'
  287.   if not self.failed and install.rebootAfter then
  288.     page.nextButton.text = 'Reboot'
  289.     page.nextButton.event = 'reboot'
  290.   end
  291.  
  292.   page.nextButton:enable()
  293.   page:draw()
  294.   page:sync()
  295.  
  296.   if not self.failed and Util.key(args, 'automatic') then
  297.     if install.rebootAfter then
  298.       os.reboot()
  299.     else
  300.       UI:exitPullEvents()
  301.     end
  302.   end
  303. end
  304.  
  305. function pages.install:draw()
  306.   self:clear()
  307.   local text = 'The files are being installed'
  308.   if #text > self.width then
  309.     text = 'Installing files'
  310.   end
  311.   self:write(1, 1, text, nil, colors.yellow)
  312.  
  313.   drawCommon(self)
  314. end
  315.  
  316. --[[ Uninstall ]]--
  317. function pages.uninstall:enable()
  318.   page.cancelButton:disable()
  319.   page.previousButton:disable()
  320.   page.nextButton:disable()
  321.  
  322.   page.titleBar.title = 'Uninstalling...'
  323.   page.titleBar.event = nil
  324.  
  325.   page:draw()
  326.   page:sync()
  327.  
  328.   UI.Window.enable(self)
  329.  
  330.   local function pruneDir(dir)
  331.     if #dir > 0 then
  332.       if fs.exists(dir) then
  333.         local files = fs.list(dir)
  334.         if #files == 0 then
  335.           fs.delete(dir)
  336.           pruneDir(fs.getDir(dir))
  337.         end
  338.       end
  339.     end
  340.   end
  341.  
  342.   local i = 0
  343.   local numFiles = Util.size(install.files)
  344.   for k,v in pairs(install.files) do
  345.     currentFile = k
  346.     currentProgress = i / numFiles * 100
  347.     self:draw()
  348.     self:sync()
  349.     fs.delete(k)
  350.     pruneDir(fs.getDir(k))
  351.     i = i + 1
  352.   end
  353.  
  354.   currentProgress = 100
  355.   currentFile = nil
  356.  
  357.   page.nextButton.text = 'Exit'
  358.   page.nextButton.event = 'quit'
  359.   page.nextButton:enable()
  360.  
  361.   page:draw()
  362.   page:sync()
  363. end
  364.  
  365. function pages.uninstall:draw()
  366.   self:clear()
  367.   self:write(1, 1, 'Uninstalling files', nil, colors.yellow)
  368.   drawCommon(self)
  369. end
  370.  
  371. function page:eventHandler(event)
  372.   if event.type == 'next' then
  373.     self.scroller:nextChild()
  374.     self:draw()
  375.  
  376.   elseif event.type == 'previous' then
  377.     self.scroller:prevChild()
  378.     self:draw()
  379.  
  380.   elseif event.type == 'reboot' then
  381.     os.reboot()
  382.  
  383.   elseif event.type == 'quit' then
  384.     UI:exitPullEvents()
  385.  
  386.   else
  387.     return UI.Page.eventHandler(self, event)
  388.   end
  389.   return true
  390. end
  391.  
  392. function page:enable()
  393.   UI.Page.enable(self)
  394.   self:setFocus(page.nextButton)
  395.   if UI.term.width < 32 then
  396.     page.cancelButton:disable()
  397.     page.previousButton.x = 2
  398.   end
  399. end
  400.  
  401. if install.gitUser then
  402.   local gitFiles = Git.list(string.format('%s/%s/%s', install.gitUser, install.gitRepo, install.gitBranch))
  403.   install.files = { }
  404.   install.diskspace = 0
  405.   for path, entry in pairs(gitFiles) do
  406.     install.files[path] = entry.url
  407.     install.diskspace = install.diskspace + entry.size
  408.   end
  409. end
  410.  
  411. if not install.files or Util.empty(install.files) then
  412.   error('File list is missing or empty')
  413. end
  414.  
  415. for _,v in ipairs(steps) do
  416.   if not pages[v] then
  417.     error('Invalid step: ' .. v)
  418.   end
  419.   table.insert(page.scroller.children, pages[v])
  420. end
  421. page.scroller:initChildren()
  422.  
  423. if Util.key(steps, 'install') and install.preInstall then
  424.   install.preInstall(page, UI)
  425. end
  426.  
  427. --UI:disableEffects()
  428. UI:setPage(page)
  429. UI:pullEvents()
  430. UI.term:reset()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement