Advertisement
ColdIV

dpm

Jan 7th, 2022 (edited)
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 15.73 KB | None | 0 0
  1. ---------------------------------------------------------
  2. --- Dependency Manager For CC: Tweaked Scripts ----------
  3. ------------------------------------ by ColdIV ----------
  4. ---------------------------------------------------------
  5. --[ SOURCE ]------------------------( up-to-date )-------
  6. --[ https://github.com/ColdIV/dependency-manager ]-------
  7. ---------------------------------------------------------
  8. --[ INSTALL ]--------------------------------------------
  9. --[ pastebin run FuQ3WvPs KqhwihZr dpm ]-----------------
  10. ---------------------------------------------------------
  11. --[[ Usage [Arguments] ----------------------------------
  12. dpm install <name in git repo>
  13. dpm install <name> <pastebin code>
  14. dpm install <name@pastebin code>
  15. dpm update <name>
  16. dpm update all
  17. dpm remove <name>
  18. dpm remove all
  19. dpm list
  20. dpm config
  21. dpm config <name> <value>
  22. dpm help
  23. dpm help <argument name>
  24. --]]-----------------------------------------------------
  25. --[[ Example [yourScript.lua] ---------------------------
  26. local dpm = require("dpm")
  27. local scriptName = dpm:load("scriptName")
  28. --- or, to install if script cannot be found:
  29. local scriptName = dpm:load("scriptName@pastebinCode")
  30. --]]-----------------------------------------------------
  31. local args = {...}
  32.  
  33. --- Helper functions
  34. -- src: https://stackoverflow.com/a/2705804/10495683
  35. function tablelength (T)
  36.     local count = 0
  37.     for _ in pairs(T) do count = count + 1 end
  38.     return count
  39. end
  40.  
  41. -- src: https://tweaked.cc/library/cc.shell.completion.html [modified]
  42. local completion = require "cc.shell.completion"
  43. local complete = completion.build(
  44.     { completion.choice, { "install", "update", "remove", "list", "config", "help" } },
  45.     completion.dir,
  46.     { completion.file, many = true }
  47. )
  48. shell.setCompletionFunction("dpm.lua", complete)
  49. --------------------
  50.  
  51. local dpm = {}
  52.  
  53. --- Config
  54. dpm.config = {
  55.     ["verbose"] = false,
  56.     ["logDate"] = true,
  57.     ["writeLogFile"] = true,
  58.     ["logFilePath"] = "log.txt",
  59.     ["printPrefix"] = "[dpm] ",
  60.     ["code"] = "KqhwihZr",
  61.     ["installScriptCode"] = "FuQ3WvPs",
  62.     ["scriptListPath"] = "scripts.json",
  63.     ["scriptPath"] = "libs/",
  64.     ["programPath"] = "programs/",
  65.     ["gitRepo"] = "ColdIV/dependency-manager/",
  66.     ["gitBranch"] = "master",
  67.     ["rawGit"] = "https://raw.githubusercontent.com/"
  68. }
  69. ----------
  70.  
  71. dpm.dpmPath = "cldv/dpm/"
  72. dpm.configFilePath = dpm.dpmPath .. "config.json"
  73. dpm.reservedNames = {
  74.     "all"
  75. }
  76. dpm.scripts = {}
  77. dpm.commandHelp = {
  78.     ["install"] = "install <name in git repo>\tInstalls the given script from the repository\ninstall <name> <code>\tInstalls the given script\ninstall <name@code>\t\tInstalls the given script",
  79.     ["update"] = "update all\t\t\t\t\tUpdates all scripts\nupdate <name>\t\tUpdates script by name",
  80.     ["remove"] = "remove all\t\t\t\t\tRemoves all scripts\nremove <name>\t\tRemoves script by name",
  81.     ["list"] = "list\t\t\tLists all installed scripts",
  82.     ["get"] = "get <name in git repo>\tDownloads the given program from the repository\nget <name@pastebin code>\tDownloads the given program from pastebin",
  83.     ["help"] = "help\t\t\tShows a list of all available arguments",
  84.     ["config"] = "config\t\t\t\t\tShows a list of all available arguments\nconfig name value\t\tSets the value of the variable"
  85. }
  86.  
  87. function dpm:log (message)
  88.     local datetime = ""
  89.     if self.config.logDate then datetime = os.date("[%Y-%m-%d %H:%M:%S] ") end
  90.     if self.config.verbose then print (self.config.printPrefix .. message) end
  91.  
  92.     if self.config.writeLogFile then
  93.         local file = fs.open(self.dpmPath .. self.config.logFilePath, "a")
  94.         file.write (datetime .. message .. "\n")
  95.         file.close()
  96.     end
  97. end
  98.  
  99. function dpm:saveScripts ()
  100.     self:log("Saving scripts...")
  101.     local file = fs.open(self.dpmPath .. self.config.scriptListPath, "w")
  102.     file.write (textutils.serializeJSON(self.scripts))
  103.     file.close()
  104.     self:log("Done")
  105. end
  106.  
  107. function dpm:getScripts ()
  108.     self:log("Getting scripts...")
  109.     local file = fs.open(self.dpmPath .. self.config.scriptListPath, "r")
  110.  
  111.     if not file then
  112.         self:log("Error! File does not exist: " .. self.dpmPath .. self.config.scriptListPath)
  113.         self:saveScripts()
  114.     else
  115.         dpm.scripts = textutils.unserializeJSON(file.readAll()) or {}
  116.         self:log("Found " .. tablelength(dpm.scripts) .. " script(s)!")
  117.         self:log("Done")
  118.         file.close()
  119.     end
  120. end
  121.  
  122. function dpm:getNameCode (argument)
  123.     local separator = string.find(argument, "@")
  124.     if not separator then return nil end
  125.     local name = string.sub(argument, 1, separator - 1)
  126.     local code = string.sub(argument, separator + 1)
  127.     return name, code
  128. end
  129.  
  130. function dpm:getGitURL (name, gitDirectory)
  131.     return self.config.rawGit .. self.config.gitRepo .. self.config.gitBranch .. "/" .. gitDirectory .. name .. ".lua"
  132. end
  133.  
  134. function dpm:downloadGit (name, gitDirectory, path)
  135.     local url = self:getGitURL(name, gitDirectory)
  136.     self:log("Downloading " .. url .. " to " .. path .. "...")
  137.     local request = http.get(url)
  138.     if request then
  139.         local content = request.readAll()
  140.         request.close()
  141.  
  142.         if content then
  143.             local file = fs.open(path .. name, "w")
  144.             file.write(content)
  145.             file.close()
  146.             self:log("Done")
  147.         end
  148.     else
  149.         self:log("Error! Could not read content from: " .. url)
  150.     end
  151. end
  152.  
  153. function dpm:getProgram (name, code)
  154.     if name and not code and string.find(name, "@") or name and code then
  155.         if not code then name, code = self:getNameCode(name) end
  156.         shell.run("pastebin", "run", self.config.installScriptCode .. " " .. code .. " " .. name)
  157.     else
  158.         self:downloadGit(name, self.config.programPath, "/")
  159.     end
  160. end
  161.  
  162. function dpm:installScript (name, code)
  163.     self:log("Installing script " .. name .. " with code " .. code .. "...")
  164.     for i = 1, #self.reservedNames do
  165.         if name == self.reservedNames[i] then
  166.             self:log("Error! Cannot install script with name \"" .. name .. "\". Name is reserved.")
  167.             return
  168.         end
  169.     end
  170.     shell.run("pastebin", "run", self.config.installScriptCode .. " " .. code .. " " .. self.dpmPath .. self.config.scriptPath .. name)
  171.     self:log("Done")
  172.    
  173.     self.scripts[name] = code
  174.     self:saveScripts()
  175. end
  176.  
  177. function dpm:installGit (name)
  178.     self:downloadGit(name, self.config.scriptPath, self.dpmPath .. self.config.scriptPath)
  179. end
  180.  
  181. function dpm:checkRequirements(name)
  182.     self:log("Checking requirements of " .. name .. "...")
  183.    
  184.     self:log("Reading requirements from file " .. self.dpmPath .. self.config.scriptPath .. name)
  185.     local file = fs.open(self.dpmPath .. self.config.scriptPath .. name, "r")
  186.  
  187.     -- Find requirements by searching for comment --@requires name
  188.     local requires = {}
  189.     while true do
  190.         local line = file.readLine()
  191.         if not line then break end
  192.  
  193.         local find = string.find(line, "--@requires")
  194.         if find then
  195.             line = string.sub(line, find + 12)
  196.             local lineEnd = string.find(line, " ")
  197.  
  198.             local scriptName = nil
  199.             if lineEnd then
  200.                 scriptName = string.sub(line, 0, lineEnd - 1)
  201.             else
  202.                 scriptName = string.sub(line, 0)
  203.             end
  204.  
  205.             self:log("Found requirement: " .. scriptName)
  206.             if fs.exists(self.dpmPath .. self.config.scriptPath .. scriptName) then
  207.                 self:log("Requirement already satisfied!")
  208.             else
  209.                 requires[#requires + 1] = scriptName
  210.             end
  211.         end
  212.     end
  213.     file.close()
  214.  
  215.     -- Install missing requirements
  216.     for i = 1, #requires do
  217.         self:log("Trying to install missing requirement " .. requires[i])
  218.         local n = requires[i]
  219.         if string.find(n, "@") then
  220.             n, code = self:getNameCode(n)
  221.             self:installScript(n, code)
  222.         else
  223.             self:installGit(n)
  224.         end
  225.         self:checkRequirements(n)
  226.     end
  227.  
  228.     self:log("Done")
  229. end
  230.  
  231. function dpm:updateScript (name)
  232.     self:log("Updating script: " .. name)
  233.     local url = self:getGitURL(name, self.config.scriptPath)
  234.     self:log("Checking " .. url .. "...")
  235.     if http.checkURL(url) then
  236.         self:log("Found! Installing from " .. url .. "...")
  237.         self:installGit(name)
  238.         self:log("Done")
  239.     else
  240.         self:log("Could not load from " .. url)
  241.         self:log("Checking for code...")
  242.         local code = self.scripts[name]
  243.        
  244.         if not code then
  245.             self:log("Error! Script does not exist.")
  246.         else
  247.             self:log("Code found: " .. code)
  248.             shell.run("pastebin", "run", self.config.installScriptCode .. " " .. code .. " " .. self.dpmPath .. self.config.scriptPath .. name)
  249.             self:log("Done")
  250.         end
  251.     end
  252. end
  253.  
  254. function dpm:updateAllScripts ()
  255.     self:log("Updating all scripts...")
  256.     for name, _ in pairs(self.scripts) do
  257.         self:updateScript(name)
  258.     end
  259.     self:log("Done")
  260. end
  261.  
  262. function dpm:update ()
  263.     self:log("Updating dpm...")
  264.     shell.run("pastebin", "run", self.config.installScriptCode .. " " .. self.config.code .. " dpm")
  265.     self:log("Done")
  266. end
  267.  
  268. function dpm:removeScript (name)
  269.     self:log("Removing script: " .. name)
  270.     local o = {}
  271.     for n, code in pairs(self.scripts) do
  272.         if n ~= name then
  273.             o[n] = code
  274.         else
  275.             self:log("Removed script from " .. self.dpmPath .. self.config.scriptListPath)
  276.         end
  277.     end
  278.     self.scripts = o
  279.     self:saveScripts()
  280.  
  281.     if fs.exists(self.dpmPath .. self.config.scriptPath .. name) then
  282.         fs.delete(self.dpmPath .. self.config.scriptPath .. name)
  283.         self:log("Removed script from " .. self.dpmPath .. self.config.scriptPath .. name)
  284.     else
  285.         self:log("File does not exists: " .. self.dpmPath .. self.config.scriptPath .. name)
  286.     end
  287.  
  288.     self:log("Done")
  289. end
  290.  
  291. function dpm:removeAllScripts ()
  292.     self:log("Removing all scripts...")
  293.     for name, _ in pairs(self.scripts) do
  294.         self:removeScript(name)
  295.     end
  296.     self:log("Done")
  297. end
  298.  
  299. function dpm:list ()
  300.     print ("name", "code")
  301.     print ("------------")
  302.     for name, code in pairs(self.scripts) do
  303.         print (name, code)
  304.     end
  305. end
  306.  
  307. function dpm:saveConfig()
  308.     self:log("Saving config...")
  309.     local file = fs.open(self.configFilePath, "w")
  310.     file.write (textutils.serializeJSON(self.config))
  311.     file.close()
  312.     self:log("Done")
  313. end
  314.  
  315. function dpm:loadConfig()
  316.     self:log("Loading config...")
  317.     local file = fs.open(self.configFilePath, "r")
  318.  
  319.     if not file then
  320.         self:log("Error! File does not exist: " .. self.configFilePath)
  321.         self:saveConfig()
  322.     else
  323.         local temp = textutils.unserializeJSON(file.readAll()) or {}
  324.         if tablelength(temp) == tablelength(self.config) then
  325.             self.config = temp
  326.         else self:saveConfig() end
  327.         self:log("Done")
  328.         file.close()
  329.     end
  330.  
  331. end
  332.  
  333. function dpm:updateConfig (name, value)
  334.     local writeConfig = true
  335.     if name and value then
  336.         if self.config[name] ~= nil then
  337.             if type(self.config[name]) == type(true) then
  338.                 if value == "true" then self.config[name] = true
  339.                 elseif value == "false" then self.config[name] = false
  340.                 else self:log("Error! Value has to be true or false.") end
  341.             else
  342.                 -- We assume string
  343.                 self.config[name] = value
  344.             end
  345.         else
  346.             writeConfig = false
  347.             self:log("Error! There is no config for a variable named " .. name)
  348.         end
  349.  
  350.         if writeConfig then
  351.             dpm:saveConfig()
  352.         end
  353.     else
  354.         print ("You can currently configure the following variables:")
  355.         for name, value in pairs(self.config) do
  356.             print (name, tostring(value))
  357.         end
  358.     end
  359. end
  360.  
  361. function dpm:help (command)    
  362.     if command and self.commandHelp[command] then
  363.         print (self.commandHelp[command])
  364.         return
  365.     end
  366.  
  367.     for _, description in pairs(self.commandHelp) do
  368.         print (description)
  369.     end
  370. end
  371.  
  372. function dpm:init ()
  373.     if not fs.exists(self.dpmPath .. self.config.scriptPath) then
  374.         fs.makeDir(self.dpmPath .. self.config.scriptPath)
  375.     end
  376.     self:loadConfig()
  377.     self:getScripts()
  378. end
  379.  
  380. function dpm:checkArguments (args, offset)
  381.     local firstArgument = offset + 1
  382.     local name = args[firstArgument + 1]
  383.     local value = args[firstArgument + 2]
  384.  
  385.     if name and not value and string.find(name, "@") then
  386.         name, value = self:getNameCode(name)
  387.     end
  388.  
  389.     if args[firstArgument] == "install" then
  390.         if value and name then
  391.             self:installScript(name, value)
  392.             self:checkRequirements(name)
  393.         else
  394.             local url = self:getGitURL(name, self.config.scriptPath)
  395.             if (http.checkURL(url)) then
  396.                 self:installGit(name)
  397.                 self:checkRequirements(name)
  398.             else
  399.                 self:log("Error! Could not install script with name: " .. name)
  400.             end
  401.         end
  402.     elseif args[firstArgument] == "update" then
  403.         if name then
  404.             if name == "all" then
  405.                 self:updateAllScripts()
  406.             else
  407.                 self:updateScript(name)
  408.             end
  409.         else
  410.             self:update()
  411.         end
  412.     elseif args[firstArgument] == "remove" then
  413.         if name then
  414.             if name == "all" then
  415.                 self:removeAllScripts()
  416.             else
  417.                 self:removeScript(name)
  418.             end
  419.         else
  420.             self:log("Error! Missing argument. What should I remove?")
  421.         end
  422.     elseif args[firstArgument] == "list" then
  423.         if name then
  424.             self:log("Error! Too many arguments.")
  425.         else
  426.             self:list()
  427.         end
  428.     elseif args[firstArgument] == "get" then
  429.         if name then
  430.             self:getProgram(name, value)
  431.         else
  432.             self:log("Error! Missing argument.")
  433.         end
  434.     elseif args[firstArgument] == "help" then        
  435.         self:help(name)
  436.     elseif args[firstArgument] == "config" then
  437.         self:updateConfig(name, value)
  438.     end
  439. end
  440.  
  441. function dpm:load(name)
  442.     self:log("Loading script " .. name .. "...")
  443.  
  444.     local code = nil
  445.     if string.find(name, "@") then
  446.         name, code = self:getNameCode(name)
  447.     end
  448.  
  449.     if not fs.exists(self.dpmPath .. self.config.scriptPath .. name) then
  450.         self:log("Error! Script does not exist: " .. self.dpmPath .. self.config.scriptPath .. name)
  451.         if code then
  452.             self:log("Trying to install " .. name .. " with code " .. code .. "...")
  453.             self:installScript(name, code)
  454.         else
  455.             local url = self:getGitURL(name, self.config.scriptPath)
  456.             if (http.checkURL(url)) then
  457.                 self:installGit(name)
  458.             else
  459.                 self:log("Error! Could not install script with name: " .. name)
  460.             end
  461.         end
  462.     end
  463.  
  464.     if fs.exists(self.dpmPath .. self.config.scriptPath .. name) then
  465.         self:checkRequirements(name)
  466.         local path = self.dpmPath .. self.config.scriptPath .. name
  467.         self:log("Loading file " .. path)
  468.         local script = require(path)
  469.         return script
  470.     end
  471.  
  472.     return nil
  473. end
  474.  
  475. --- Initialise
  476. -- Check -v / -verbose flag to enable verbose output without saving config directly
  477. local argOffset = 0
  478. if args[1] == "-v" or args[1] == "-verbose" then
  479.     argOffset = 1
  480.     dpm.verbose = true
  481. end
  482. dpm:init()
  483. --- Check arguments
  484. if args[argOffset + 1] then
  485.     dpm:checkArguments(args, argOffset)
  486. end
  487. -------------------
  488.  
  489. return dpm
  490.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement