Moving my git repositories to BitBucket

I moved my git repositories to BitBucket and it was super-easy.

As part of my annual digital spring cleaning, I decided it was time to find a new home for the dozen or so git repositories taking up space on my virtual server.  I’d set up gitosis a few years back (way back before gitolite was even a thing), without any fancy web interface or DAV access.  Only command-line access, operating under the full Ron Popeil server-admin philosophy: Set it and forget it.

All was fine and dandy until I realized that having several working copies (along with the master copy) of a dozen repositories, operating on the same server, was kind of silly.  (No, I didn’t plan it that way, but, well, you know.  Things happen.)  One of those repositories was a few hundred megabytes on its own.  I started to get notifications about the disk being full and such.  I hate those notifications.  I actually hate all notifications.  It goes very much against the “forget it” part of the aforementioned server-admin philosophy I outlined in great detail above.  So, I went to the Cloud to find a new home for my gits.

GitHub charges by the repository.  Bleh; no thanks.  As one writer put it: GitHub charging by the repository is as asinine as if Dropbox charged users by the folder.  Then I got all caught up with the times and discovered that not only is BitBucket in the git game now, it’s also offering essentially unlimited repositories for up to five users, for the price of free.

After a few hours of researching how best to migrate all this data and all my commit history over to its new home, I found a very easy way to get it done, thanks to Oscar Merida.  First, you create a new repository in BitBucket.  Then run the following two commands in the folder where your repository currently lives:

git remote add origin git@bitbucket.org:user/newproject.git
git push -u git@bitbucket.org:user/newproject.git master:master

Repeat for each repo.

On my first attempt, however, I did run into one problem, which was actually very easily solved, thanks to BitBucket’s excellent documentation.  The first time I tried a push, I got the error:

Permission denied (publickey).

Which meant that BitBucket didn’t know that it was okay to accept my pushes.  So I just followed their instructions for how to fix it, and, boom.  Done.

Very easy.

Music tagging oddness

Why do digital music publishers do stuff like this?

Better clarify that it's the "Album Version", for every track on the album

Maybe it’d make sense if the album was a compilation and there were different versions of the songs, so there’d be a reason to distinguish between, say, the “Album Version” and the “Hot Dance Mix”. But not when all of them are the same, and not when the album is just basically the regular plain-old album.

Maybe there’s actually some rationale. Odd though.

Who starts you? Who keeps you going?

He saw an evening when he sat slumped across his desk in that office.

It was late and his staff had left; so he could lie there alone, unwitnessed. He was tired. It was as if he had run a race against his own body, and all the exhaustion of years, which he had refused to acknowledge, had caught him at once and flattened him against the desk top. He felt nothing, except the desire not to move. He did not have the strength to feel—not even to suffer. He had burned everything there was to burn within him; he had scattered so many sparks to start so many things— and he wondered whether someone could give him now the spark he needed, now when he felt unable ever to rise again. He asked himself who had started him and kept him going. Then he raised his head.

Slowly, with the greatest effort of his life, he made his body rise until he was able to sit upright with only one hand pressed to the desk and a trembling arm to support him.

He never asked that question again.

Side-stepping the absolute URL requirement in WordPress

This is a limited use-case, but it’s one I’ve just successfully figured out how to deal with. Hope it helps.

I have a WordPress codebase that is shared between three domains. The code executes the same on all three domains — only the domain itself is different. Which, there should be nothing inherently problematic about doing this.

Problem is, when you set up your blog’s settings, WordPress requires that you enter a fully-qualified absolute URL for the blog’s root directory — and that URL is inserted throughout every nook and cranny of the app. For whatever reason, you can’t supply it a domain-less path, even though it seems like this would be a perfectly reasonable thing to expect. (I read one explanation that this would be too problematic for many users.) There are way too many references to this absolute URL to fix by hand, and if it can be avoided, it’s not generally a good idea to go monkeying around in the guts of the app to try to change its behavior. Maintenance becomes a lot more hands-on. Upgrading can easily become a migraine.

So: database hacks to the rescue.

You can actually force WordPress to use a domain-less root path, by altering two settings directly in the database. In the wp_options table, change the siteurl and home values to whatever URL you like. Like, say, the perfectly reasonable / or /blog. The only downside is that if you ever try to change anything on the General Settings page from within wp-admin, WordPress will bark at you and give you a couple of error messages. It’s okay. You can ignore them. Everything else works just fine.

Update: Apparently, everything else does not work just fine. Setting the URL in the database broke Akismet.

Akismet requires the home value in the database options to be the URL associated with your API key. Unsurprisingly, if it doesn’t have that URL, the service requests will fail.

WordPress is great and all, but like every other off-the-shelf software package, there are times where if you want to customize it and color outside the lines they’ve drawn for you, you end up diving down a frustrating rabbit hole.

I’m sure I’ll port this bad boy over to Django soon enough. Then: sweet, satisfying, complete control.

Integrating Jinja2 and Django

Jinja2 is a real improvement over the standard Django template system. It has a number of useful features that the built-in Django templates just don’t have — especially when it comes to basic visual markup logic (elif statements, basic macros). Thankfully, Django is built to be pluggable and modular, and it’s not terribly difficult to get Jinja2 working with it.

When I wrote my first Jinja2-based app a couple of years ago, I did so using a little helper script I cobbled together from various Jinja2/Django-type pioneers, and the result was a workable — if a little hacky and kludgy — module that I could reuse in each of my apps. I import it in my views.py, and it gives me the most basic template-type methods like render_to_response and such. It’s limited, but I really haven’t had need for much else. (And when I’ve needed to expand its functionality, I have.) But it’s always felt like a temporary fix — a little incomplete and hackish. I took a look around recently to see if there were any other solutions that integrated Jinja2 into Django a little more gracefully and completely.

It wasn’t long before I found coffin — a library that’s more or less a port of Django’s template functionality, but using Jinja2′s rendering. Its real killer feature, IMO, is how easy it is to use Django template tags and filters within coffin — which is something you might not expect to need, but it’s very handy to have. For example, coffin includes a ton of useful tags and filters out of the box — like the super-useful {% spaceless %}. And you can easily add others, without having to write a complete port.

Coffin works a lot like my little helper module. You import it in every page, explicitly.

But I found something that I think is just a tad better: this fork of coffin. Its best feature is that it can be plugged in directly to Django’s native template loading system, so that it is integrated a little more neatly. All it takes is just a little adjustment to your project’s settings file:


TEMPLATE_LOADERS = (
'coffin.template.loaders.Loader',
)

JINJA2_TEMPLATE_LOADERS = (
'django.template.loaders.app_directories.Loader',
'django.template.loaders.filesystem.Loader',
)

The coffin template handling is enabled more or less transparently — using Django’s syntax while the templates are handled behind the scenes. Thus, in your apps, instead of this:

from coffin.shortcuts import render_to_response

You can use the usual Django syntax:

from django.shortcuts import render_to_response

Helpfully, this fork also allows you to turn off Jinja2 rendering on an app-by-app basis, with a simple tuple in your settings file. So it’s easy to have, say, the Django debug toolbar running with Django templates alongside your app that uses Jinja2 templates.

I really like this approach, mainly for the reason that enabling Jinja2 can be enabled — and overridden — completely from the settings file.

I don’t have a strong opinion about the pros and cons of these two approaches, but I’ll be trying out the template-loader fork of coffin to see how well it runs and how easy it is to use. I’ll be curious to see if anyone has any input as to whether the template-loader approach has any design concerns that I haven’t considered.

Meanwhile, give it a shot! Enjoy.

The ultimate result of shielding man from the effects of folly is to people the world with fools.

– Herbert Spencer

These ever-expanding enforcement powers miss the point: The threat posed by drunk driving comes not from drinking per se but from the impairment drinking can cause. [...]

If our ultimate goals are to reduce driver impairment and maximize highway safety, we should be punishing reckless driving. It shouldn’t matter if it’s caused by alcohol, sleep deprivation, prescription medication, text messaging, or road rage.

Radley Balko

It is the working man who is the happy man

It is the working man who is the happy man. Man was made to be active, and he is never so happy as when he is so. It is the idle man who is the miserable man.

– David Alfred Doudney, Old Jonathan, or the Parish Helper (though often misattributed to Benjamin Franklin)

Q: How does one eat an elephant?

A: One bite at a time.

Getting things done

Changing the status quo.

Return top