The O2 website shows the Moto G 3rd gen handset is “in stock” and there’s a tenner off bringing the cost to GBP109.00 for a new phone. Win!
I add the phone to my basket and pick an airtime tariff. Annoyingly you *have* to pick an airtime tariff even though you just want a handset, there’s no “I already have a bloody SIM” option. And this truly annoys me because they allocate you a number on a new SIM which is just a complete waste of a number and plastic and packaging, etc.
So, I then click checkout. Despite already being logged into my account the checkout wants me to login *again* (sigh).
Next up, delivery address. The last Moto was bought from O2’s local bricks and morter shop so my account doesn’t have my postal address, I only ever used my account to do online topups and was never asked to provide my home address. At the checkout it’s currently filled in with some weirdo default template text. So I hunt around for a way to update my address, turns out you can’t. Their FAQ swears blind there’s an option to do this, but I’ll be damned if I can find it. What to do?
To solve the delivery address problem I hit up their online support chat doodah. Before I get to chat to anyone I’m asked to fill in my Name and registered mobile number, I do this and what’s the first thing the human on the other end asks? “Can you tell me your mobile number?” (deep sigh).
Anyway after going through various security checks I explain my address problem, the blandly helpful bod on the other end says he can fix this and I provide him with my address. After confirming he’s updated my address I’m told this will take up to 48hrs to happen (another deep sigh). Seriously 48hrs? At this point I decide to eat lunch.
Unconvinced that it really takes 48hrs to update an account’s postal address I decide to try and purchase this sodding phone again. I get to the checkout and find my address has actually updated but there’s something wrong with it, it shows as:
(more sighing because there are courier drivers out there who won’t deliver your package unless the address is 100% correct, for all I know my phone might be delivered by Yodel, enough said)
So I ping the blandly helpful online support folks on chat and after the several minutes of security checks I explain that my address is wrong. He/she assures me it is fine and will print out correctly on the courier’s labels etc.
Whilst chatting I also explain that my contact number (presumably so the courier can call if they get lost) on the checkout is wrong, it’s set to my mobile number, which is completely unusable because I don’t have a functioning mobile, hence this purchase. There’s no way for me to change it on the website.
I try to explain this to the blandly helpful support bod but he/she doesn’t seem to comprehend this Catch 22 problem. I ask for the contact number on the order to be changed to my house land line number (in case the courier can’t find me and needs to phone for directions) but this is a futile and fruitless effort. The blandly helpful support bod says he/she will remain on chat to make sure my order goes through properly, so I click through my payment details only to be logged out by the site, again.
So, I re-login, restart the purchase, pick phone, pick unnecessary tariff, add to basket, click checkout which makes me login again, pick incorrectly displayed address, sigh at unusable and non-editable contact number, click through to payment page. I enter my card details, click confirm, and then for the first time in forever my bank’s 3D secure anti-fraud checker decides it wants to do its own security check (more deep sighing), fortunately it just asks for my card’s bank sort code, account number, expiry date and CVV number on the back, which I have in my hand; if it had asked anything else and I’d be kicking off on the gin early. One more click and I get the order confirmation page and an order number….yay!
I copy/paste the order number to the blandly helpful chat bod and he/she confirms my order is fine, we exchange pleasantries and part company. I give the chat bod a very favourable rating in that “was our support helpful” survey screen before closing the window.
A few minutes later I check my email and see that there’s an order confirmation message complete with order number, so far so good.
Now during the whole laborious process O2’s e-commerce website showed my handset as “In Stock – Free delivery next working day when you order by midnight”, I double check this before getting back to work, and it’s still showing as in-stock.
Later in the afternoon I get a second email confirming that “Your order is being processed”, again, progress. However, dismayingly, the message also says:
“We’ll email or send you an SMS to confirm when your order has been despatched so that you’ll know when to expect your delivery”
Grr…SMS, to a number that I CAN’T BLOODY USE UNTIL I HAVE A WORKING SODDING PHONE, which is why I went to the trouble of trying to explain why my contact number needed to be changed…deep, deep sighing and eye-rolling.
Fast forward to the next day, I check my email for order progress updates, there’s not a peep from O2. It’s still early, I’ll check again in the afternoon. I take a late lunch at around 3pm, check my email and still nothing from O2.
I also once again check that my handset is still showing as in-stock, because I have that sneaky feeling something is not right.
So I logon to my account to, as the last O2 email explained, “keep tabs on your order at https://myo2services.o2.co.uk/myorders”. My account screen under “Recent Orders” states “You haven’t ordered anything in the last 31 days.”, I have a hunt around to see if there’s maybe a different “Orders” page, but no, that’s the only one. Gathering my remaining reserves of patience for the day I decide to hit up the blandly helpful support bods on chat again. Once more, several minutes of doing the security thing, copy paste my order number, then explain that I don’t see my order on my online account, nor have I received any further updates about my order. There’s a longer than usual pause before the support bod comes back to me and tells me that the phone is out of stock and on back-order. What the cocking hell!?
I maintain my online calm and explain that the handset is showing as “in-stock” on their website (right there and then I check once more, yep, “in stock”), support bod blandly apologies and explains to me that the website is wrong and it’ll be at least a week before any more Moto G’s are in stock. This is no bloody good. In a fit of polite and constrained temper I tell the remote support bod to cancel the order and refund my money which he/she confirms is done but it’ll take up to 14 days to process the refund. YES…FOURTEEN TWATTING DAYS!?
Knowing there’s no point trying to argue the toss with the blandly helpful remote support bod, who’s clearly in a far away land several timezones ahead of me, I politely protest about how stupid their website is, grumble about the 14 day refund thing, part company, and leave a far less favourable rating on their “how did we do?” end-of-chat survey.
Annoyed I decide to phone O2 Sales to double check if the remote support bod is maybe seeing incorrect stock data or is just plain lying.
After 15 minutes of queuing and heading up several ACR/ACD/ACH blind alleys I eventually get to speak to a sales person, and one on the same continent as me, and quite possibly even on the same land mass just north of the cost of France.
I provide my order number, but they insist on more security checks, I provide my order number again (doesn’t anyone have a pen and paper?) and the sales dude confirms that new Moto G’s are definitely out of stock and would be on back order. I explain to the sales person that yesterday and all of today the phone is showing “in stock”. Out of idle curiosity I refresh the Moto G’s product item page and lo-and-behold its stock status changes to “Home delivery in up to 1 week”. I have a moan to the sales bloke about how much this experience has sucked from start to finish but he, politely, doesn’t really give a shit. I get him to check the stock status of the refurbished Moto G 3rd Gen which even as we were speaking was still showing “in stock for home delivery” on their website, unsurprisingly it’s also out of stock. Exasperated, I ask why they still show it as “in stock”, he doesn’t really answer my question, he doesn’t give a crap. I ask about my refund and get him to confirm that it’s really happening, he confirms it’s all fine and I should have my money back in five working days, not fourteen (but who bloody knows what might happen between now and then?).
From start to finish my whole order experience was one hurdle after another. Seriously, it’s 2016, and O2 can’t provide a real-time stock status from whatever big iron ERP runs their back office? I think what really pisses me off is that they didn’t provide any sort of update to explain that my phone went from “processing” to “on back order”. Oh no, I had piss about for an hour or so to find this out for myself, and couldn’t leave the house in case the courier turned up. It makes me wonder how many sales they lose when their website shows items as “out of stock” but are really in stock because they aren’t reflecting their stock status in real time. Or maybe they do, but maybe showing as “in stock”, for items that really aren’t, is just a dark sales pattern where they hope you don’t have the mental energy to cancel an order. Either way it’s shit.
The upside was that Argos has unlocked/sim-free refurbished Moto G 3rd Gen handsets for 99 quid advertised on ebay. I ordered that instead, it means I’m now no longer tied to O2. I’m rather hoping we’ve got better coverage around my village from other providers so I can ditch O2 completely.]]>
After around two weeks the T-shirt hadn’t arrived, this is unusual because although I’m based in Ireland most things posted from the UK arrive within 2-5 working days, even on second class post.
I sent an email on the 23rd of October asking if Mr Cloud had received my order whilst explaining that I didn’t get any sort of order confirmation, and if they did, had they shipped the order yet.
Later that day I got my one and only communication from Mr Cloud which answered none of the questions raised above, all it said was:
It may take up to 28 days
A quick check of Mr Cloud’s Terms page did indeed confirm that non-UK orders would take up to 28 days, fair enough, but a little bit more info in the reply would have been nice.
I replied on the 24th of October asking if they could maybe nudge the order seeing as it was for Ciaran’s birthday on the 2nd of November, and asked again if Mr Cloud (or Craig Hesmondhalgh who is apparently the proprietor of the business) could confirm if the order had shipped.
There was no reply and I emailed again on the 25th of October asking politely if he could answer my question about whether the order had shipped. I got no response and decided to leave chasing the order until 28 days was up.
On the 7th of November the postman had been and gone and still no t-shirt, and still no communication from Mr Cloud. I emailed him again explaining that 28 days had now passed since I placed my order and that there was nothing in the post from him, could he confirm the order had been posted.
Having had no reply by 2pm on the 8th of November I emailed once again:
It’s now 29 days since I ordered this item and it still hasn’t arrived. Ireland is not the other side of the world and the postal service between the UK and ROI is fairly efficient with most items being delivered within 2-3 days of posting.
Where is my t-shirt?
Having had no response by mid-day on the 9th of November I opened a PayPal dispute which was resolved this morning with a refund and no explanation from Mr Cloud. Getting the refund is fine, but what a fucking waste of time.
With hindsight this will teach me not to Google around for complaints and disputes about a company I’ve never dealt with previously before spending money with them. Having done that in the past few days turned up these links about Mr Cloud’s past form:
I know this is a bit of a speil but if Google indexes this article and at least one person is saved the hassle of dealing with this company then my work is done.]]>
<% wsdl = "https://mysecure.service.com/Service.asmx?wsdl" Set service = CreateObject("MSSOAP.SoapClient30") service.ClientProperty("ServerHTTPRequest") = True Call service.MSSoapInit(wsdl) %>
The above code suddenly starts throwing this error for no apparent good reason:
WSDLReader error '80020009' WSDLReader:XML Parser failed at linenumber 0, lineposition 0, reason is: System error: -2147012721. HRESULT=0x1: Incorrect function. - WSDLReader:Loading of the WSDL file failed HRESULT=0x80070057: The parameter is incorrect. - Client:One of the parameters supplied is invalid. HRESULT=0x80070057: The parameter is incorrect. /services/WS.inc, line 5
Then after half an hour of head scratching I realise the SSL certificate has probably expired…and lo and behold it has.
Maybe next year the penny will drop more quickly. :)]]>
mercurial-server is one of many shared SSH publishing solutions to allow your development team have access to your central repository collection.
It kind of works like this. A single SSH account (
hg) is created on your Mercurial central repo server. This account acts as a gateway account and it also owns all of the repositories on the server. The account is heavily restricted. You can’t logon to it using a username and password, only SSH keys are permitted and these keys must be imported using mercurial-server’s
refresh-auth script (or via upload to a special administrative repository once the administrator’s public key has been installed).
Each developer generates a public and private SSH key pair. Their public key is uploaded to central repository server and is added to the
~hg/.ssh/authorized_keys file using the
refresh-auth script (or via the
hgadmin administrative repository.
authorized_keys record also has the
command option specified which restricts the
hg logon to a single operation regardless of any commands specified by the client (which are ignored). For example:
no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command="/usr/local/share/mercurial-server/hg-ssh root/bob/bob.pub" ssh-dss AAAAB3NzaC1kc...Qfa02w== firstname.lastname@example.org
For a more detailed explanation of how this works see: How mercurial-server works
First off, download and unzip mercurial-server from here:
mercurial-server 1.2 sources
wget http://dev.lshift.net/paul/mercurial-server/mercurial-server_1.2.tar.gz tar zxf mercurial-server_1.2.tar.gz cd mercurial-server_1.2.orig
Before building and installing there’s some tweaks I needed to make for my CentOS install.
On CentOS we need to prevent the docbook files being built. They’re not necessary and the build will fail on CentOS if you try to build them.
Makefile, at around line 53 you’ll see this step:
installfiles: installetc installdoc pythoninstall
I removed the
installdoc reference, so it should look like this:
installfiles: installetc pythoninstall
Next we need to amend the
useradd command switches at around line 61. CentOS doesn’t support the
--system switch and we need to use
useradd: useradd -r --shell /bin/sh \ --home /var/lib/mercurial-server --create-home \ --comment "Mercurial repositories" $(NEWUSER)
Finally, because I have both Python 2.4 and 2.7 installed and my Mercurial installation has been installed for Python 2.7, I need to ensure that Python 2.7 is called.
To make this easier I modified the
Makefile just a bit more and added a
PYTHON variable to point to the default version of python I want to use. This is because
make doesn’t expand bash aliases, so even if you’ve aliased
python to Python 2.7 it’ll be ignored. Setting a
PYTHON variable and using that makes life easier. It also means you can override the python version from the command line. This is my revised
#!/usr/bin/env make -f PREFIX=/usr/local/share LIBDIR=$(PREFIX)/mercurial-server DOCDIR=$(PREFIX)/doc/mercurial-server ETCDIR=/etc/mercurial-server NEWUSER=hg DOCBOOK_XSL=/usr/share/xml/docbook/stylesheet/nwalsh PYTHON=/usr/bin/python2.7 INSTALL=install build: build/html/index.html pythonbuild setup-adduser: installfiles adduser inituser # WARNING: this is experimental setup-useradd: installfiles useradd inituser remove: rm -Rfv $(DESTDIR)$(ETCDIR) rm -Rfv $(DESTDIR)$(LIBDIR) userdel -rf $(NEWUSER) installetc: $(INSTALL) -d $(DESTDIR)$(ETCDIR) $(INSTALL) -m 644 -t $(DESTDIR)$(ETCDIR) \ src/init/conf/access.conf $(INSTALL) -d $(DESTDIR)$(ETCDIR)/remote-hgrc.d $(INSTALL) -m 644 -t $(DESTDIR)$(ETCDIR)/remote-hgrc.d \ src/init/conf/remote-hgrc.d/access.rc \ src/init/conf/remote-hgrc.d/logging.rc $(INSTALL) -d $(DESTDIR)$(ETCDIR)/keys/root $(INSTALL) -d $(DESTDIR)$(ETCDIR)/keys/users installdoc: build/html/index.html $(INSTALL) -d $(DESTDIR)$(DOCDIR) $(INSTALL) -m 644 -t $(DESTDIR)$(DOCDIR) README $(INSTALL) -d $(DESTDIR)$(DOCDIR)/html $(INSTALL) -m 644 -t $(DESTDIR)$(DOCDIR)/html build/html/index.html build/html/index.html: doc/manual.docbook xsltproc --nonet -o $@ $(DOCBOOK_XSL)/html/docbook.xsl $^ build/pdf/manual.pdf: doc/manual.docbook mkdir -p build/pdf fop -xml $^ -xsl $(DOCBOOK_XSL)/fo/docbook.xsl $@ pythonbuild: $(PYTHON) setup.py build pythoninstall: $(PYTHON) setup.py install \ --install-purelib=$(DESTDIR)$(LIBDIR) \ --install-platlib=$(DESTDIR)$(LIBDIR) \ --install-scripts=$(DESTDIR)$(LIBDIR) \ --install-data=$(DESTDIR)$(LIBDIR) installfiles: installetc pythoninstall adduser: adduser --system --shell /bin/sh --group --disabled-password \ --home /var/lib/mercurial-server \ --gecos "Mercurial repositories" $(NEWUSER) # WARNING: this is experimental useradd: useradd -r --shell /bin/sh \ --home /var/lib/mercurial-server --create-home \ --comment "Mercurial repositories" $(NEWUSER) inituser: su -l -c "$(DESTDIR)$(LIBDIR)/init/hginit $(DESTDIR)$(LIBDIR)" $(NEWUSER)
I also added a
remove rule to clean up and remove mercurial-server so you can do
make remove. I left the docbook rules in place because one day I might get around to fixing that for CentOS, however they don’t get called.
All that remains now is to build and install mercurial-server, do this by running:
The first thing we need to do is generate and install the administrators SSH public and private key pairs. If you already have a pair of key files you want to use then skip the next step:
To generate a new public/private key pair then use
[root@vostro1700 ~]# ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): kevin_rsa Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in kevin_rsa. Your public key has been saved in kevin_rsa.pub. The key fingerprint is: 86:fc:13:23:ec:3b:41:01:fb:59:b8:75:a9:da:cb:57 email@example.com [root@vostro1700 ~]#
You can do this on the mercurial server machine or you can do this on your workstation. Ultimately we want to get the public key file (kevin_rsa.pub) onto the server.
Once you’ve generated a pair of key files and you’ve got the public key file onto the mercurial server we need to copy it to the mercurial-server
keys/root folder and then instruct mercurial-server to “import” it to the
sudo mkdir -p /etc/mercurial-server/keys/root/kevin sudo cp kevin_rsa.pub /etc/mercurial-server/keys/root/kevin sudo -u hg /usr/local/share/mercurial-server/refresh-auth
We’re now ready to create new repositories.
Connecting From Linux
If your client machine is Linux and you’re already using SSH keys to authenticate against remote servers then the following will be familiar. First we start
ssh-agent, then we add our private key. This means we don’t have to re-type our password:
$ eval `ssh-agent` Agent pid 13464
What we just did there was launch ssh-agent but evaluate the output, this sets up a couple of handy environment variables (SSH_AUTH_SOCK and SSH_AGENT_PID). If we just did
ssh-agent on its own then we’d see:
SSH_AUTH_SOCK=/tmp/ssh-RnDfd13515/agent.13515; export SSH_AUTH_SOCK; SSH_AGENT_PID=13516; export SSH_AGENT_PID; echo Agent pid 13516;
Next we need to add our private key:
$ ssh-add kevin_rsa Enter passphrase for kevin_rsa: Identity added: kevin_rsa (kevin_rsa) $
Finally lets see if we can create a new repository on the remote server:
$ hg init ssh://firstname.lastname@example.org/helloworld
If all is well then you should see a
helloworld folder appear in
Connecting From Windows – TortoiseHg
On my Windows Workstation I have the Selenic TortoiseHg bits installed. I also have PuTTY and its related tools installed as well because I use PuTTY but I also need PuTTYgen as well.
There’s a bit of a gotcha with PuTTY and SSH key files. If you generated your keyfiles using ssh-keygen then they need to be converted to work with PuTTY and Pageant (PuTTY’s equivalent of ssh-agent).
To do this launch PuTTYgen and select “Conversions -> Import key”:
Locate your private key file (kevin_rsa) which was generated using ssh-keygen and open it. You’ll be prompted for the private key’s password, enter it and hit enter. If the key file is imported successfully then PuTTYgen will pop up a notice and tell you what to do next:
Click OK and then click on “Save private key”, I saved mine as “kevin_rsa_putty.ppk” (the PuTTY tools like to see the .ppk extension so you may as well go along with that).
As an aside I save my keys in a hidden “.ssh” folder in my
As I mentioned earlier, Pageant does the equivalent job of ssh-agent. When you launch Pageant it’ll minimise itself into the notification area:
Load up your newly converted private key into Pageant by right clicking on it’s icon and selecting “Add Key”:
You’ll prompted for your private key file’s password so enter it and hit enter. To confirm the key is loaded right click on Pageant’s notification icon and select “View Keys”. All being well we should see our key in the key list:
Next we need to tell TortoiseHg about our SSH settings. In your Windows
%USERPROFILE% directory there should be a file called
mercurial.ini. If there isn’t then create one. Mine looks like this:
[tortoisehg] ui.language = en_GB vdiff = kdiff3 [ui] merge = kdiff3 username = kevin <email@example.com> verbose = True ssh="C:\Program Files\TortoiseHg\TortoisePlink.exe" -ssh -2 -agent -v
The important line line is the one that says:
ssh="C:\Program Files\TortoiseHg\TortoisePlink.exe" -ssh -2 -agent -v
TortoisePlink.exe is a recompiled variant of PuTTY’s Plink tool. Plink is the equivalent of Unix’s ssh tool.
That line is instructing TortoiseHg to connect to our remote Mercurial server using TortoisePlink and pickup our private key along the way from Pageant.
Save mercurial.ini and then open a command line window. Next try to create a new repository on your remote Mercurial server (I have all the verbosity switches turned on just so we can see what’s happening under the bonnet):
hg init ssh://firstname.lastname@example.org/anewrepo
This should result in output that looks similar to this:
running "C:\Program Files\TortoiseHg\TortoisePlink.exe" -ssh -2 -agent -v email@example.com "hg init anewrepo" running ""C:\Program Files\TortoiseHg\TortoisePlink.exe" -ssh -2 -agent -v firstname.lastname@example.org "hg -R anewrepo serve --stdio"" remote: Looking up host "hg.zygonia.net" remote: Connecting to 172.16.3.21 port 22 remote: Server version: SSH-2.0-OpenSSH_4.3 remote: We claim version: SSH-2.0-PuTTY_Local:_Feb_27_2009_19:14:38 remote: Using SSH protocol version 2 remote: Doing Diffie-Hellman group exchange remote: Doing Diffie-Hellman key exchange with hash SHA-1 remote: Host key fingerprint is: remote: ssh-rsa 2048 6f:23:ab:c8:4a:12:8a:d9:b0:36:09:b4:49:54:97:c0 remote: Initialised AES-256 SDCTR client->server encryption remote: Initialised HMAC-SHA1 client->server MAC algorithm remote: Initialised AES-256 SDCTR server->client encryption remote: Initialised HMAC-SHA1 server->client MAC algorithm remote: Pageant is running. Requesting keys. remote: Pageant has 1 SSH-2 keys remote: Using username "hg". remote: Trying Pageant key #0 remote: Remote debug message: Pty allocation disabled. remote: Remote debug message: Port forwarding disabled. remote: Remote debug message: X11 forwarding disabled. remote: Remote debug message: Agent forwarding disabled. remote: Remote debug message: Forced command: /usr/local/share/mercurial-server/hg-ssh root/kevin/kevin_rsa.pub remote: Authenticating with public key "imported-openssh-key" from agent remote: Sending Pageant's response remote: Remote debug message: Pty allocation disabled. remote: Remote debug message: Port forwarding disabled. remote: Remote debug message: X11 forwarding disabled. remote: Remote debug message: Agent forwarding disabled. remote: Remote debug message: Forced command: /usr/local/share/mercurial-server/hg-ssh root/kevin/kevin_rsa.pub remote: Access granted remote: Opened channel for session remote: Started a shell/command remote: Sent EOF message remote: Server sent command exit status 0 remote: Disconnected: All channels closed
Logon to your repository server and look in the
/var/lib/mercurial-server/repos folder, there should be a new directory in there called
A Gotcha: When running Pageant and TortoiseHg, make sure that if you run either as “Administrator”, both run as administrator. I had an hour or so of head scratching when running
hg init ssh://email@example.com/anewrepo from an command prompt opened using “Run As Administrator” whilst Pageant was running under my normal Windows account.
In the next article I’ll cover adding new users and joining up the mercurial-server repository with Apache.
Very useful resources:
Sharing Mercurial repositories with mercurial-server
Using ssh-agent with ssh
Using Pageant for authentication
Configure Apache + mod_wsgi
Load up your apache
httpd.conf file into your favourite editor and add the following lines:
LoadModule wsgi_module modules/mod_wsgi.so AddHandler wsgi-script .wsgi WSGIPythonHome /opt/python2.7.2
That last line ensures that mod_wsgi knows which Python to invoke.
On my system I’m using named virtual hosts, this is what my Mercurial’s site virtual host configuration looks like:
<VirtualHost 172.16.3.21:80> ServerName mercurial ServerAlias hg.mydomain.com ServerAdmin root@localhost DocumentRoot /sites/mercurial/htdocs WSGIScriptAlias / /sites/mercurial/htdocs/cgi-bin/hgweb.wsgi </VirtualHost>
Under your document root create a folder called
cgi-bin and create a file in there called
To verify that
mod_wsgi is working I used the trouble-shooting script found on the “Installation Issues” section of the mod_wsgi site. So drop that code into the newly created
hgweb.wsgi file and save it:
import sys def application(environ, start_response): status = '200 OK' output = 'Hello World!' response_headers = [('Content-type', 'text/plain'), ('Content-Length', str(len(output)))] start_response(status, response_headers) print >> sys.stderr, 'sys.prefix = %s' % repr(sys.prefix) print >> sys.stderr, 'sys.path = %s' % repr(sys.path) return [output]
When you browse to your site you should see:
Hello World! in my browser. So far so good.
If the above works then replace the contents of
hgweb.wsgi with the following:
# An example WSGI for use with mod_wsgi, edit as necessary # See http://mercurial.selenic.com/wiki/modwsgi for more information # Path to repo or hgweb config to serve (see 'hg help hgweb') config = "/sites/mercurial/htdocs/cgi-bin/hgweb.config" # Uncomment and adjust if Mercurial is not installed system-wide: #import sys; sys.path.insert(0, "/path/to/python/lib") # Uncomment to send python tracebacks to the browser if an error occurs: #import cgitb; cgitb.enable() # enable demandloading to reduce startup time from mercurial import demandimport; demandimport.enable() from mercurial.hgweb import hgweb application = hgweb(config)
You can find this file in the Mercurial source in the
contrib folder. If you’ve followed my instructions to the word
Next create a new file in the
cgi-bin folder called
hgweb.config and add the following:
[paths] / = /sites/mercurial/htdocs/repos/** [web] allow_push = * push_ssl = false
Create a folder for your repositories under your document root and initialise a new repository:
mkdir repos cd repos hg init testrepo
You should now be able open the Mercurial repository browser by opening: http://hg.mydomain.net
You also need to ensure that your web server’s user can read and write to your repositories. On a default apache install on CentOS this should look like:
chown -R apache:apache /sites/mercurial/htdocs/repos chmod -R g+rw /sites/mercurial/htdocs/repos chmod g+x /sites/mercurial/htdocs/repos
You also need to make each repository folder and it’s
.hg folder executable as well:
chmod g+x /sites/mercurial/htdocs/repos/testrepo chmod g+x /sites/mercurial/htdocs/repos/testrepo/.hg
For more info see: Mercurial – 8. Troubleshooting
To test your Mercurial server go to a different machine and do:
E:\>md hg_test E:\>cd hg_test E:\hg_test>hg clone http://hg.zygonia.net/testrepo destination directory: testrepo no changes found updating to branch default resolving manifests 0 files updated, 0 files merged, 0 files removed, 0 files unresolved E:\hg_test>cd testrepo E:\hg_test\testrepo>copy con test.txt Hello World! ^Z 1 file(s) copied. E:\hg_test\testrepo>hg add test.txt adding test.txt E:\hg_test\testrepo>hg commit test.txt -m "Test commit" test.txt committed changeset 0:1904a8ab9a97 E:\hg_test\testrepo>hg push http://hg.zygonia.net/testrepo pushing to http://hg.zygonia.net/testrepo searching for changes 1 changesets found remote: adding changesets remote: adding manifests remote: adding file changes remote: added 1 changesets with 1 changes to 1 files E:\hg_test\testrepo>
If we browse to our repository we can see the file we just pushed:
If you follow all of the steps exactly you should end up with a basic but working Mercurial server that you can use to push and pull changesets to.
Obviously you should secure this server if it’s public facing (mine is secured with a simple
.htaccess/.htpassword affair for now).
There were a number of sites and documents online that helped me to get this far, these included:
The following Mercurial articles also helped:
For this build I used:
PyPi Setup Tools 0.6c11
First off download all of the files listed above to
cd /usr/local/src wget http://www.python.org/ftp/python/2.7.2/Python-2.7.2.tgz wget http://www.sqlite.org/sqlite-autoconf-3070800.tar.gz wget http://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11-py2.7.egg wget http://modwsgi.googlecode.com/files/mod_wsgi-3.3.tar.gz wget http://prdownloads.sourceforge.net/docutils/docutils-0.8.1.tar.gz wget http://mercurial.selenic.com/release/mercurial-1.9.3.tar.gz tar zxf Python-2.7.2.tgz tar zxf sqlite-autoconf-3070800.tar.gz tar zxf mod_wsgi-3.3.tar.gz tar zxf docutils-0.8.1.tar.gz tar zxf mercurial-1.9.3.tar.gz
There are a few dependencies we’ll need, some might already be installed:
yum -y install gcc gdbm-devel readline-devel ncurses-devel zlib-devel bzip2-devel sqlite-devel db4-devel openssl-devel tk-devel bluez-libs-devel make
Build and install SQLite3:
cd sqlite-autoconf-3070800 ./configure make make install cd ..
CentOS 5.5 ships with Python 2.4 which is fine for Mercurial but I wanted to use Python 2.7 for some other stuff as well. This explains how to install Python 2.7 side by side with 2.4 (which would be a real bugger to evict from your system due to the huge number of dependencies there are – yum for example).
I installed Python 2.7 into
/opt/python2.7.2, to do this:
cd Python-2.7.2 ./configure --prefix=/opt/python2.7.2 --with-threads --enable-shared make make install cd ..
When you execute
make it’s possible you’ll get this message:
Python build finished, but the necessary bits to build these modules were not found:
bsddb185 dl imageop
Don’t worry, Python was built successfully, it just means these modules aren’t supported. For our purposes it won’t break anything not to have these modules, they are either deprecated or not relevant.
Next we need to tell
ld where to find our Python 2.7 shared libraries:
touch /etc/ld.so.conf.d/opt-python2.7.2.conf echo "/opt/python2.7.2/lib/" >> /etc/ld.so.conf.d/opt-python2.7.2.conf ldconfig
Then we create a link to Python 2.7 in
/usr/bin and fix up our bash profile to use 2.7:
ln -sf /opt/python2.7.2/bin/python /usr/bin/python2.7 echo "alias python=/opt/python2.7.2/bin/python" >> ~/.bash_profile echo "alias python2.7=/opt/python2.7.2/bin/python" >> ~/.bash_profile echo "PATH=$PATH:/opt/python2.7.2/bin" >> ~/.bash_profile source ~/.bash_profile
If all is well you should see the following when you launch
Python 2.7.2 (default, Oct 21 2011, 10:46:56)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-51)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
Press Ctrl+D to exit back to bash.
PyPi, pip, virtualenv (optional)
Although not strictly necessary I also installed these to flesh out my Python dev environment:
cd /usr/local/src sh setuptools-0.6c11-py2.7.egg --prefix=/opt/python2.7.2 /opt/python2.7.2/bin/easy_install pip ln -sf /opt/python2.7.2/bin/pip /usr/bin/pip pip install virtualenv ln -sf /opt/python2.7.2/bin/virtualenv /usr/bin/virtualenv
Mercurial requires Docutils. When installed this for the first time I had to explicitly call python 2.7 to ensure that Docutils was installed to
/opt/python2.7 and not the default Python 2.4 install (that said it’s no big deal if it does also end up being installed there):
cd docutils-0.8.1 python2.7 setup.py install cd ..
Drop into the mercuria source directory:
Build and install Mercurial:
make PYTHON=/opt/python2.7.2/bin/python PREFIX=/opt/python2.7.2 all make PYTHON=/opt/python2.7.2/bin/python PREFIX=/opt/python2.7.2 install cd ..
Pay particular attention to the
PREFIX=/opt/python2.7.2 arguments, these ensure that mercurial is built using our Python 2.7 install and gets installed in the correct
hg version and hit return, if all is good you should see:
Mercurial Distributed SCM (version 1.9.3)
(see http://mercurial.selenic.com for more information)
Copyright (C) 2005-2011 Matt Mackall and others
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
To build mod_wsgi you need to ensure that the
httpd-devel package is installed, I’m assuming you already have apache installed, so go ahead and do that now:
yum install httpd-devel
Next we do the build, and be sure to configure for Python 2.7:
cd mod_wsgi-3.3 ./configure --with-python=/opt/python2.7.2/bin/python make make install
If all is good then you’ll find
mod_wsgi.so in your apache modules folder:
$ ll /usr/lib/httpd/modules/mod_wsgi.so -rwxr-xr-x 1 root root 303801 Oct 21 12:12 /usr/lib/httpd/modules/mod_wsgi.so
Continued in Part #2…]]>