Main

November 16, 2010

#protip: In app purchase requires ability to sell apps

If you're new to the iPhone scene or working on In App Purchase code using a client's iTunes Connect setup, be aware that you must have all of your banking and financial information set up such that you *could* sell something on the app store, even if your app is not yet released, in order to test In App Purchase.

I have a client who hasn't yet released any applications. (SOON! Right, Randy?) We ran into this problem together and spent a couple of hours pulling our hair out over this one. I suggested that he go ahead and add his banking information before escalating the problem to our friends at Apple and everything started working one he got himself setup for payments. Unless I'm missing something obvious in the docs, and since there is no error message that comes back from the Store Kit callback indicating why an item is invalid, there is really no way that one would know that other than to have stumbled upon it like we did.

(facepalm)

October 04, 2010

Mercurial as überVCS

I remember a Q&A session during the most recent 360|idev where several of us took to discussing our favorite flavors of version control. During that discussion I asked whether anyone knew of a sort of über version control system that would allow me to pull code from each of the three most popular version control systems (git, mercurial, subversion). Given that there is a lot of fantastic code on bitbucket (mercurial), github (git), google code (subversion / mercurial), and elsewhere, we all agreed that it would likely prove very useful to be able to use some overarching version control system to pull up-to-date code from more or less anywhere in a manner similar to the way svn-externals handles pulling subversion-based subprojects into a subversion working copy.

I have a number of projects using Subversion for version control, a few using Mercurial, and I even maintain a private branch of Three20 using git. When an external project is using the same version control system as the project itself, life is generally simple. In the gogoDocs subversion repository, for example, the svn-externals mechanism happily keeps the GData API at a specific revision for me. Almost all of my projects use code from some other project that uses a "foreign" version control system. In gogoDocs, where I keep my copy of the GData API close to the bleeding edge, the version of Three20 I'm using is woefully out of date. The reason for this is pretty simple. It's difficult to update Three20 because it requires a lot of voodoo to pull the changes from the git repository. In order to keep Three20 up to date, I would have to keep the .git directory with the Three20 code inside of my working copy, making sure to svn-ignore that directory and never check it in to subversion (I did that once accidentally...not pretty). If I were to try to update my copy of Three20 with the canonical version on github, I would also have to remember to commit those changes into my own subversion repository. This always causes some problems on whichever of my other development machines is behind the bleeding edge. In order to update to the latest Three20 on another development machine, I have to remember to git pull before I svn up or things start to get scary; this means that I have to keep the .git directory in all of my working copies up to date. What a pain. Like many programmers, I'm almost inexcusably lazy, so I don't bother. I need an überVCS.

Here's what I think such an überVCS should do:
  • It should be distributed, allowing me to branch and commit locally. I have lately taken to making atomic local commits and using local branches to experiment and I really miss that workflow when I'm working in svn.
  • It should be ubiquitous and familiar. I don't want to learn another version control system, okay? I already have three version control systems competing for the mental space that used to hold one. I really just want one version control system that deals with everything.
  • It should be able to easily pull subprojects from git, mercurial, and subversion repositories in a manner similar to subversion's svn-externals.
  • It should allow me to work within those subprojects through plugins or natively so as to avoid the use of "foreign" version control command sets. In other words, I should be able to use the überVCS's command set inside of, for example, a subversion subproject. Ideally, I could work in one version control system and have subprojects from other version control systems just work somehow.


Using a few plugins, Mercurial can act as The überVCS I've been looking for. It fulfills the first two requirements out of the box. It's distributed and familiar. As far as I'm concerned, it acts a lot like a distributed version of Subversion, which is the old(ish) school version control system I'm most familiar with, whereas git feels like it is from someplace like Mars. Your mileage may vary.

The third requirement "to easily pull subprojects from git, mercurial, and subversion repositories" can be fulfilled by installing my fork of hgexternals from bitbucket. It's just a simple merge of the fork from adri (available here) with the latest code from the original author of hgexternals available (here). Once my little fork of hgexternals is installed, you can place an .hgexternals file in the root of your main project and Mercurial will pull code from pretty much anywhere when you run the hg externals command. If you wanted to pull the gdata objective-c client (google code / Subversion), the hgsubversion project (bit bucket / Mercurial), and mogenerator (github / git) into a contrib subdirectory of your project, you would put the following three lines into your .hgexternals file.
./contrib/gdata http://gdata-objectivec-client.googlecode.com/svn/trunk/ svn
./contrib/hgsubversion https://jonmarimba@bitbucket.org/durin42/hgsubversion hg
./contrib/mogenerator http://github.com/rentzsch/mogenerator.git git
If you then run hg externals in the project. You'll see that the subversion, mercurial, and git repositories are checked-out much like subversion handles svn-externals. Note: Be aware that the hgexternals python scrip will actually run svn or git binaries in a subprocess, so svn and git will have to be installed for this to work properly. If you wanted to hold the external project to a given revision, which is usually a good idea, you just append the external version control system's usual revision flag. For example, if you wanted the Gdata Objective-C code pegged at revision 533, the first line in the .hgexternals file would look like this.
  
./contrib/gdata http://gdata-objectivec-client.googlecode.com/svn/trunk/ svn --revision 533
In order to get the hg externals command to act a little more like subversion, you'll want to add the hgexternals.extstatushook to your .hgrc to get the status of the external projects when you type hg stat. To do this, you add the below to your .hgrc as suggested in the hgexternals installation instructions.
[hooks]
post-status = python:hgexternals.extstatushook
With a couple of extra plugins, mercurial can pull from subversion and git, in addition to the usual mercurial repositories. If you prefer to let hgexternals shell out to git or svn (thus requiring you to use git and svn tools within the subprojects themselves), you can stop here. If you would like to use mercurial commands within all subprojects, regardless of whether they are Mercurial repositories, read on. Either way, we can now pull subprojects from anywhere and we can also use hg stat as we normally would in the working copy of the project and each subproject status will also be shown.

Fulfilling the last requirement is actually pretty simple. Mercurial has third-party plugins that do a fine job of allowing you to use mercurial inside of working copies pulled from git or subversion repositories. For git, hg-git from here does the trick. While you can always use git commands within the mogenerator subproject from the example above, I personally find it easier to avoid switching between different version control systems on the fly. Hg-git lets you to interact with a git repository using mercurial. In order to do that, we install hg-git and then change the third line in our .hgexternals file to the following.
./contrib/mogenerator git://github.com/rentzsch/mogenerator.git hg
What we're doing here is telling the mercurial hgexternals extension to pull from the git repository using mercurial itself. When hg-git is installed, this works with a git-based subproject just as it would with a Mercurial-based project. Make this edit to .hgexternals, remove the mogenerator directory that was checked-out with git, and rerun hg external command. Mercurial will now pull mogenerator from github and we can now work within the mogenerator subproject using regular hg commands.

A similar plugin called hgsubversion, available here, allows you to use Mercurial to pull from Subversion repositories. Just like we did with hg-git, we can install hgsubversion and then change our .hgexternals file to look like this.
./contrib/gdata svn+http://gdata-objectivec-client.googlecode.com/svn/trunk/ hg -r 533
./contrib/hgsubversion https://jonmarimba@bitbucket.org/durin42/hgsubversion hg
./contrib/mogenerator git://github.com/rentzsch/mogenerator.git hg
If we remove the gdata subdirectory tha wall pulled using Subversion from contrib and rerun hg external so that Mercurial will now pull it using its hgsubversion plugin, we now have three projects in our contrib directory that Mercurial itself pulled from git, svn, and hg repositories. With Mercurial plus the addition of a few plugins, we now have an über distributed version control system that makes it much simpler to work with and to update external code from many different sources.

February 24, 2009

Useful bash foo with subversion

I've been a command-line user of subversion (svn) for some time and have long enjoyed these little bits of bash foo.

Stripping .svn directories

I often start one-off little test projects in my private slush svn repository and then move them into their own repository for further development as (or if) they grow up. Sometimes you'll want to get rid of svn's footprints in a working directory.
rm -rfv `find . -name *\.svn`
The find . -name *\.svn finds all of the .svn folders that svn uses to track the repository and with the help of those handy back-tics, rm -rv does the recursive removal of svn tracking directories.

Adding new files

During that early "making lots of new stuff" phase, I often generate quite a number of files that need to be added to svn at once. This is one of those times where having (say) class files in their own subdirectory is nice. Running this command will svn add every file that isn't currently being tracked by svn in the current directory.
svn add `svn stat |grep \? |awk '{print $2}'`
Grep finds every svn stat output line that includes a question mark (meaning the item is not currently under version control) and pipes it through awk '{print $2}', which shows only the text (the filename) from the second column of the svn stat output. The back-tics and svn add finish the magic.

Using a Mulligan

I'll use something similar to the above along with svn revert to rollback a working copy "all the way." Say you're experimenting in your working directory; you've added a few files, hit a dead end, and want to revert the whole tree as well as delete anything you've added. In other words, you're looking for a full-on "do over." Using svn revert --recursive will revert any files that svn is tracking, but will leave anything svn is not tracking alone, so we have to also remove those files.
svn revert --recursive && rm -rf `svn stat |grep \? |awk '{print $2}'`

As with any other nerd foo, make sure that you really want to do what you're asking for when you use these commands. These make my life with svn just a little easier.

February 01, 2007

Compile dar on OSX 10.4.8

CFLAGS="-DINSTALLPREFIX=/usr/local"
./configure --disable-nls
./make
sudo ./make install

that is all

self, out

January 18, 2007

Cocoa manual binding to selection in NSArrayController

If I want to do this manually binding.jpg
I have to do this
    [vizController bind:@"runData"
               toObject:runsController
            withKeyPath:@"selection.self"
                options:nil];
My RTFM skills lack the voodoo to find where this is documented. Is there perhaps another way?

October 11, 2006

bash is cool

We know this functionality is there, but often forget.
IF we have a directory full of folders with plone_*

for i in plone_*; do mv $i iavtheme_${i#plone_}; done

will replace plone_ with iavtheme_ for each directory name

See these for other pattern toys (thanks Juan for reminding me of this useful stuff I never seem to use):

${variable%pattern}
Trim the shortest match from the end
${variable##pattern}
Trim the longest match from the beginning
${variable%%pattern}
Trim the shortest match from the end
${variable#pattern}
Trim the shortest match from the beginning

http://linuxgazette.net/issue18/bash.html