Tinybang_Studio

Untitled

Jun 21st, 2020
433
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local unpack = unpack or table.unpack
  2.  
  3. os.unloadAPI("backpack")
  4.  
  5. local args = {...}
  6.  
  7. local opwords = {
  8.     install = true,
  9.     remove = true,
  10.     update = true,
  11.     ["install-help"] = true,
  12.     ["remove-help"] = true,
  13.     ["update-help"] = true,
  14.     list = true,
  15.     search = true,
  16.     bootstrap = true,
  17. }
  18.  
  19. local argwords = {
  20.     fetch = true,
  21.     force = true,
  22.     auto = true,
  23.     --target = 1,
  24. }
  25.  
  26. if #args < 1 or (not opwords[args[1]] and not argwords[args[1]]) then
  27.     io.write("Usage:\n")
  28.     io.write("packman [options] install <package name[s]>\n")
  29.     io.write("packman [options] update <package name[s]>\n")
  30.     io.write("packman [options] remove <package name[s]>\n")
  31.     io.write("packman [options] list [pattern]\n")
  32.     io.write("packman [options] search [pattern]\n")
  33.     io.write("packman bootstrap\n")
  34.     io.write("packman [options] install-help <package name[s]>\n")
  35.     io.write("packman [options] update-help <package name[s]>\n")
  36.     io.write("packman [options] remove-help <package name[s]>\n")
  37.     io.write("\n")
  38.     io.write("Options:\n")
  39.     io.write("fetch\n")
  40.     io.write("  Update repository and package lists before performing operations (can be used without an operation)\n")
  41.     io.write("force\n")
  42.     io.write("  Force requested operation, even if it appears to be unnecessary; answer all questions with yes\n")
  43.     io.write("auto\n")
  44.     io.write("  Automatically answer yes when manipulating packages\n")
  45.     --io.write("target <directory>\n")
  46.     --io.write("  Set root directory to install packages in\n")
  47.     return
  48. end
  49.  
  50. local config = {}
  51.  
  52. function loadConfig()
  53.     local path = "/etc/packman/packman.conf"
  54.     --load a configuration file, given a fully-resolved path and an optional environment.
  55.     if not fs.exists(path) or fs.isDir(path) then return nil, "not a file" end
  56.     local env
  57.     if not _env then
  58.         --if we were not provided an environment, create one.
  59.         env = setmetatable({}, {__index = _G})
  60.     else
  61.         env = _env
  62.     end
  63.     local fn, err = loadfile(path)
  64.     if fn then
  65.         setfenv(fn, env)
  66.         local success, err = pcall(fn)
  67.         if success then
  68.             --strip the metatable from the environment before returning it.
  69.             config = setmetatable(env, {})
  70.         else
  71.             return nil, err
  72.         end
  73.     else
  74.         return nil, err
  75.     end
  76. end
  77.  
  78. function saveConfig()
  79.     local path = "/etc/packman/packman.conf"
  80.     if not config or type(config) ~= "table" then return nil, "Not a configuration" end
  81.     local handle = io.open(path, "w")
  82.     if handle then
  83.         for k, v in pairs(config) do
  84.             local success, str = pcall(textutils.serialize, v)
  85.             if success then
  86.                 handle:write(k.." = "..str.."\n\n")
  87.             end
  88.         end
  89.         handle:close()
  90.     else
  91.         return nil, "Could not write configuration."
  92.     end
  93. end
  94.  
  95. loadConfig()
  96.  
  97. local mode = ""
  98. local forced = false
  99. local target = "/"
  100. local fetch = false
  101. local auto = false
  102. local argState = nil
  103. local argCount = 0
  104. local operation = {options = {}, arguments = {}}
  105.  
  106. --lower all arguments
  107. for i = 1, #args do
  108.     args[i] = string.lower(args[i])
  109.     if argState == nil and args[i] == "fetch" then fetch = true end
  110.     if argState == nil and args[i] == "force" then forced = true end
  111.     if argState == nil and args[i] == "auto" then auto = true end
  112.  
  113.     if argwords[args[i]] and type(argwords[args[i]]) == "number" then
  114.         operation.options[args[i]] = {}
  115.         argState = args[i]
  116.         argCount = argwords[args[i]]
  117.     elseif opwords[args[i]] then
  118.         mode = args[i]
  119.         if mode == "bootstrap" then fetch = false break end
  120.         argState = "arguments"
  121.         argCount = 0
  122.     elseif argState and argCount > 0 then
  123.         --option arguments
  124.         table.insert(operation.options[argState], args[i])
  125.         argCount = argCount - 1
  126.         if argCount == 0 then argState = nil end
  127.     elseif argState == "arguments" then
  128.         --operation arguments
  129.         table.insert(operation.arguments, args[i])
  130.     end
  131. end
  132.  
  133. if operation.options.target then
  134.     target = operation.options.target[1]
  135. end
  136.  
  137. local function resetScreen()
  138.     term.setTextColor(colors.white)
  139.     term.setBackgroundColor(colors.black)
  140. end
  141.  
  142. local function printError(errorText)
  143.     if term.isColor() then term.setTextColor(colors.red) end
  144.     io.write(errorText.."\n")
  145.     term.setTextColor(colors.white)
  146.     error()
  147. end
  148.  
  149. local function printWarning(warningText)
  150.     if term.isColor() then term.setTextColor(colors.yellow) end
  151.     io.write(warningText.."\n")
  152.     term.setTextColor(colors.white)
  153. end
  154.  
  155. local function printInformation(infoText)
  156.     if term.isColor() then term.setTextColor(colors.lime) end
  157.     io.write(infoText.."\n")
  158.     term.setTextColor(colors.white)
  159. end
  160.  
  161. local function getUserInput(default)
  162.     if auto then
  163.         return default
  164.     else
  165.         return io.read()
  166.     end
  167. end
  168.  
  169. local function loadPackageAPI()
  170.     if not backpack then if shell.resolveProgram("backpack") then os.loadAPI(shell.resolveProgram("backpack")) elseif fs.exists("usr/apis/backpack") then os.loadAPI("usr/apis/backpack") elseif not (fetch or mode == "bootstrap") then error("Could not load backpack API!") end end
  171.  
  172.     if backpack then
  173.         resetScreen()
  174.         io.write("Loading database...\n")
  175.         backpack.installRoot = target
  176.  
  177.         local co = coroutine.create(backpack.load)
  178.         local event, filter, passback = {}
  179.         while true do
  180.             if (filter and (filter == event[1] or event[1] == "terminate")) or not filter then
  181.                 passback = {coroutine.resume(co, unpack(event))}
  182.             end
  183.             if passback[1] == false then printWarning(passback[2]) end
  184.             if coroutine.status(co) == "dead" then break end
  185.             filter = nil
  186.             if passback and passback[1] and passback[2] then
  187.                 filter = passback[2]
  188.             end
  189.             event = {os.pullEventRaw()}
  190.             if event[1] == "package_status" then
  191.                 if event[2] == "info" then
  192.                     printInformation(event[3])
  193.                 elseif event[2] == "warning" then
  194.                     printWarning(event[3])
  195.                 elseif event[2] == "error" then
  196.                     printError(event[3])
  197.                 end
  198.             end
  199.         end
  200.     end
  201. end
  202.  
  203. loadPackageAPI()
  204.  
  205. local categoryList = {}
  206. local categorySorted = {}
  207.  
  208. if fetch then
  209.     local queue
  210.     if backpack then
  211.         queue = backpack.newTransactionQueue("main/backpack")
  212.     end
  213.     io.write("Fetching Repository List\n")
  214.     local repolistContent = ""
  215.     remoteHandle = http.get("https://raw.githubusercontent.com/lyqyd/cc-packman/master/repolist")
  216.     if remoteHandle then
  217.         repolistContent = remoteHandle.readAll()
  218.         if queue then
  219.             queue:makeDir("/etc")
  220.             queue:addFile("/etc/repolist", repolistContent)
  221.         else
  222.             local fileHandle = io.open("/etc/repolist", "w")
  223.             if fileHandle then
  224.                 fileHandle:write(repolistContent)
  225.                 fileHandle:close()
  226.             else
  227.                 printWarning("Could not write file /etc/repolist")
  228.             end
  229.         end
  230.         remoteHandle.close()
  231.     else
  232.         printWarning("Could not retrieve remote file.")
  233.     end
  234.  
  235.     if fs.exists("/etc/custom-repolist") then
  236.         local fileHandle = io.open("/etc/custom-repolist", "r")
  237.         if fileHandle then
  238.             repolistContent = repolistContent.."\n"..fileHandle:read("*a")
  239.             fileHandle:close()
  240.         end
  241.     end
  242.  
  243.     if repolistContent then
  244.         if queue then
  245.             queue:makeDir("/etc/repositories")
  246.         else
  247.             if not fs.exists("/etc/repositories") then fs.makeDir("/etc/repositories") end
  248.         end
  249.  
  250.         for line in string.gmatch(repolistContent, "([^\n]+)\n?") do
  251.             local file, url = string.match(line, "^(%S*)%s*(.*)")
  252.             if file and url then
  253.                 io.write("Fetching Repository: "..file.."\n")
  254.                 local remoteHandle = http.get(url)
  255.                 if remoteHandle then
  256.                     if queue then
  257.                         queue:addFile(fs.combine("/etc/repositories", file), remoteHandle.readAll())
  258.                     else
  259.                         local fileHandle = io.open(fs.combine("/etc/repositories", file), "w")
  260.                         if fileHandle then
  261.                             fileHandle:write(remoteHandle.readAll())
  262.                             fileHandle:close()
  263.                         else
  264.                             printWarning("Could not write file: "..fs.combine("/etc/repositories", file))
  265.                         end
  266.                     end
  267.                     remoteHandle.close()
  268.                 else
  269.                     printWarning("Could not retrieve remote file: "..file)
  270.                 end
  271.             end
  272.         end
  273.     end
  274.  
  275.     if queue then
  276.         queue:finish()
  277.     end
  278.  
  279.     fetch = false
  280.  
  281.     if #mode > 0 then
  282.         --reload backpack API.
  283.         os.unloadAPI("backpack")
  284.         loadPackageAPI()
  285.     end
  286. end
  287.  
  288. if #mode > 0 and backpack then
  289.     for n, v in pairs(backpack.list) do
  290.         if v.category then
  291.             for category in pairs(v.category) do
  292.                 if not categoryList[category] then
  293.                     categoryList[category] = {[n] = true}
  294.                     table.insert(categorySorted, category)
  295.                 else
  296.                     categoryList[category][n] = true
  297.                 end
  298.             end
  299.         end
  300.     end
  301.     table.sort(categorySorted)
  302.  
  303.     local badPackages = {}
  304.     --flesh out dependencies
  305.     for pName, pData in pairs(backpack.list) do
  306.         if pData.dependencies then
  307.             dependencies, errmsg = backpack.findDependencies(pName, {})
  308.             if not dependencies then
  309.                 --if dependencies could not be resolved, remove the backpack.
  310.                 printWarning("Could not resolve dependency on "..errmsg.." in package "..pName)
  311.                 table.insert(badPackages, pName)
  312.             else
  313.                 pData.dependencies = dependencies
  314.             end
  315.         end
  316.     end
  317.     --actual package removal and short-name lookup cleanup.
  318.     for _, pack in pairs(badPackages) do
  319.         local entry = backpack.list[pack]
  320.         local name = entry.name
  321.         local others, key = false
  322.         for k, v in pairs(backpack.list[name]) do
  323.             if v == entry then
  324.                 key = k
  325.             else
  326.                 others = true
  327.             end
  328.         end
  329.         if others then
  330.             backpack.list[name][key] = nil
  331.         else
  332.             backpack.list[name] = nil
  333.         end
  334.         backpack.list[pack] = nil
  335.     end
  336. end
  337.  
  338. local function lookupPackage(name, installedOnly)
  339.     if backpack.list[name] and not backpack.list[name].dependencies then
  340.         local options = {}
  341.         if installedOnly and backpack.installed[name] then
  342.             for name, pack in pairs(backpack.installed[name]) do
  343.                 table.insert(options, name)
  344.             end
  345.         elseif installedOnly then
  346.             --using installedOnly, but no packages of that name are installed.
  347.             return false
  348.         else
  349.             for name, pack in pairs(backpack.list[name]) do
  350.                 table.insert(options, name)
  351.             end
  352.         end
  353.         if #options > 1 then
  354.             io.write("Package "..name.." is ambiguous.\n")
  355.             for i = 1, #options do
  356.                 write(tostring(i)..": "..options[i].."  ")
  357.             end
  358.             io.write("\n")
  359.             io.write("Select option: \n")
  360.             local selection = getUserInput("1")
  361.             if tonumber(selection) and options[tonumber(selection)] then
  362.                 return options[tonumber(selection)].."/"..name
  363.             end
  364.         elseif #options == 1 then
  365.             return options[1].."/"..name
  366.         else
  367.             return false
  368.         end
  369.     elseif backpack.list[name] then
  370.         --since it must have a dependencies table, the name is already fully unique.
  371.         return name
  372.     else
  373.         return false
  374.     end
  375. end
  376.  
  377. local function raw_package_operation(name, funcName)
  378.     local pack = backpack.list[name]
  379.     if not pack then return nil, "No such package" end
  380.     local co = coroutine.create(function() return pack[funcName](pack, getfenv()) end)
  381.     local event, filter, passback = {}
  382.     while true do
  383.         if (filter and (filter == event[1] or event[1] == "terminate")) or not filter then
  384.             passback = {coroutine.resume(co, unpack(event))}
  385.         end
  386.         if passback[1] == false then printWarning(passback[2]) end
  387.         if coroutine.status(co) == "dead" then return unpack(passback, 2) end
  388.         filter = nil
  389.         if passback and passback[1] and passback[2] then
  390.             filter = passback[2]
  391.         end
  392.         event = {os.pullEventRaw()}
  393.         if event[1] == "package_status" then
  394.             if event[2] == "info" then
  395.                 printInformation(event[3])
  396.             elseif event[2] == "warning" then
  397.                 printWarning(event[3])
  398.             elseif event[2] == "error" then
  399.                 printError(event[3])
  400.             end
  401.         end
  402.     end
  403. end
  404.  
  405. local function install(name)
  406.     if config.manageHelp then
  407.         return raw_package_operation(name, "installFiles") and raw_package_operation(name, "installHelp") and raw_package_operation(name, "finalizeInstall")
  408.     else
  409.         return raw_package_operation(name, "install")
  410.     end
  411. end
  412.  
  413. local function installHelp(name)
  414.     return raw_package_operation(name, "installHelp")
  415. end
  416.  
  417. local function remove(name)
  418.     if config.manageHelp then
  419.         return raw_package_operation(name, "removeHelp") and raw_package_operation(name, "remove")
  420.     else
  421.         return raw_package_operation(name, "remove")
  422.     end
  423. end
  424.  
  425. local function removeHelp(name)
  426.     return raw_package_operation(name, "removeHelp")
  427. end
  428.  
  429. local function upgrade(name)
  430.     if config.manageHelp then
  431.         return raw_package_operation(name, "upgradeFiles") and raw_package_operation(name, "upgradeHelp") and raw_package_operation(name, "finalizeUpgrade")
  432.     else
  433.         return raw_package_operation(name, "upgrade")
  434.     end
  435. end
  436.  
  437. local function upgradeHelp(name)
  438.     return raw_package_operation(name, "upgradeHelp")
  439. end
  440.  
  441. if mode == "bootstrap" then
  442.     --initial setup, results in main/packman and main/backpack packages being installed
  443.     if not backpack or backpack.list["main/packman"] == nil then
  444.         --grab the backpack API, since we have no transaction queue yet.
  445.         io.write("Updating Backpack API\n")
  446.         remoteHandle = http.get("https://raw.githubusercontent.com/lyqyd/cc-packman/master/backpack")
  447.         local apiContents = ""
  448.         if remoteHandle then
  449.             if not fs.exists("/usr/apis") then fs.makeDir("/usr/apis") end
  450.             local fileHandle = io.open("/usr/apis/backpack", "w")
  451.             if fileHandle then
  452.                 apiContents = remoteHandle.readAll()
  453.                 fileHandle:write(apiContents)
  454.                 fileHandle:close()
  455.             else
  456.                 printWarning("Could not write file /usr/apis/backpack")
  457.             end
  458.             remoteHandle.close()
  459.         else
  460.             printWarning("Could not retrieve remote file.")
  461.         end
  462.  
  463.         io.write("Fetching main package list\n")
  464.         remoteHandle = http.get("https://raw.githubusercontent.com/lyqyd/cc-packman/master/packlist")
  465.         local packlistContents = ""
  466.         if remoteHandle then
  467.             if not fs.exists("/etc/repositories") then fs.makeDir("/etc/repositories") end
  468.             local fileHandle = io.open("/etc/repositories/main", "w")
  469.             if fileHandle then
  470.                 packlistContents = remoteHandle.readAll()
  471.                 fileHandle:write(packlistContents)
  472.                 fileHandle:close()
  473.             else
  474.                 printWarning("Could not write file /etc/repositories/main")
  475.             end
  476.             remoteHandle.close()
  477.         else
  478.             printWarning("Could not retrieve remote file.")
  479.         end
  480.  
  481.         os.unloadAPI("backpack")
  482.         loadPackageAPI()
  483.         if not backpack then printError("Backpack API required for bootstrap!") end
  484.  
  485.         --re-do the file writes for the files above so they end up in the package file list.
  486.         local queue = backpack.newTransactionQueue("main/backpack")
  487.         queue:makeDir("/usr")
  488.         queue:makeDir("/usr/apis")
  489.         queue:addFile("/usr/apis/backpack", apiContents)
  490.         queue:makeDir("/etc")
  491.         queue:makeDir("/etc/repositories")
  492.         queue:addFile("/etc/repositories/main", packlistContents)
  493.         queue:finish()
  494.     end
  495.  
  496.     backpack.list["main/packman"]:install(getfenv())
  497.  
  498.     --reload backpack API.
  499.     os.unloadAPI("backpack")
  500.     loadPackageAPI()
  501.  
  502.     config.manageHelp = false
  503.     saveConfig()
  504. elseif mode == "install" then
  505.     if #operation.arguments >= 1 then
  506.         local installList = {}
  507.         for packageNumber, packageName in ipairs(operation.arguments) do
  508.             local result = lookupPackage(packageName)
  509.             if not result then
  510.                 printWarning("Could not install package "..packageName..".")
  511.             else
  512.                 for k,v in pairs(backpack.list[result].dependencies) do
  513.                     if not backpack.installed[k] then
  514.                         installList[k] = true
  515.                     else
  516.                         if k == result then
  517.                             printInformation("Package "..k.." already installed")
  518.                         else
  519.                             printInformation("Dependency "..k.." already installed")
  520.                         end
  521.                     end
  522.                 end
  523.             end
  524.         end
  525.         local installString = ""
  526.         for k, v in pairs(installList) do
  527.             installString = installString..k.." "
  528.         end
  529.         if #installString > 0 then
  530.             if not forced then
  531.                 io.write("The following packages will be installed: "..installString.."\n")
  532.                 io.write("Continue? (Y/n)\n")
  533.                 local input = getUserInput("y")
  534.                 if string.sub(input:lower(), 1, 1) == "n" then
  535.                     return true
  536.                 end
  537.             end
  538.             for packageName in pairs(installList) do
  539.                 if not install(packageName) then
  540.                     printWarning("Could not "..mode.." package "..packageName)
  541.                 end
  542.             end
  543.         end
  544.     end
  545. elseif mode == "update" then
  546.     local updateList = {}
  547.     local installList = {}
  548.     if #operation.arguments >= 1 then
  549.         for _, name in ipairs(operation.arguments) do
  550.             local result = lookupPackage(name, true)
  551.             if result then
  552.                 table.insert(updateList, result)
  553.             end
  554.         end
  555.     else
  556.         for k, v in pairs(backpack.installed) do
  557.             if v.files then
  558.                 --filters out the disambiguation entries.
  559.                 table.insert(updateList, k)
  560.                 for name, info in pairs(backpack.list[k].dependencies) do
  561.                     if not backpack.installed[name] then
  562.                         installList[name] = true
  563.                     end
  564.                 end
  565.             end
  566.         end
  567.     end
  568.     local installString = ""
  569.     for k, v in pairs(installList) do
  570.         installString = installString..k.." "
  571.     end
  572.     if not forced then
  573.         for i = #updateList, 1, -1 do
  574.             if backpack.installed[updateList[i]].version == backpack.list[updateList[i]].version then
  575.                 table.remove(updateList, i)
  576.             end
  577.         end
  578.     end
  579.     if #updateList > 0 or #installString > 0 then
  580.         local updateString = ""
  581.         for i = 1, #updateList do
  582.             updateString = updateString..updateList[i].." "
  583.         end
  584.         if not forced then
  585.             io.write("The following packages will be updated: "..updateString.."\n")
  586.             if #installString > 0 then
  587.                 io.write("The following packages will also be installed: "..installString.."\n")
  588.             end
  589.             io.write("Continue? (Y/n)\n")
  590.             local input = getUserInput("y")
  591.             if string.sub(input:lower(), 1, 1) == "n" then
  592.                 return true
  593.             end
  594.         end
  595.         local failureCount = 0
  596.         for packageName in pairs(installList) do
  597.             if not install(packageName) then
  598.                 printWarning("Could not install package "..packageName)
  599.             end
  600.         end
  601.         for _, packageName in pairs(updateList) do
  602.             if not upgrade(packageName) then
  603.                 printWarning("Package "..packageName.." failed to update.")
  604.                 failureCount = failureCount + 1
  605.             end
  606.         end
  607.         if failureCount > 0 then
  608.             printWarning(failureCount.." packages failed to update.")
  609.         else
  610.             printInformation("Update complete!")
  611.         end
  612.     else
  613.         io.write("Nothing to do!\n")
  614.         return true
  615.     end
  616. elseif mode == "remove" then
  617.     if #operation.arguments >= 1 then
  618.         local packageList = {}
  619.         for _, name in ipairs(operation.arguments) do
  620.             local result = lookupPackage(name, true)
  621.             if result then
  622.                 table.insert(packageList, result)
  623.             end
  624.         end
  625.         dependeesList = {}
  626.         --find packages which depend on the packages we are removing.
  627.         for pName, pData in pairs(backpack.installed) do
  628.             if pData.version then
  629.                 if not packageList[pName] then
  630.                     for dName in pairs(backpack.list[pName].dependencies) do
  631.                         for _, packName in pairs(packageList) do
  632.                             if packName == dName then
  633.                                 dependeesList[pName] = true
  634.                                 break
  635.                             end
  636.                         end
  637.                         if dependeesList[pName] then
  638.                             break
  639.                         end
  640.                     end
  641.                 end
  642.             end
  643.         end
  644.         local removeString = ""
  645.         local dependeesString = ""
  646.         for i = 1, #packageList do
  647.             removeString = removeString..packageList[i].." "
  648.             if dependeesList[packageList[i]] then
  649.                 dependeesList[packageList[i]] = nil
  650.             end
  651.         end
  652.         for dName in pairs(dependeesList) do
  653.             dependeesString = dependeesString..dName.." "
  654.         end
  655.         if #removeString > 0 then
  656.             if not forced then
  657.                 io.write("The following packages will be removed: "..removeString.."\n")
  658.                 if #dependeesString > 0 then
  659.                     io.write("The following packages will also be removed due to missing dependencies: "..dependeesString.."\n")
  660.                 end
  661.                 io.write("Continue? (y/N)\n")
  662.                 local input = getUserInput("y")
  663.                 if string.sub(input:lower(), 1, 1) ~= "y" then
  664.                     return true
  665.                 end
  666.             end
  667.             for pName in pairs(dependeesList) do
  668.                 printInformation("Removing "..pName)
  669.                 remove(pName)
  670.             end
  671.             for _, pName in pairs(packageList) do
  672.                 printInformation("Removing "..pName)
  673.                 remove(pName)
  674.             end
  675.         else
  676.             io.write("Nothing to do!\n")
  677.         end
  678.     end
  679. elseif mode == "install-help" then
  680.     if #operation.arguments >= 1 then
  681.         local installString = ""
  682.         for packageNumber, packageName in ipairs(operation.arguments) do
  683.             local result = lookupPackage(packageName)
  684.             if not result then
  685.                 printWarning("Could not find package "..packageName..".")
  686.             else
  687.                 installString = installString..result.." "
  688.             end
  689.         end
  690.         if #installString > 0 then
  691.             if not forced then
  692.                 io.write("The following packages' help files will be installed: "..installString.."\n")
  693.                 io.write("Continue? (Y/n)\n")
  694.                 local input = getUserInput("y")
  695.                 if string.sub(input:lower(), 1, 1) == "n" then
  696.                     return true
  697.                 end
  698.             end
  699.             for packageName in string.gmatch(installString, "%S+") do
  700.                 if not installHelp(packageName) then
  701.                     printWarning("Could not install help files for package "..packageName)
  702.                 end
  703.             end
  704.         end
  705.     end
  706. elseif mode == "upgrade-help" then
  707.     if #operation.arguments >= 1 then
  708.         local upgradeString = ""
  709.         for packageNumber, packageName in ipairs(operation.arguments) do
  710.             local result = lookupPackage(packageName)
  711.             if not result then
  712.                 printWarning("Could not find package "..packageName..".")
  713.             else
  714.                 upgradeString = upgradeString..result.." "
  715.             end
  716.         end
  717.         if #upgradeString > 0 then
  718.             if not forced then
  719.                 io.write("The following packages' help files will be installed: "..upgradeString.."\n")
  720.                 io.write("Continue? (Y/n)\n")
  721.                 local input = getUserInput("y")
  722.                 if string.sub(input:lower(), 1, 1) == "n" then
  723.                     return true
  724.                 end
  725.             end
  726.             for packageName in string.gmatch(upgradeString, "%S+") do
  727.                 if not installHelp(packageName) then
  728.                     printWarning("Could not install help files for package "..packageName)
  729.                 end
  730.             end
  731.         end
  732.     end
  733. elseif mode == "remove-help" then
  734.     if #operation.arguments >= 1 then
  735.         local removeString = ""
  736.         for _, name in ipairs(operation.arguments) do
  737.             local result = lookupPackage(name, true)
  738.             if not result then
  739.                 printWarning("Could not find package "..name)
  740.             else
  741.                 removeString = removeString..result.." "
  742.             end
  743.         end
  744.         if #removeString > 0 then
  745.             if not forced then
  746.                 io.write("The following packages' help files will be removed: "..removeString.."\n")
  747.                 io.write("Continue? (y/N)\n")
  748.                 local input = getUserInput("y")
  749.                 if string.sub(input:lower(), 1, 1) ~= "y" then
  750.                     return true
  751.                 end
  752.             end
  753.             for packageName in string.gmatch(removeString, "%S+") do
  754.                 printInformation("Removing help files for package "..packageName)
  755.                 removeHelp(packageName)
  756.             end
  757.         else
  758.             io.write("Nothing to do!\n")
  759.         end
  760.     end
  761. elseif mode == "list" then
  762.     --list all installed packages
  763.     local match = ".*"
  764.     if #operation.arguments == 1 then
  765.         --list with matching.
  766.         match = operation.arguments[1]
  767.     end
  768.     for name, info in pairs(backpack.installed) do
  769.         if info.version then
  770.             if string.match(name, match) then
  771.                 io.write(name.." "..info.version.."\n")
  772.             end
  773.         end
  774.     end
  775. elseif mode == "search" then
  776.     --search all available packages
  777.     local match = ".*"
  778.     if #operation.arguments == 1 then
  779.         --search using a match
  780.         match = operation.arguments[1]
  781.     end
  782.     for name, info in pairs(backpack.list) do
  783.         if info.version then
  784.             if string.match(name, match) then
  785.                 io.write((backpack.installed[name] and "I " or "A " )..name.." "..info.version.."\n")
  786.             end
  787.         end
  788.     end
  789. end
Add Comment
Please, Sign In to add comment