Program to push and commit code to Working Copy. Full Git source control, on device!

I thought that Codea users who do back-up/ source control/ versioning via Git might be interested in Working Copy, a rather nice Git client for iOS (I’m not affiliated with anyone involved in this app).

This one is interesting because whereas earlier Git apps on iOS had a relatively restricted function set, just allowing you to browse, or manage issues or whatever, this one has the sort of features you’d normally see in a desktop client (albeit a fairly paired-down one, like say Github for Mac). It’s free for read-only (eg pulling a repository, browsing through all the changes made in the various versions), and the full version that allows you to edit and push changes is an IAP of £7.99. It has a nice viewer with syntax recognition (including for Lua, see the screenshot below), and a great “diff” viewer, that shows you insertions and deletions, either in a split-screen side-by-side view, or an integrated list.

wc

But what’s really interesting is it supports the iOS 8+ “Open In” framework, which suggests some interesting future possibilities. In the past of course, code-executing apps such as Codea were required by Apple to remove “Open In” functionality, but it seems that Apple is reversing that policy a little, in part because of how much iOS 8 uses inter-app functionality. That is only going to accelerate once iOS 9 launches with split-screen multitasking. @Simeon has mentioned on this forum that he might look into whether it’s possible to bring back “Open In” for Codea.

Right now, I’m only going to use this in read-only mode, as a nice complement to @juce 's IMO indispensable Git client, Codea-SCM. Codea-SCM allows you push the latest version of your Codea project to a Git server, or pull a prior version if you need to roll back changes. Working Copy, like a desktop Git client, allows me to browse back through all the previous versions of a project (without needing an internet connection), making it easier to identify, for instance, which prior build it is I want to pull. If you use the “time machine” backup that Macs ship with, that’s what it feels like.

Working Copy has built-in support for GitHub and BitBucket, and it was incredibly easy to set up with BitBucket. It supports SSH keys, and just a few presses had the app authorised with my BitBucket account, so I could access all the Codea projects I have there. According to the docs though it can be set up with any Git website or server.

In the screenshot above I’m browsing one of my Codea projects (though this particular chunk of code is by @Ignatz ). You can see my Codea tabs on the left, and the share/ open-in pane on the right. Wouldn’t it be awesome to see a Codea icon in there? Even better, Working Copy also supports apps pushing content to it. If Codea gets two-way “Open In” support, both in to Codea and out of Codea, then something like Working Copy could be the Git client we use to back-up/ version control our Codea projects. At that point, the £7.99 “push” IAP would be pretty indispensable I reckon.

I love that iOS is gradually becoming more desktop-like, less of a walled garden.

Hmmmm, Working Copy has a URL-scheme, with support for commands, commit etc… So it should be possible to write a Codea app that sends a project to Working Copy, and then pushes it from there

thanks for sharing, very practical

interesting. Please post a lînk to the URL-scheme api?

It’s here:

http://workingcopyapp.com/url-schemes.html

Unfortunately right now I can’t get the x-URL-callbacks to work (the ones protected by a security key), either from Codea or any other app. I’ve emailed the developer. If we can get it working it could be very good. You can use the clipboard to push content, and if you don’t specify a repository path in the URL, Working Copy will ask you to select a location where you want to push the file to, or give you an option to create a new repository (according to the docs, haven’t got it working so far). So it could offer a very easy way to set up a new repo for your Codea project. You could use it locally, as an offline version control system (I think), then connect to bitbucket or whatever when you next have a connection.

One issue at the Codea end though, is that you can’t get data back from OpenURL can you? And http.request, which does return data, doesn’t seem to support the inter-app URL-scheme. So that could make pull requests tricky (unless the Working Copy scheme supports putting the requested file into the clipboard). I also need to investigate whether multiple files can be sent at once with one URL.

The developer Anders got back to me and fixed my issue. It was my inexperience with URLs. I didn’t realise that only the first tag is preceded by “?” and the subsequent ones take “&”.

The write URL command is very nice, it sends you to a dialogue where you can choose to overwrite an existing file in a repository (with version control, naturally), save as a new file, create a new repository etc. The text to be written can be encoded in the URL, or be the clipboard contents. This could be huge.

You can even suggest a filename that the new file will be saved as.

thanks. IOS8, though, time to switch…

Ok, here are my first efforts in making a light client that pushes Codea code to Working Copy. This means you can do full Git version control, entirely locally, on-device, for free. If you buy the full version of Working Copy, then you can sync the local repository with your remote account on GitHub, BitBucket or wherever.

Currently this just supports single files (it concatenas all the tabs together using Codea’s “paste into project” format). I think this is fine for smaller projects that don’t warrant their own dedicated repository. For larger projects, you’re better off using the excellent Codea-SCM.

I’m working on a multi-file version though. The developer of Working Copy is incredibly helpful, and I’ve joined the beta-test channel for the app.

Incidentally, this technique (using URL schemes) could be adapted to push your code anywhere, to Dropbox etc (via one of those apps that support URL schemes).

One day soon of course, I hope that a client like the one below won’t be necessary. I dream that I’ll have Codea and Working Copy running side-by-side in split-screen mode, and pushing/ committing code will just be a case of pressing the “share” button in Codea!

Usage instructions in the code:


--# Main
-- Working Copy Client

--[[

A light Codea program for committing code to Working Copy, a full iOS Git client. The free version of Working Copy supports local Git commits. To push to a remote host such as GitHub, BitBucket, or your own server, please buy the full version of Working Copy. Currently, Working Copy Client concatenas your project into a single file using Codea's "paste into project" format. I think this is OK for smaller projects that don't merit their own, dedicated repository. In future, I'm planning on adding multi-file push and commit.

## Installation

1. Install Working Copy on your iPad 

2. Set up a repository called "Codea" in Working Copy to store your code. If you have a remote host on GitHub, BitBucket, your local server etc then you can clone an existing repository. Otherwise you can initialise local repos on your device, and push them to the remote host later. 

3. In Working Copy settings, turn on "URL Callbacks" and copy the URL key to the clipboard.

4. The first time you run Working Copy Client in Codea, paste this URL key (from step 3) into the "Working Copy key" text box. The key will be stored in your global data.

## Usage

1. In Codea, make Working Copy Client a dependency of any project you want to push to Working Copy 

2. Run the project you want to backup, and hit the "Working Copy client" button.

3. Enter a message describing whatever change you made into the commit text box, and press commit.

Your project is concatena-d using Codea's "paste into project" format <--# tab name> and pushes it to the "Codea" repository in Working Copy, naming the file after its Codea project name. The project name is found by looking for the "-- <project name>" string that Codea places at the top of the Main tab. Make sure you don't put anything before this in the Main tab. To restore a previous version, you can copy the file from Working Copy (share pane > Copy), and in Codea, "paste into project"


  ]]

function setup()
    
end

--# WorkingCopy
-- Working Copy Client

displayMode(OVERLAY)

local workingCopyKey = readGlobalData("workingCopyKey", "")

local function urlencode(str)
    str = string.gsub (str, "\
", "\\r\
")
    str = string.gsub (str, "([^%w ])", 
        function (c)
            return string.format ("%%%02X", string.byte(c))
        end)
    str = string.gsub (str, " ", "%%20") -- %20 encoding, not + 
    return str
end

local function commitSingleFile()   
    --concatenate project tabs in Codea "paste into project" format and place in pasteboard
    local tabs = listProjectTabs()
    local tabString = ""
    for i,tabName in ipairs(tabs) do
        tabString = tabString.."--# "..tabName.."\
"..readProjectTab(tabName).."\
\
" --"paste into project" format
        print(i,tabName)
    end
    tabString = urlencode(tabString) --encode if passing code in URL, using &text="..tabString
   -- pasteboard.copy(tabString) --avoid encoding by placing code in pasteboard
    
    --get project name
    local projectName = urlencode(string.match(readProjectTab("Main"), "^%s*%-%-%s*(.-)\
") or "My Project")
    --encode commit message
    local commitEncode = urlencode(commitMessage)
    --build URL chain, starting from end (chained urls must be double-encoded)

    local commitURL = urlencode("working-copy://x-callback-url/commit/?key="..workingCopyKey.."&repo=Codea&path="..projectName..".lua&limit=1&message="..commitEncode) 
    
    local totalURL = "working-copy://x-callback-url/write/?key="..workingCopyKey.."&repo=Codea&path="..projectName..".lua&uti=public.txt&text="..tabString.."&x-success="..commitURL --&text="..tabString..
    
    openURL(totalURL) 

    print(projectName.." saved")
end

local function WorkingCopyClient()
    parameter.clear()
    parameter.text("commitMessage", "")
    parameter.action("Commit", commitSingleFile)
    parameter.text("workingCopyKey", workingCopyKey, function(v) saveGlobalData("workingCopyKey", v) end)
    parameter.action("Exit Working Copy Client", parameter.clear)
end

parameter.action("Working Copy client", WorkingCopyClient)

posh, A light Codea program for committing code to Working Copy