Backup folder suggestion

Hey all,

Little addition to Codea that would be nice to see. For every project that I make, I routinely back up my project by creating a copy. Then when I want a new backup, I delete the old copy and make a new one. This not only leaves me with twice as many projects to scroll through in my project list, but the extra steps of having to delete my old copy first before creating a new one.

It would be cool if Codea had a way of when holding on the project that brings up the list of duplicate, export, etc. there was an option of Backup and Restore from Backup, and it saves the 2 or 3 most recent backups.

This would allow us to backup our projects without having a list that is twice as long to scroll through.

it would not be too difficult to write a custom backup, now that we have project assets.

Maybe you could use the text functions to save a text file with the code to Dropbox.
And also use them to read the file along with saveProjectTab() to restore.

I would do something simple like using saveText to store a backup in the Project assets, then a simple restore function using readText to go back.

whats the difference between backuping folder and backuping files?

@JakAttak Very dangerous, you go first.

I think I’ll just stick to creating a copy of every project. :wink:

@Crumble i would like to do something about that. My idea is to make a project called XFCarchiver,

  • you make a depency to this project
  • you write in the setup
XFCarchiver:save(002) 

to save a copy with version number 002. This saving will only occur once.

  • when you want a new saving you just change the number:
XFCarchiver:save(003)
  • when you want to load a past version simply uncomment this line in the setup
-- XFCarchiver:load()

this opens a menu to choose the version you want to load. There will be an undo (1 level) for safety. You can also delete past versions from the menu.
Maybe: after first completion, XFCarchiver copies itself into the project so you dont need the dependency any more (tbc).

How does it work? it save the whole project in a new last tab in your current project, under the name zzzzzzz002, then

  • it doesnt interfere with your tabs.
  • you can easily copy it by hand and paste it into another new project is something goes wrong.
  • you know exactly where is your saved data.
    What do you think?

@Goatboy76, well since you asked so nicely… /s :wink:

Here’s something I threw together. Add it as a dependency to your projects, it will inject itself and add two buttons to the output panel, backup and restore. (Alternatively you can just call the functions backup and restore)

--# Main
function draw()
    background(255)
    
    text("JakAttak Backup Utility", WIDTH / 2, HEIGHT / 2)
end

--# Backup
local tabInd1 = "--"
local tabInd2 = "# " -- Needed so that backup util wont mix up

-- Backup the current version
function backup()
    saveText("Project:Backup", generateCodeaFormat())
    
    alert("You can find the backup in the Project Assets as 'Backup.txt'", "Backup Completed")
end

-- Restore from the backup
function restore()
    if not readText("Project:Backup") then
        alert("There is no backup stored.", "Restore Failed")
    else
        replaceTabs(splitCodeaFormat(readText("Project:Backup")))
        
        alert("This project will close in 3 seconds..", "Restore Completed")
        
        tween.delay(3, close)
    end
end

-- Generate a text with the proper codea tab format from our code
function generateCodeaFormat()
    local txt = ""
    for i,t in pairs(listProjectTabs()) do
        txt = txt .. tabInd1..tabInd2 .. t .. "\
" .. readProjectTab(t) .. "\
"
    end
    
    return txt
end

-- Split a text in the codea tab format into tabs
function splitCodeaFormat(str)
    local tabs, tname = {}
    local splitByLigne = function(ligne)
        if ligne:find("^%-%-#") then
            tname = ligne:sub(tabInd1:len() + tabInd2:len() + 1, ligne:len() - 1)
            tabs[tname] = ''
        else
            tabs[tname] = tabs[tname]..ligne
        end
    end
    
    str:gsub("[^\
]*\
", splitByLigne)
    
    return tabs
end


-- Replace current project tabs with new ones
function replaceTabs(tabs)
    -- Clear all current tabs (except Main because every project needs a Main)
    for i, t in ipairs(listProjectTabs()) do
        if t ~= "Main" then
            saveProjectTab(t, nil)
        end
    end
    
    -- Replace with stored tabs
    for name, data in pairs(tabs) do
        saveProjectTab(name, data)
    end
end

-- Add parameters for backing up and restoring
function backupSetup()
    parameter.action("Backup Project", backup)
    parameter.action("Restore Project", restore)
end


-- Inject yourself into setup
local s_setup
debug.sethook(function(event)
    if setup == nil or setup ~= s_setup then
        local o_setup = setup or function() end
        setup = function()
            if backupSetup then backupSetup() end
            o_setup()
        end
        s_setup = setup
    end
end, "r")

:slight_smile:

@JakAttak It was a Raiders of the Lost Ark refrence. Sorry if you were offended. Relying completely on this seems very risky. If something goes wrong, it could do a lot of damage. And with me, thats happens a lot. Thanks for sharing your code. I have a lot to learn from it.

@Goatboy76, I was not offended, my reply was sarcastic (I have to stop using that in writing…)

As for the risk, even if the restore goes wrong, the backup will still be there in the assets folder for you to paste into Codea.

@JakAttak I guess sarcasm can be hard to convey in writing.

So the backup would have to be made wrong and then you’d have to restore your project without knowing that the backup is wrong?

@Goatboy76, yes that is pretty much the only way something could go wrong. That said, it seems very, very unlikely that the backup would be created wrong (it’s super simple). The restore really seems like the only place something would go wrong, and as I said above if that happens, you can grab the text file and have Codea import it.

Otherwise, I assume this is pretty much how a built-in backup would work, though it might save tabs individually.