Blog

Publishing Using GIT

Git, for those unaware, is a version control system. It tracks changes that you make to files and lets you review history, revert back to older versions, and do all sorts of useful stuff. It comes into its own when you work with groups of developers – you can each work on different parts of a project, and then very cleanly merge your changes together into an authoritative master version of the codebase.

Even if, like me, you’re the only one working on your code it’s still a great tool. So far I haven’t had to revert back to an old version of my code, but it’s nice to know I could if I wanted to. What I primarily use it for however is (in my opinion) way more useful than its stated purpose.

Publishing Websites Using Git

I have a webserver within my home network. It’s open to the world and I could host my little teeny-tiny web empire on it probably quite nicely. But commercial webhosts offer much better uptime than I might get from using my home internet connection, and certainly much better download speeds for end users like you. So I don’t. I have a VPS that hosts the “production” versions of my web work, and I use my home server as a “development” environment.

What I use git for is publishing from the development to the production server. If you have a similar setup using a local xAMP stack for development then you can probably replicate my setup quite nicely to your advantage. It makes publishing to the web a one-step process, and it uses SSH so the publishing is done over a secure connection.

The prerequisites:

  • Webserver with shell access and git installed
  • Local machine (development server, in my case) with terminal access and git installed
  • Passwordless SSH setup between the local machine and webserver (read this)
  • xAMP or a similar environment on the local machine

Strictly speaking that last point isn’t a requirement, but this setup only really comes into its own if you can test code locally and then only publish it once you’re happy with the results.

The Server

We’ll take care of the server side of things first. Create a directory outside your webserver root that will hold the git meta-data. On my server the web root is at /home/account/domain/. I think this is atypical, so your set-up may be different.

mkdir /home/account/domain.git
cd /home/account/domain.git
git init --bare

Next we need to tell git where to actually put the files:

git config core.worktree /home/account/domain
git config core.bare false
git config receive.denycurrentbranch ignore

Finally, we need to tell git what to do for us when new files are pushed to the server’s git repository. Create a file called hooks/post-receive

vi hooks/post-receive

In the file:

#!/bin/sh
git checkout -f

This file needs to be executable.

chmod +x hooks/post-receive

The Local Machine

Navigate to the directory where the website code lives.

git init
git add .
git commit -m 'Initial Commit'

Next, link the repository on the webserver:

git remote add origin ssh://[email protected]/home/account/domain.git

Finally, “push” all the content from the local machine to the server:

git push origin master

Done! Depending on the size of your codebase and speed of your connection it may take a few moments the first time, but since git is smart enough to only push content that’s changed, it will be quicker next time.

From now on, whenever you’ve made some changes on the development machine that are ready to be published to production, run:

git add .
git commit -a -m ā€˜Change Descriptionā€™
git push

I put these three lines into a little bash script, and I can publish using a little web control panel I made using PHP (relying on PHP’s exec function). Also in my control panel I have the ability to push and pull databases from the server thanks to this page and the comments on it. Simple!

Blog

PHP Unzip

Because my free webhost places a limit on the number of files that can be uploaded using FTP, I needed to come up with a way to upload an archive and then unzip it on the server. Even if weren’t for the limit, this is still a potentially great idea – when uploading FTP opens a connection to the server forĀ every file it uploads, so uploading an archive file of 25mb is significantly faster than uploading a thousand smaller files that total 25mb for example.

After some googling, I found some code that makes use of PHP’s built in zip file compatability to allow me to upload a zipped archive and along with a single PHP file. My tool first unzips the archive into a folder corresponding to the archive name, then deletes the original archive file and finally deletes itself.

I didn’t write the code below, merely adapted it for my own purposes. Unfortunately I don’t remember where I found it so I’m unable to credit the original author.

The code is below and it’s also available for quick and easy download via the link at the top right of this page. There are more detailed usage instructions at the bottom of the page.

<?php
	if (!isset($_GET['src'])) echo "Usage: unzip.php?src=<em><strong>file.zip</strong></em>";
	else {
		unzipnew($_GET['src']);
		unlink("unzip.php");
	}

	function unzipnew($src_file, $dest_dir=false, $create_zip_name_dir=true, $overwrite=true, $delzip=true) {
		$filecounter = 0;
		echo "<p>Writing files (a count of files written will be at the bottom the page)...</p>";
		if ($zip = zip_open($src_file)) {
			if ($zip) {
				$splitter = ($create_zip_name_dir === true) ? "." : "/";
				if ($dest_dir === false) $dest_dir = substr($src_file, 0, strrpos($src_file, $splitter))."/";
				create_dirs($dest_dir);
				while ($zip_entry = zip_read($zip)) {
					$pos_last_slash = strrpos(zip_entry_name($zip_entry), "/");
					if ($pos_last_slash !== false) {
						create_dirs($dest_dir.substr(zip_entry_name($zip_entry), 0, $pos_last_slash+1));
					}
					if (zip_entry_open($zip,$zip_entry,"r")) {
						$file_name = $dest_dir.zip_entry_name($zip_entry);
						if ($overwrite === true || $overwrite === false && !is_file($file_name)) {
							$fstream = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
							@file_put_contents($file_name, $fstream );
							chmod($file_name, 0777);
							echo "File written: ".$file_name."<br />";
							$filecounter++;
						}
						zip_entry_close($zip_entry);
					}
				}
				zip_close($zip);
				if($delzip) unlink($src_file);
				echo "<p>".$filecounter." files written.</p>";
			}
		} else {
			return false;
		}
		return true;
	}

	function create_dirs($path) {
		if (!is_dir($path)) {
			$directory_path = "";
			$directories = explode("/",$path);
			array_pop($directories);
			foreach($directories as $directory) {
				$directory_path .= $directory."/";
				if (!is_dir($directory_path)) {
					mkdir($directory_path);
					@chmod($directory_path, 0777);
				}
			}
		}
	}
?>

Usage instructions:

  1. Save the file as unzip.php (or download it using the link at the top right of this page) and upload it along with the zipped archive you’d like to extract to a folder of your choice.
    For the purposes of an example, let’s say you’re uploading it to the root of your website, foo.com, and the archive you have is named stuff.zip
  2. Once it’s uploaded, open a web-browser and navigate to the unzip.php file, adding the archive filename as a an attribute in the URL named src.
    E.g., foo.com/unzip.php?src=stuff.zip
  3. The files within stuff.zip will be extracted to foo.com/stuff, and any directory structure that existed within the stuff.zip archive is retained.
  4. Both the original archive file, stuff.zip, and the tool itself, unzip.php, are deleted at the end of the process.

Enjoy!

Blog

40 Days, and 40 Nights

I hear on theĀ newsĀ there are rolling blackouts across Alberta (nothing here yet) because the heat today is causing a huge demand for power.

Because Iā€™m a huge geek, I thought I would take the opportunity to snap this quick screenshot, just in case šŸ˜›

Blog

Tasker

This evening, I have been discoveringĀ TaskerĀ for Android. Iā€™ve downloaded the seven day trial and Iā€™m just getting things set up to try it out before I decide whether itā€™s worth $6, but it kinda seems like it is.

So far I have it set up to automatically enable WiFi when Iā€™m at home (and disable it again when I leave), set the phone to vibrate-only when Iā€™m in the office (and again, set it back to noisy when I leave) and turn the internet off at 10pm on school nights, midnight on weekends and turn it back on again at 6:45am (so I donā€™t get woken up by email or chat notifications).

There are literallyĀ hundreds of possible thingsĀ you can do with it if youā€™re willing to invest a little time (preciselyĀ because thereā€™s so much you can do with it thereā€™s some complexity involved) and I already have plans to dive into in a little more depth and set upĀ custom text notifications for some people, assuming I decide to purchase the app.

I may also have itĀ automatically open maps/navigation if it detects Iā€™m in the car. That oneā€™s certainly more in-depth. The possibilities are endless!

Blog

Dumpster Diving

Last week I broke my in-ear headphones – the ones I use when I walk to work and in the gym.

Yesterday I fixed the problem by replacing them during a quick trip to Walmart (and I picked up some nice new over the ear headphones while I was at it, to use at work).

Last night when I got home I grabbed the over the ear headphones I use at home and unpacked my two new pairs to do a quick comparison. Both new pairs were better than my existing pair, and I was pleased.

This morning I got up and set about tidying the living room. All the packaging from the new headphones was in one of the shopping bags I had from Walmart, so I threw it down the garbage chute.

Five minutes later I go to put both the new pairs of headphones into my man bag to take them to the office tomorrow, and I canā€™t find the in-ear ones. After 15 minutes spent tearing my living room apart and throwing sofa cushions everywhere, only one conclusion remains. Iā€™d thrown them out along with the packaging.

Luckily when I went downstairs to the garbage room the dumpster was fairly full and the bag Iā€™d thrown out was more or less at the top. Luckily nobody had thrown any weird disgusting shit down there since Iā€™d thrown my stuff out. Luckily the bag was tied and the headphones hadnā€™t fallen out and to the bottom of the dumpster.

This was my first dumpster diving experience, and Iā€™m not keen to repeat it anytime soon. But at least I have my new headphones back.

Blog

Oops

About a month ago my credit card cracked down the centre, so I called and asked to have it replaced with a new one.

All went well until today. Seems like I forgot to tellĀ Netflix,Ā ShawĀ orĀ Virgin MobileĀ that they canā€™t take their bills from the old card anymore. Oops.

Luckily Netflix were the first to notice (and cut off my service), because theyā€™re the least important and they allow for instant reactivation.

Iā€™ll try and remember this next year when the card expires and gets replaced again.

Blog

Pretty soon Iā€™ll be working on improving the appearance of my daily digest posts, but for now Iā€™m working on adding content.

I havenā€™t checked in anywhere since the weekend, but IĀ thinkĀ that myĀ foursquareĀ updates will also be included now.

Either that, or the whole thing will fail when it tries to run itself at midnight tonight. Who knows. I havenā€™t tested it yet.

Blog

So, I very much screwed up the script that automatically posts my daily digest updates.

It was a simple mistake, but the results were pretty profound. In a nutshell, instead of setting it to run once at midnight, I accidentally set it to run every minute where the hour on the clock was zero, the end result being 60 identical posts every night between midnight and 1am.

I think itā€™s safe to say that I donā€™t have any subscribers on here yet, but if I do then I apologise.Ā Iā€™ve fixed it now.

It looks like my updates fromĀ twitterĀ andĀ facebookĀ are being published successfully though. Next up is flixster and foursquare. I was going to get that working tonight, but Iā€™m extremely tired so it might just be a job for another day instead.

Blog

Progress

Iā€™ve begun writing the code that will automatically post a daily (probably) digest of my activities from elsewhere on the web to my shiny new tumblr here, and Iā€™m seriously thinking about bringing back late night links!

Watch this space šŸ™‚

In other news, one of the main points of tumblr (as I understand it, anyway) is itā€™s social aspect. I see that you can ā€œreblogā€ stuff, for example. I donā€™t follow anybody though. Who should I be following? Make me a suggestion in the comments. Waitā€¦ are there comments? I have much to learn.

Blog

Hello (again), world…

Recently, the automated scripts that runĀ my websiteĀ have broken. I can run them manually just fine, but I donā€™t really want to do that. Theyā€™re supposed to run all on their own at 16 minutes past every hour.

The website is hosted with a free provider so much as I can complain, it doesnā€™t mean theyā€™ll get around to fixing it any time soon. My website is a mix of things I like to keep online. Thereā€™s a library of photos and video that I share, but increasingly in these days of social media things like that are much more fleeting – when you share something online people care about it for an hour or so, then itā€™s forgotten amongst the noise of newer updates from other friends.

TheĀ infrastructureĀ for all this is not easy to maintain on an individual basis, so I think Iā€™m just going to stop doing it.

Iā€™m not sure yet, but tumblr just might be my new online home. I think I can write some code that will run on my home server every day to post a few automated updates so that pictures I take and updates I post elsewhere will automatically feed into here, and I wonā€™t worry about the old photo albums and videos because nobody really cares to go that far back anyway.

But weā€™ll see if I ever get around to updating it or not. I havenā€™t updated myĀ previous blogĀ in two months though, so thereā€™s not a lot of point maintaining it.