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

Making a updater for an OS

Started by ThyMason122, 22 December 2015 - 07:05 PM
ThyMason122 #1
Posted 22 December 2015 - 08:05 PM
Hello, sorry if I might have posted this in the wrong forums, but I need help.
I'm making an OS, called "MasonOS" and I have made an installer.
But I want to make a updater from a different program that checks for an update, if so prompts the user to download it and
run it.
I'm a noob at os'es and would fairly appreciate if you could help me out
TheOddByte #2
Posted 22 December 2015 - 09:28 PM
What you want to do is have newest version online somewhere, like for example Github, then the program should use http.get to get that version and compare it with the local version, if it's newer then it should prompt the user to update.

Here's a basic example of how it could look

local version = "1.3"
local response = http.get( "<version url>" ) --# Try to get the latest version using http.get
if response then --# See if the site responded
    local ver = response.readAll() --# If it did then read all the content
    if tonumber( ver ) > tonumber( version ) then --# Check if the version on the site is newer
        print( "There's a new version, do you want to update?" )
        -- more code
   else
        print( "You're already using the newest version!" )
    end
end
ThyMason122 #3
Posted 22 December 2015 - 09:34 PM
Seems simple enough. But how would I download the files from github onto the computer thats outdated?
As in, testing for the github, and if it returns it would download it from github/pastebin?
Edited on 22 December 2015 - 08:40 PM
Lyqyd #4
Posted 22 December 2015 - 10:46 PM
To be honest, this sort of case would be perfect for making it into a packman package.

Essentially, though, what you'd want to do is create a file on the local machine in which you store the path of each file and the sha hash for the file. You'd then compare those hashes to the hashes for the up-to-date files provided by the github API. You would then download the contents of any files that mismatch, overwrite the local file, and save the updated hash in your versioning file.
ThyMason122 #5
Posted 23 December 2015 - 06:16 AM
What you want to do is have newest version online somewhere, like for example Github, then the program should use http.get to get that version and compare it with the local version, if it's newer then it should prompt the user to update.

Here's a basic example of how it could look

local version = "1.3"
local response = http.get( "<version url>" ) --# Try to get the latest version using http.get
if response then --# See if the site responded
	local ver = response.readAll() --# If it did then read all the content
	if tonumber( ver ) > tonumber( version ) then --# Check if the version on the site is newer
		print( "There's a new version, do you want to update?" )
		-- more code
   else
		print( "You're already using the newest version!" )
	end
end

Im understanding this a bit better and Im wondering if this code would be put in the top, or a different program. As I'm not really understanding how to use packman.

Edit: Im going to implement this coding instead. This seems alot easier as the installer will just install the basic stuff. Which is great cause the main things in MasonOs dont need to be updated. But, I would like to know how to make it so if theres a new thing that does not come with the os coding that can also be downloaded. So for example I added a new background, how would I add that?

Anyways, Thanks to both of you! :)/>
Edited on 23 December 2015 - 05:15 AM
ThyMason122 #6
Posted 23 December 2015 - 06:27 AM
When I run the Code it comes up with os:16: attempt to compare nil with number
Line 16 is the code

if tonumber( ver ) > tonumber( version ) then --# Check if the version on the site is newer
Edited on 23 December 2015 - 05:28 AM
Bomb Bloke #7
Posted 23 December 2015 - 07:26 AM
Either "ver" or "version" can not be represented as a number (but not both - one can and the other can't), and so one of your tonumber() calls returns nil. As a result you attempt to compare nil with a number.
ThyMason122 #8
Posted 23 December 2015 - 07:32 AM
Both ver and version are numbers, ver = 1.3, and version = 1.0

Unless I cant have decimals after whole numbers.
Bomb Bloke #9
Posted 23 December 2015 - 08:15 AM
No, they're not numbers; if you can't see why that is, then I suggest showing us your code. ;)/>

If this is it, then take a good look at line 13. Assuming you've corrected that, try printing "ver" before attempting your comparison.
ThyMason122 #10
Posted 23 December 2015 - 08:24 AM
Yes, this is the cloned one. Yes it is has been fixed to that link and I will attempt to do so

Ver has been printed on line 15 on the coding. Before the comparison

If you mean making it global I dont know why that would fix it.
Bomb Bloke #11
Posted 23 December 2015 - 08:29 AM
When you do response.readAll(), what you're getting is the entirety of this page's source - a big bunch of HTML. Everything that the pastebin site's web server sends to your web browser when you view the paste online. That's, um, not a number, and it wouldn't be even if you just grabbed a page containing the content of your paste only - it'd still be a bunch of Lua source.

You would be better off creating a separate paste, containing only a representation of your highest version number and nothing else, and http.get()'ing the raw version of that. This'd save you from having to filter out the data you actually want from a big chunk of text.
ThyMason122 #12
Posted 23 December 2015 - 08:36 AM
This seems alot easier. Thank you ;)/>/&amp;gt; Im going to try it out now and see if it works.

After: Still a string. See This
This wont work after trying the current
1.3 (alone)
ver = 1.3
Edited on 23 December 2015 - 07:37 AM
Bomb Bloke #13
Posted 23 December 2015 - 08:42 AM
I'm currently seeing your paste as containing "ver = 1.3". That can't be represented as a number, either - though just "1.3" could be.
ThyMason122 #14
Posted 23 December 2015 - 08:42 AM
I've tried that, it says its still a string
Bomb Bloke #15
Posted 23 December 2015 - 08:54 AM
Methinks it took you a couple of tries to save the paste correctly - you've got it right now.

On to the next error: You can't call a function you haven't defined yet. You'll need to re-order some code.
ThyMason122 #16
Posted 23 December 2015 - 08:57 AM
What function is that?
Bomb Bloke #17
Posted 23 December 2015 - 10:42 AM
Well, if you run the script in your pastebin, what does it tell you?
ThyMason122 #18
Posted 23 December 2015 - 10:59 AM
Havent Tried it, Ive been running a dev version on the computer I created it.
Ill try to dl it

Im getting the same error about

if tonumber( ver ) > tonumber( version ) then --# Check if the version on the site is newer
Edited on 23 December 2015 - 08:18 PM
Admicos #19
Posted 24 December 2015 - 05:13 PM
Take a look at AdmiOS's updater:

local config = libCFG.readConfig("/etc/update.cfg")
local latest = tonumber(libNET.getFile(config["repo"] .. "version"))
local current = tonumber(config["version"])
if latest > current then
print("\nThere is an update!")
print("Your version: " .. current .. "\nLatest version: " .. latest)
print("Update? (Y/N)")
local e = {os.pullEvent("key")}
if e[2] == 21 then
  print("Getting installer...")
  libNET.downloadSaveFile("http://pastebin.com/raw/dAH7J9X8", "/.installer_temp")
  print("Running installer...")
  shell.run("/.installer_temp update")
else
  print("Update dismissed. Continuing Boot...")
end
end
if fs.exists("/.installer_temp") then
print("\nRemoving Update remains...")
fs.delete("/.installer_temp")
end

This code runs in the every* bootup of the OS
*this does not include the shell login since it doesnt execute init files.

So, I made some APIs to do stuff and i used 2 of them (libCFG and libNET) You probably don't have then. So i'm just going to explain what they do.

libCFG just takes a config files and turns it into a table (Available in the Apis section of programs)
libNET gots files from the internet and does some stuff with them.

So, first, i get the contents of the update config file. This has the URL of the site that has the version file. (the file only contains a number and nothing else)
Second, i download the version file and return it's contents to a variable named latest.
Third, i get the current version from the config file said above (saved in variable current). And compare them with if latest > current then
If latest version is bigger than the current version. I prompt the user for updates.
When the user presses y (Detected with if e[2] == 21 then) i go and download the installer to /.installer_temp (My installer gets the latest version from GitHub.) and execute it with the argument update that makes the installer skip creating a new user. It will get everything from GitHub as said above and it will reboot (rebooting happens in the installer)
After the reboot, the files should be updated. And the program will run agan to check for updates. It will probably not find any since the user just updated. Then it will check if /.installer_temp exists and if so, will delete it. Removing the unneccecary file.

I'm sorry for the wall of text but this should explain what i do to keep AdmiOS updated.
If you have any questions, i will try to answer them here.
Edited on 24 December 2015 - 04:21 PM
ThyMason122 #20
Posted 25 December 2015 - 12:46 AM
This seems like the most easiest code ever, I did notice the init problem and will fix that too. I'll look at the libCFG and libNet after the holidays are over. I only have time to talk since Im helping my family with cooking.
ThyMason122 #21
Posted 14 January 2016 - 07:53 PM
Im back and I let everyone in my Os post about the trouble with the updater.