http://www.perlmonks.org?node_id=1002149

I've never really gotten along with git. Its feature set is good, but its usability is horrible. Mercurial on the other hand has roughly the same features, but is much more enjoyable to use, which is why it is my version control system of choice.

However, in recent years Github's popularity has exploded. So, how to get my code onto Github without using git?

Firstly, there's the hggit mercurial extension that allows you to push to a git repository. Install it and add these lines to .hgrc:

[extensions] hggit= bookmarks=

Then you need to create a bookmark for hggit to use as the basis for the master git head:

$ hg bookmark -r default master

And now you can just push:

$ hg push git+ssh://git@github.com:tobyink/some-repo.git

So where does Perl come into it? Well, I want to automate the creation of the Github repository, and setting up the bookmark. Here's my script to do that...

#!/usr/bin/env perl use v5.14; use constant { GH_USER => 'tobyink', GH_PASS => 'A BIG SECRET', }; use Acme::Constructor::Pythonic qw( Pithub Path::Class::File Path::Class::Dir ); use Cwd; BEGIN { package PithubX::Base; use Pithub::Base (); use Moo::Role; around _request_for => sub { my ($orig, $self, @args) = @_; my $req = $self->$orig(@args); $req->headers->remove_header('Authorization'); $req->headers->authorization_basic(::GH_USER, ::GH_PASS); return $req; }; 'Moo::Role'->apply_roles_to_package( 'Pithub::Base', 'PithubX::Base', ); }; my $gh = Pithub(user => GH_USER, token => 1); my $name = (Dir(cwd)->dir_list)[-1]; while ( not $gh->repos->get(repo => $name)->response->is_success ) { say "creating github repo '$name'"; $gh->repos->create(data => { name => $name, has_wiki => 0, has_downloads => 0, }); } unless (`hg bookmarks` =~ /master/) { say "creating 'master' bookmark"; system "hg bookmark -r default master"; } my $url = sprintf('git+ssh://git@github.com:%s/%s.git', GH_USER, $name +); system "hg push $url";

One interesting part of the script is the PithubX::Base package which acts as a monkey-patch for Pithub::Base, swapping out the OAuth authentication for HTTP basic auth because that seemed easier than figuring out how to get an OAuth authentication token.

I've saved that as github-mirror. But so that I don't have to remember to run it, I've also added it as a hook in my .hgrc so that whenever I push changes to my mercurial repo, github-mirror runs too:

[hooks] preoutgoing = /home/tai/bin/github-mirror
perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'