Monday, January 7, 2013

dulwich porcelain

dulwich is an pure python implementation of git plumbing. It comes with a bin/scripts folder but it is incomplete - although I'm sure the developers would welcome additions. I have been working on a package called dulwich-porcelain, which facilitates adding features like checkout, fetch, push and status. Uh ... it's still beta, but contributions are welcome.

I also started a fork of dulwich with binpatches, porcelain and android branches. Android was actually the reason I origin started working on this. With just three commands it's easy to use your android device to retrieve your repos from a remote server anywhere you have 3g.

~$ dulwich clone <remote> <repo-name>
~$ cd <repo-name>
~/<repo-name>$ fetch_refs
~/<repo-name>$ checkout

n.b.: the functions also work as Python commands.

 You also need sl4a and py4a and some ssh authentication such as dropbear which is built into Cyanogenmod 7, openSSH is now used on CM9. Paramiko would be another option. I should make a post about this, but basically, I created an .ssh folder on my sdcard and created keys there. Cyanogenmod has a dropbear wiki and there is also a blogpost by TK, but both refer to creating an ssh server to communicate with your phone from a remote device, not creating keys to communicate with a remote device from your phone. Something like this should work.

~$ mkdir .ssh
~$ cd .ssh
~/.ssh$ dropbearkey -t rsa -f id_rsa
~/.ssh$ dropbearkey -y -f id_rsa > id_rsa_pub

Now you need to copy the public key, id_rsa_pub, to your remote Git server. You also need to make a small change to dulwich SSHvendor in client.py to make dropbear work. You can find the relevant changes in the android branch of my dulwich fork; basically append this class ...

class DropbearSSHVendor(object):
    def connect_ssh(self, host, command, username=None, port=None):
        import subprocess
        #FIXME: This has no way to deal with passwords..
        args = ['ssh', '-i', '/mnt/sdcard/.ssh/id_rsa']
        if port is not None:
            args.extend(['-p', str(port)])
        if username is not None:
            host = '%s@%s' % (username, host)
        args.append(host)
        proc = subprocess.Popen(args + command,
                                stdin=subprocess.PIPE,
                                stdout=subprocess.PIPE)
        return SubprocessWrapper(proc)

to the client.py file and then set get_ssh_vendor to the new vendor instead of the default one.

# Can be overridden by users
# get_ssh_vendor = SSHVendor
get_ssh_vendor = DropbearSSHVendor

Known hosts also got created automatically by dropbear in my .ssh folder on my sdcard. Dropbear doesn't let you use passwords, which is fine because dulwich has no way to deal with them. You could use keyring to get around that.

Now you can copy, send via email/bluetooth/wifi and/or edit your repo files on-the-go without needing to use a public computer or worry about ssh keys or passwords.
Fork me on GitHub