This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Noiro's profile picture

UpdateFunction throwing nil and I have no idea why

Started by Noiro, 10 June 2014 - 11:01 PM
Noiro #1
Posted 11 June 2014 - 01:01 AM
Alrighty, I'm working on kind of a basic API to give myself some essentials I end up using a lot, and my pastebin update is throwing nil (line 71), would you happen to know what is up?
Spoiler



--[[
		CoreAPI is designed to provide some of the regularly needed
		features of general types of programs in one place.

		It is a mish-mash of functions where I wasn't sure where to place
		elsewhere.
		]]

version = "0.0.1"

--==Startup Functions==--

--Test This
function setStartup(...)
  --Takes any number of arguments and creates
  --a startup script to execute the program (argument 1)
  --with any following parameters (arguments afterwards)

  local args = {...}

  --Making sure I don't break a previous startup
  if fs.exists("startup") then
		fs.move("startup", "oldStartup")
  end

  --Saving the params file
  if not fs.exists("tempFiles/") then
		fs.makeDir("tempFiles")
  end

  local tempStartupParams = fs.open("tempFiles/tempStartupParams", "w")
  tempStartupParams.write(textutils.serialize(args))
  tempStartupParams.close()

  --Generating the startup file
  local startupFile = fs.open("startup", "w")
  startupFile.writeLine("--If you can read this, remove it")
  startupFile.writeLine("local params = fs.open(\"tempFiles/tempStartupParams\", \"r\")")
  startupFile.writeLine("local args = textutils.unserialize(params.readAll())")
  startupFile.writeLine("params.close()")
  startupFile.writeLine("shell.run(unpack(args))")
  startupFile.close()
end

function removeStartup()
		--Removes the startup you created and sets old one
		--(if it exists), back to normal place

		--Removes set startup and puts new one back
		if fs.exists("oldStartup") then
				if fs.exists("startup") then
						fs.delete("startup")
				end
				fs.move("oldStartup", "startup")
		end

		--Gets rid of the tempFiles Folder
		if fs.exists("tempFiles") then
				fs.delete("tempFiles")
		end
end

--==Update Functions==--

function checkUpdate(pastebinExtension, programPath)
		--Downloads the latest version of the program and compares size.
		--If size is different, it deletes the old and replaces with the new
		--Returns true if there was an update.

		print("Checking for updates...")
		shell.run("pastebin", "get", pastebinExtension, programPath.."temp")
		if fs.exists(programPath) then
				if fs.getSize(programPath) == fs.getSize(programPath.."temp") then
						fs.delete(programPath.."temp")
						print("You are up to date.")
						return false
				else
						print("Updates found. Applying...")
						fs.delete(programPath)
						fs.move(programPath.."temp", programPath)
						print("Done!")
						return true
				end
		else
				print("Updates found. Applying...")
				fs.move(programPath.."temp", programPath)
				print("Done!")
				return true
		end
end

function updateApis()
		--Updates/Downloads newest renditions of
		--my APIs (including this one)
		checkUpdate("kvLnweEf", "api/core")
		checkUpdate("9QFxP4Ff", "api/move")
		checkUpdate("E4cPHATD", "api/network")
end

For some reason the:
shell.run("pastebin", "get", pastebinExtension, programPath.."temp")
line gets errored out, and even if I manually replace all variables with their actual name and remove the 'temp' addition, I get the same error. Any idea what is going on or why?
Edited on 10 June 2014 - 11:02 PM
Lyqyd #2
Posted 11 June 2014 - 01:05 AM
What do you mean by "throwing nil"? That's not an actual error. In spite of this omission, you have given enough information to solve the question; you're trying to use the shell from within an API. This is not possible unless you pass a shell instance in to the API for it to use. You could try using os.run instead, though you will additionally need to provide an environment table for the code to run with. You may simply be better off writing a simple fetching function rather than trying to rely on the pastebin program, which has a lot of cruft for simple file fetching like an API should do.
Noiro #3
Posted 11 June 2014 - 01:27 AM
I'm having a hard time understanding why shell.run() operates within a program, but not within an API. Is the API not just treated as a storage container of functions the program can execute from afar? To write a fetching function would essentially involve copying pastebin itself (maybe stripping a couple pieces) as that is all I'm looking to do is pull data off of it. When you talk about environments, that gets into metatables and in Lua, that concept still confuses me.
Edited on 10 June 2014 - 11:41 PM
Lyqyd #4
Posted 11 June 2014 - 01:40 AM
Http fetching is really simple, and definitely won't involve copying even a significant fraction of the code from the pastebin program. It's about six or seven lines.

APIs have no reference to the shell, since there is no shell API. The shell "API" that programs can use is injected into their environment by the shell itself. There isn't really a way to simplify this further without pointing out the distinction in function environments between the program and the API, as that is the underlying reason why the shell is inaccessible from APIs. As well, there's no reasonable way for the API to know which shell to use if multiple of them have been instantiated. The easiest fix here is to just toss together a little fetching function to use instead.