Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Backup Options

in Code Sharing Posts: 623

Hi all,

A number of options have been provided in the past for backup of your Codea workspace. The most recent from the development team, I have found all of these useful and appreciate the efforts of the all the work done.

There are several systems that have been developed but all seem to cease to function, largely I think due to the changes in Codea itself. So I find it frustrating when I can't backup my projects. I have to admit that this is largely due to my lack of organisation and I just accumulate loads of partially finished files.

One of the options was provided by @dave1707 which backed up locally in the Dropbox storage, which should be backed up by Dropbox itself. But it fails to run due to an error in reading the plist file the link for this is below :

Backup

I suspect this is due to a change in the text searching system. Any chance someone could check this out?

Bri_G

Comments

  • dave1707dave1707 Mod
    Posts: 6,397

    @Bri_G I wrote another backup/restore program that doesn't use the plist file. The next version of Codea has new functions that I use. They are createProject, deleteProject, hasProject, and listProjects. It will backup all of the projects into one file into the Dropbox folder. That file can be syncd with the Dropbox app. To restore a project, just select which backup file you want to use, select the project name from a list, and then restore. It will backup my 490+ projects in about 2 seconds which creates a 1.5MB file. You can create as many backup files as you want and restore from any one you select. Once the next Codea version comes out, I'll share the code.

  • Posts: 623

    @dave1707 - thanks for the prompt reply - played with the Project functions you mentioned but weren't they temporarily removed ? because of the import function in that version of Codea?

    Sounds really fast - hope it's implemented soon.

    Thanks,

    Bri_G

  • dave1707dave1707 Mod
    Posts: 6,397

    The thing that was removed was the Codea version of the restore. You can still do the export, but only assets can be restored. The functions are still valid. Since you're listed as a beta tester, you probably have the latest beta version of Codea. So here's a copy of my backup/restore that uses the new functions. There are 4 sliders that need to be turned on depending on what you want to do. Allow_bkup_create needs to be on to create a backup file. Allow_project_extract needs to be on to extract a file. Only_view_project_extract needs to be on if you just want to see the extracted project printed in the print panel. Allow_overwrite needs to be on if you want to overwrite an existing project. To use the code, turn on the Allow bkup create slider and tap Create a backup file. To restore a project, tap Select a backup file and tap the backup file you want to use and then tap List all projects. Tap the project you want to extract, and tap Extract or view a project. If the project already exists, turn on Allow overwrite and tap Extract again. You can create as many backup files as you want because the backup file name is the date and time of the backup.

    EDIT: THIS PROJECT IS ONLY FOR THE BETA VERSION OF CODEA. ONCE THE BETA IS LIVE, THEN THIS CAN BE USED.

    function setup()
        proj=listProjects("documents")
        param()
        pns="PROJ".."NAME".."START" -- project name start
        pne="PROJ".."NAME".."END"   -- project name end
        tns="TAB".."NAME".."START"  -- tab name start
        tne="TAB".."NAME".."END"    -- tab name end
        te="TAB".."END"             -- tab end
        pe="PROJ".."END"            -- project end
    end
    
    function param()
        pasteboard.text=""
        parameter.clear()
        parameter.boolean("Allow_bkup_create",false)
        parameter.boolean("Allow_project_extract",false)
        parameter.boolean("Only_view_project_extract",false)
        parameter.boolean("Allow_overwrite",false)
        parameter.action("Create a backup file.",createBkup)
        parameter.action("Select a backup file.",selectProject)
        parameter.action("List all projects.",showProjects)
        parameter.action("Extract or view a project.",extractProject)
    end
    
    function createBkup()
        output.clear()
        if not Allow_bkup_create then
            print("Allow_bkup_create not on.")
            return
        end
        local t=os.date("*t")
        backupName=string.format("bkup%02d%02d-%02d%02d",t.month,t.day,t.hour,t.min)
        local temp={}
        local dt=os.date()
        local cnt=0
        table.insert(temp,"BKUP==START.."..dt)
        for a,b in pairs(proj) do
            print(b)
            lst=listProjectTabs(b)
            cnt=cnt+1
            table.insert(temp,pns.."=="..b.."=="..pne)
            for c,d in pairs(lst) do
                table.insert(temp,tns.."=="..d.."=="..tne)
                table.insert(temp,readProjectTab(b..":"..d))
                table.insert(temp,"=="..te)
            end
            table.insert(temp,"=="..pe)
        end
        table.insert(temp,"BKUP==END")
        local str=table.concat(temp,"\n")
        print("Backup file created.")
        print(dt)
        print(cnt.." Projects.")
        print("File size  "..#str.." bytes.")
        saveText("Dropbox:"..backupName,str)
        param()
    end
    
    function selectProject()
        output.clear()
        local lst=assetList("Dropbox")
        for a,b in pairs(lst) do
            if string.find(b,"bkup") then
                print(b)
            end
        end
    end
    
    function showProjects()
        output.clear()
        local s=#pasteboard.text
        local name=string.sub(pasteboard.text,1,s-1)
        bkupFile=readText("Dropbox:"..name)
        if bkupFile==nil then
            print("No backup files were selected.")
            return
        end
        local sss=pns.."==(%g+)=="..pne
        for projName,proj in     
                string.gmatch(bkupFile,sss) do
            print(projName)
        end 
    end
    
    function extractProject()
        output.clear()
        if pasteboard.text=="" then
            print("A project wasn't selected.")
            return
        end
        local s=#pasteboard.text
        name=string.sub(pasteboard.text,1,s-1)
        local sss=pns.."==(%g+)=="..pne.."\n(.-)=="..pe
        if Only_view_project_extract then
            for projName,proj in string.gmatch(bkupFile,sss) do
                if name==projName then
                    print("===  "..name.."  ===\n")
                    print(proj)
                    return
                end
            end
        end
        if not Allow_project_extract then 
            print("Allow_project_extract not on.")
            return
        end
        if Allow_overwrite then
            if hasProject(name) then
                print("Deleting project..."..name)
                deleteProject(name)
            end
        end
        if not hasProject(name) then
            print("Creating project... "..name)
            createProject(name)
            for projName,proj in string.gmatch(bkupFile,sss) do
                if name==projName then
                    getTab(proj)
                end
            end 
            param()
        else
            print("Project "..name.." already exists.\n\nAllow_overwrite not on.")
        end        
    end
    
    function getTab(proj)
        local sss=tns.."==(%g+)=="..tne.."\n(.-)\n=="..te
        for tabName,tab in string.gmatch(proj,sss) do
            saveProjectTab(name..":"..tabName,tab)
            print("Tab created  "..name..":"..tabName)
        end        
    end
    
  • Posts: 623

    @dave1707 - very neat and have used the backup option followed by the Dropbox sync to get the file backed up in the cloud. This has allowed me to delete most of my projects and slim down my work-space.

    Thanks for that - do you think we would be better moving this to the development folders?

    Bri_G

  • dave1707dave1707 Mod
    Posts: 6,397

    @Bri_G I hope you tested my code and did backups and restores before you deleted your projects. Another thing that can be done with the Dropbox app is to view the file and copy sections of code from it while on a PC linked to Dropbox. Things always change and as people leave the forum, their projects created for everyone's use aren't kept up to date by those who are left. So I don't think it really matters where the code is kept. If someone does a search for backups, they'll find this eventually or be referred to it. So is this backup/restore easy enough to use. I know I don't have a mass restore option, but I'm not sure it's really needed because you can pull a project from the backup as needed. I also was thinking of deleting a lot of my projects to free up memory. If I look in Settings/Usage/Codea, it takes up 364 MB of memory.

  • dave1707dave1707 Mod
    edited April 11 Posts: 6,397

    Just a warning to anyone who uses this code, it hasn't been fully tested. Make sure you have multiple backup files just in case a backup gets corrupted. The name uses mmdd-hhmm so wait at least a minute between multiple backups. This is still a work in progress.

  • Posts: 623

    @dave1707 Just used the code to save to my Dropbox. Have confirmed transfer but not used any other features yet. Have only deleted older backed up files so far.

    Thanks

  • dave1707dave1707 Mod
    Posts: 6,397

    Here's an updated version of my backup/restore code. I removed the print option since I only used that as I was writing/testing the program and didn't see any need for it anymore. I also added code so that you had to do the extract steps in order (Select, List, Extract) otherwise I'll print a message. I think I have this working to make the backup/restore easy. As a test, I copied Cargo-Bot to a test file and backed up that test file. I restored that test file using overwrite and again with the test file deleted before the restore. Both times I restored the Cargo-Bot test file and in both cases Cargo-Bot started OK. I didn't try running a full game though.

    NOTE: As I said above, this uses some new functions that are in the beta version, so it can't be used until the beta version is accepted by Apple.

    function setup()
        proj=listProjects("documents")
        param()
        pns="PROJ".."NAME".."START" -- project name start
        pne="PROJ".."NAME".."END"   -- project name end
        tns="TAB".."NAME".."START"  -- tab name start
        tne="TAB".."NAME".."END"    -- tab name end
        te="TAB".."END"             -- tab end
        pe="PROJ".."END"            -- project end
    end
    
    function param()
        pasteboard.text=""
        parameter.clear()
        parameter.boolean("Allow_bkup_create",false)
        parameter.action("Create a backup file.",createBkup)
        parameter.action("Select a backup file.",selectProject)
        parameter.action("List all projects.",showProjects)
        parameter.boolean("Allow_project_extract",false)
        parameter.boolean("Allow_overwrite",false)
        parameter.action("Extract a project.",extractProject)    
    end
    
    function createBkup()
        nextFunction=""
        pasteboard.text=""
        output.clear()
        if not Allow_bkup_create then
            print("Allow_bkup_create not on.")
            return
        end
        local t=os.date("*t")
        backupName=string.format("bkup%02d%02d-%02d%02d",t.month,t.day,t.hour,t.min)
        local temp={}
        local dt=os.date()
        local cnt=0
        table.insert(temp,"BKUP==START.."..dt)
        for a,b in pairs(proj) do
            print(b)
            lst=listProjectTabs(b)
            cnt=cnt+1
            table.insert(temp,pns.."=="..b.."=="..pne)
            for c,d in pairs(lst) do
                table.insert(temp,tns.."=="..d.."=="..tne)
                table.insert(temp,readProjectTab(b..":"..d))
                table.insert(temp,"=="..te)
            end
            table.insert(temp,"=="..pe)
        end
        table.insert(temp,"BKUP==END")
        local str=table.concat(temp,"\n")
        print("Backup file created.")
        print(dt)
        print(cnt.." Projects.")
        print("File size  "..#str.." bytes.")
        saveText("Dropbox:"..backupName,str)
        param()
    end
    
    function selectProject()
        output.clear()
        pasteboard.text=""
        local lst=assetList("Dropbox")
        for a,b in pairs(lst) do
            if string.find(b,"bkup") then
                print(b)
            end
        end
        nextFunction="show"
    end
    
    function showProjects()
        output.clear()
        local s=#pasteboard.text
        local name=string.sub(pasteboard.text,1,s-1)
        bkupFile=readText("Dropbox:"..name)
        if bkupFile==nil or nextFunction~="show" then
            print("No backup file was selected.")
            return
        end
        local sss=pns.."==(%g+)=="..pne
        for projName,proj in     
                string.gmatch(bkupFile,sss) do
            print(projName)
        end 
        pasteboard.text=""
        nextFunction="extract"
    end
    
    function extractProject()
        output.clear()
        if pasteboard.text=="" or nextFunction~="extract" then
            print("A project wasn't selected.")
            return
        end
        local s=#pasteboard.text
        name=string.sub(pasteboard.text,1,s-1)
        local sss=pns.."==(%g+)=="..pne.."\n(.-)=="..pe
        if not Allow_project_extract then 
            print("Allow_project_extract not on.")
            return
        end
        if Allow_overwrite then
            if hasProject(name) then
                print("Deleting project..."..name)
                deleteProject(name)
            end
        end
        if not hasProject(name) then
            print("Creating project... "..name)
            createProject(name)
            for projName,proj in string.gmatch(bkupFile,sss) do
                if name==projName then
                    getTab(proj)
                end
            end 
            param()
            nextFunction=""
        else
            print("Project "..name.." already exists.\n\nAllow_overwrite not on.")
        end        
    end
    
    function getTab(proj)
        local sss=tns.."==(%g+)=="..tne.."\n(.-)\n=="..te
        for tabName,tab in string.gmatch(proj,sss) do
            saveProjectTab(name..":"..tabName,tab)
            print("Tab created  "..name..":"..tabName)
        end        
    end
    
  • dave1707dave1707 Mod
    edited April 12 Posts: 6,397

    Just a note that the above code DOESN'T backup any local or project data associated with any project. There also isn't any option to backup any global data. I guess I can look into adding those if needed.

    EDIT: The local and project data CAN'T be backed up in the above program. In order to read local and project data of a project, you have to be running that project. There's no easy way that I know of where one program can read the local or project data of another project. It can be done, but not easy enough that I'll add it to the above code. If you want to save local or project data, you'll have to do it yourself.

  • JohnJohn Admin Mod
    Posts: 459

    @dave1707
    I was thinking that it might be helpful to add some functions for archiving and unarchiving projects (i.e. to and from zip format). That way you can treat the project as a single file and do whatever you want with it.

  • dave1707dave1707 Mod
    Posts: 6,397

    @John I'm not sure I understand what you're saying. When I create a backup, it creates a single file with all the projects in it and a single project can be pulled from the file. I don't zip the file because it wasn't that big of a file (1.5MB) for my 499 projects. When it gets syncd with Dropbox on my PC, it can be viewed as a text file and I can highlight and copy any text from the file. The thing I don't understand is why Apple won't let you do the export/restore like what was in the first version of this beta if I can write something similar.

  • JohnJohn Admin Mod
    Posts: 459

    @dave1707
    The main advantage to archiving and unarchiving projects in that way is that you can easily transfer both the source code and additional files (sounds, images, text, project data, info plist etc). I feel that most people sharing projects avoid having any additional dependencies due to this, which in-turn limits what you can share.

    Apple is being very strict with us in particular (and less so with other developers) for some reason. They allow and encourage code sharing with Swift Playgrounds on iPad, going as far as to advertise the feature as a major benefit of using it while at the same time disallowing it for us. The reason why appears to be strict application of the Terms of Service that we must agree to as developers.

  • dave1707dave1707 Mod
    Posts: 6,397

    @John I wasn't trying to write something all inclusive, just something simple. Something that if I deleted a project by mistake, I could easily get it back. I wasn't worried about dependencies, assets, or local/project data. I figured Codea would eventually have all that, which you did have until Apple made you remove it. I figure what I have above will do until Apple stops being so picky. I'm past the point of trying to write large, complicated code. I did all of that for too long while I was working.

Sign In or Register to comment.