It’s been a while since I started this. Sorry for the delay.
Source Control is pretty easy to use when used correctly and consistently. If you start to do odd things, then it starts to twist your mind.
First up, you have a repository. This is object you are working with and where your files live happily in harmony.
The repository is divided logically into three sections. These are just names, you can replace them with what you want, but the normal nomenclature is TTB: Trunk, Tags, and Branches. I first came across this when working with Subversion but can be used in VSS, TFS and any other TLAs you can think of.
The trunk is the working copy of your application/web-site. This should always be able to be checked out and compiled. The top of the trunk where the latest code lives is called the head.
The branches is where you perform the modifications to the source. More on this in a bit.
Tags is where you have a specified release of the repository – this is so you can roll back to a previous known working copy if something has gone arse over tits.
Now you know what the logical structure of the repository is what do you want to do with?
If you don’t have anything in the repository you need to fill it.
The first thing you do is put a clean working copy of the source into trunk. This should have no dead files, no file with things called index.htm.old (or similar). Also when checked out it should compile and run without crashing or when mounted on the webserver, run fine. This is the bit that people don’t seem to get. If you check the file out to a clean PC with just the compiler then you should be able to build/run the app. Too many times have I branched and found the source doesn’t compile because FooWidget2000.dll cannot be found. Turns out that FooWidget2000 is availble in R:\Software on the network or is a free download from SourceForge.
That’s not right. *Everything* needed to build the project should be under version control. Also documentation of the project should be in there too. Most large corporations use Windchill (aka Global Vault) to store their documents, but I prefer to keep the documentation with the source – closer the better. Microsoft make a repository viewer which is great for project manager to access the documentation while not having to learn the arcane commands – source control isn’t just for source any more.
Now we have everything in place it’s time to start making changes. Let’s identify a necessary change – the foo widget is displaying the wrong value for bar. You think you know what is going on so you begin to branch the source into branches – but how should you do it?
Well my way is to have the user create a folder within branches for his (or her) changes:
projects/bugatti/trunk
/tags
/branches/graham.reeds/id00001
/id00002
Within that user folder you create sub-folders for each branch you make. What constitutes a branch? Well I use branches mainly for performing a bug-fix. Did you note the use of singular?
If you are working with a specified bug tracking system (like Trac or Mantis) then you can use the assigned bug id number, or if you are working on a new piece of software then you can call it by the task you are performing. I use a mixture of the two.
You can forgo the username, but I prefer it this way. People tend to point out you can use blame (or praise) and such to see who worked on what, but I prefer the username method. If you have your name stamped on it, then you are more likely to have a sense of pride in your work. You do have a sense of pride about your craft, don’t you?
Then when you have fixed problem with bar’s value you then merge the corrections back into the trunk. Usually the merging is only done after the fixes have been peer reviewed and approved by the lead coder – you don’t want substandard code to be checked in because if the original coder leaves then it will probably be you who have to work on it – so any bad smells in the code you should flag up immeadiately. (Also don’t take the process personally – it’s tempting to nitpick if the person’s code you are reviewing grilled you over your previous submission.)
Once the source is back in the trunk then that will be tested by the testing department – you’ve tested it yourself but a decent tester will test it in half a dozen ways while programmers tend to skip through to that bit and use keyboard shortcuts the entire time, etc.
This may be the last bug to be fixed before the latest release is pushed out the door. If you are on schedule, congrats. If not, well done on getting it finished.
Now this release needs to be marked in someway. This enables you, in the future, to see what source files made up an exact release. Very useful if a bug fixed previously has crept back in over time (unit tests help here). This is the last part of the puzzle. Basically you tag (or copy as it is Subversion) a set of files to the tags branch. The tags are usually numbered, named or a combination of the two. For instance. A minor bug fixing release after version 1.0.0 could be 1.0.1, whereas an added feature could make it 1.1.0. Also if you get paid to add a special feature by the XAB Corp. you could name a version 1.1.0 (XAB) to differentiate it from the 1.1.0 (HAL) you did for the HAL Corp.
And that concludes a simple overview of how source control works.
I’m just trying a walk through for eclipse which is a little over a year old. I am running Ganymede, the tutorial is for Europa.
The gentleman who wrote this has screenshots for nearly every step of the way. Nearly 95% of the images are now out of date. The steps he takes are no longer available – you can only click finish where he clicks next, etc.
Now I thank the gentleman for his time, but I am really frustrated by the lack of support. There is nowhere to turn to help and the actual documentation is out of date (where is the mythical Modify button in Java Facets?). The continuous change is probably good if you are in the middle of it and regularly update – it would be more of an evolutionary change as new screens are added or taken away, but when you try and step into the thick of it…it is a painful experiences.
Also seems that update for the JEE is broken – everytime I auto-update eclipse refuses to start.
So I am forced, reluctantely to delete the current install of Eclipse and go back to the Europa release, just to follow along with the tutorials. However, there are still differences – notably in the JPA section of the tutorials…
Okay first it is a 65.5mb download and requires 200mb of space. For a piece of software that plays music and video. Even this day and age of bloat, that is a tad excessive.
I have a large music collection on a different machine – it is a slow connection (see previous post) and I told iTunes where it was – now my machine is unusable while it indexed the 2000 tracks in that folder – and I have another two folders to go. You can’t minimize iTunes while this is going on due to the modal dialog, you can’t inform it of other locations that you want indexing. But it doesn’t stop there, once the modal dialog box finally buggers off and you tell it of the next folder you want indexing it has started on a “gapless playback” and now your machine really crawls as it tries to do two things at once. My fault for having a slow network? Maybe that is part of it, but I can set the folders up in Winamp and have it index at the same time and Winamp is a fraction of the size and I would hazard that Apple can afford to hire better programmers.
When you first index your music iTunes claims it is getting album art automatically. Cool – that’s neat. However I have this other folder to index, you can get the art later. So you index the album, let the gapless playback work out its stuff and then select all and then tell it to ‘Get Album art’. No can do – you need to be signed in. What? You didn’t need that a few minutes ago why now?
Now comes the really insiduous part of it. Okay lets’ create an account, and this is what I really don’t agree with. Why does Apple need to know my house address, what I do for a living, and my telephone number? And I am never going to buy stuff at the Apple Store so I don’t want to give you my credit card details but I can’t sign in without handing over my details. So I did a google search for a way and now I definitely don’t want to hand over my credit card details.
Fortunately I found a tutorial on YouTube that details how to get an account without handing over those details.
Update: I’ve now got my account by the above method. Something I didn’t mention was that I indexed my collection with a wired connection, but the wired couldn’t stay as it was laying directly across the living room, so I am back to my slow-ass wireless. Whether this is what is affecting the album art updating and causes it to crash out about the 1200th cover (which happens to be where my compilation albums exist). Perhaps crash was a bad word, how about hang, or just stop. Whatever. The point is it hasn’t finished the albums and there doesn’t seem to be a way of kickstarting it.
Not only that the only way of getting it restarted is to shut down iTunes. This brings up a dialog box telling you that you are get the album art and whether you are sure you want to stop this. Naturally you click yes and as iTunes shuts down a dialog flashes up for the briefest of seconds – looks like one of those ‘Do not show this dialog again’ boxes. But does it get all my albums? No. And the albums it get are pretty varied. Missed The Chemical Brothers, but did get Blutengel.
Final thing: The iPod has an update available a 57.8mb download. What?! It’s a software update!
The posts are slowing, due to Christmas arriving (and ’tis the season of parties) and me now working with the Zero Sum Games guys (and gals), the new owners of Space – Glory Through Conquest - the game I was working against with my homage, Galaxy. Galaxy is not off the cards, but it’s definately been put on a back burner now.
You gotta love user written instructions – especially when they are down right wrong and you know it and the person writing it has to know it (since he has enough intelligence to actually create a blog and use it) but it is still put out there for the universe to see. This is even more bizarre when the instructions that come with the software is pretty explicit and correct. Hell I am also guilty of it.
Case in point: Getting Apache2 and PHP4 working together. I generally ignore the given instructions – my experience up until this point is that they are pretty terse and work on their systems and their systems alone. The best way is to ask google and see what the masses think. Well the masses think that this is a good set of instructions. Well they are right, up until the part where they install PHP and then it goes horribly wrong.
Why would you want to copy everything into a directory of another item and then start to copy various files all over the place – makes upgrading a painful experience: I know this as in a previous life a colleague wrote some software using a 3rd party source library – an expensive one at that. I came to work on it and was wondering why we were still using the several year old version despite the fact that everyone got the update messages forwarded to them from the library authors. What about the 30% speed increases that one of the mails raved about, what about the vulnerability that was fixed? Well they went out of the window when the muppet who wrote it took the decision not to bother with fixing the problem with his configuration and make the code fit the configuration. After that it was all down hill from there.
Anyway I eventually decided that the internet is full of muppets and read the actually instructions shipped with PHP. My god – they have instructions for getting it working on webservers I have never heard of and it is all very clear and well written, if a little terse.
So I now have a working installation of Apache2.0 and PHP4.4!
People bleat on and on about how much better Linux is than Windows. Here’s some news: I’m fairly bright, and I like challenges, but even I am getting frustrated at Linux. I’m using RedHat 9, which might make some of you mutter “Why isn’t he using Ubuntu?”. Well I’ve joined a group of like minded individuals, and we’ve inherited a server and it happens to be RedHat 9. So it stays.
So I get VirtualBox, download the 3 CD’s that RedHat is provided on and start installing. The installation was painless. However getting the needed stuff installed is where things collapsed. Every website and forum that goes into installing redhat files has a slightly different way of doing things. But they don’t tell you where to get the files from: “Type the following to extract the apr-1.2.5-41b+8.tar.gz”. That’s fine, but please tell me where to get that file first. Also installing from source isn’t the greatest it’s cracked up to be. Various software components organically evolve – functions come, go and get renamed or deprecated and dropped. So trying to compile several things from releases that you try and glean from the net isn’t the productive, especially when you have to wait 10 minutes to find they aren’t compatible. So there goes rpmfind.net.
And that brings me to my next point: The point of the tools is to make me more productive, not the tools themselves. Spending an afternoon trying to install software (Subversion of all things) isn’t productive. Windows takes about 30 seconds: Download the msi, double click the msi, accept the default config, done. I can now start using Subversion. Can I use it on RedHat? No. Because I still haven’t got it installed.
So why don’t I use the install I have on my Windows box? Because I am trying to get the steps figured out so we can use it on the server without me borking the entire server.
This is the reason why Linux will never break the strangle hold of Windows. You may say that if I used Ubuntu then I wouldn’t have this problem, but RedHat was released in 2003. I can still double click MSI installers created in 2003 and be confident that they will work as advertised.
Just checked my stats and while the traffic has been constant for the past few weeks, a couple of days ago there was a massive (2x) spike in traffic which disappeared just as quickly. There wasn’t an increase in spam which usually coincides with this type of event – in fact with 1 spam that day it is one of the lowest I’ve ever had. Drilling down via the wordpress stats plugin it appears that most were legitimate hits too.
NOTE: I found this in my drafts folder, from a long, long time ago, it’s a little dated but I will let it stand as some of the points are still valid.
At work I’ve inherited several legacy projects, one large with several smaller ones that support it. Making changes is pretty dangerous – I’ve been bitten a few times by a seemingly innocuous change that has only come to light during testing. The way I use the application as the developer and the way a service engineer uses the same application is different.
So I started writing unit-tests (UnitTest++ retrofitted to work with VC6) to test my assumptions and make sure that my changes don’t break things. A major problem is testing private functions. Some can be fixed by promoting private to protected, inheriting the class and then adding testing hooks in the class. Like:
// Example.h
class Example
{
bool ThisNeedsTesting();
};
// in TestExample.cpp
#include "Example.h"
class TestExample : public Example
{
public:
bool TestThisNeedsTesting() { return ThisNeedsTesting(); }
};
TEST( TestThisNeedsTesting )
{
TestExample tester;
CHECK( tester.TestThisNeedsTesting, true );
}
Others get refactored out the classes they reside in and get put into their own functor classes – the current project has validation that is needed in several subclasses. These were first on my list to be refactored – they became functors and as a bonus made it easier to test – just a call to their public () operator. Others were functions that performed several duties. These too were split into separate functions and then split into functors as they weren’t directly related to the class they were in – they just played a supporting role.
Then I started on the larger objects. These became strategies. These strategies each implemented states via enums. These are massive classes and are a testing and maintenance nightmare – and one of these is what needed changing. According to Gamma, et al, states have a main state with empty functions. Specific states are derived from these states like so:
// I've left out the public declarations to save space
class State
{
virtual void StateOne() { };
virtual void StateTwo() { };
};
class StateBored : public State
{
virtual void StateOne() { /* do stuff */ }
};
class StateHappy : public State
{
virtual void StateTwo() { /* do happy stuff */ }
};
This really aids maintenance, extending and unit-testing as well, but it is screaming out to be functors with just the () operator being overridden in each. Like this:
// I've left out the public declarations to save space
class State
{
virtual void operator() () { };
};
class StateBored : public State
{
virtual void operator() () { /* do boring stuff */ }
};
class StateHappy : public State
{
virtual void operator() () { /* do happy stuff */ }
};
I am also sure that I will be finding more functors as I continue. Which really reduces most coding to functions – like traditional C programming. Does anyone else find them reducing nearly everything to functors?
Last time we spoke I left you with two repositories and waiting to put data into them.
So let’s get on with that, then.
In a temporary directory create your ferrari and bugatti folders here, and in them create the standard Trunk, Tags, and Branches (TTB).
Now switch into the two directories and run svn import on each:
D:\temp\bugatti>svn import .\ svn://localhost/bugatti -m "Commiting the initial TTB layout to repository"
Authentication realm: <svn://localhost:3690> 4f93af25-16dc-3d41-b82e-acee2e868d11
Username: graham.reeds
Password for 'graham.reeds': ********
Adding trunk
Adding branches
Adding tags
Committed revision 1.
You can delete these temporary folders since they are no longer required.
Let’s start doing something useful with them.
In your directory where you normally do your programming, create a directory to hold the projects we are going to write. Due to a lack of imagination on my part, I use a directory called projects, also on drive D, to hold my projects.
So switch there and let’s get to work creating the directories.
The first will be project ferrari, so create a project folder named ‘ferrari’. In that directory issue the check-out command:
D:\projects\ferrari>svn co svn://localhost/ferrari/trunk ./
Checked out revision 1.
If you look at the folder you will see that a hidden folder called .svn has appeared. Open up Visual Studio (or similar if you use another IDE) and create a Win32 project called ferrari. For this I will accept all the defaults so the 20 or so files will demonstrate my purpose perfectly – I also prefer to configure my directory structure to something more convenient but that can be another blog topic.
So we now run ‘svn add’ and are greeted by the following sight:
D:\projects\ferrari>svn add ./*.*
svn: Skipping argument: '.svn' ends in a reserved name
A ferrari
A ferrari\ChildFrm.cpp
A ferrari\ChildFrm.h
A ferrari\ferrari.cpp
A ferrari\ferrari.h
A ferrari\ferrari.rc
A ferrari\ferrari.vcproj
A ferrari\ferrari.vcproj.DIGITAL-UTOPIA.graham.reeds.user
A ferrari\FerrariDoc.cpp
A ferrari\FerrariDoc.h
A ferrari\FerrariView.cpp
A ferrari\FerrariView.h
A ferrari\MainFrm.cpp
A ferrari\MainFrm.h
A ferrari\ReadMe.txt
A ferrari\res
A (bin) ferrari\res\ferrari.ico
A ferrari\res\ferrari.rc2
A (bin) ferrari\res\ferrariDoc.ico
A (bin) ferrari\res\Toolbar.bmp
A ferrari\Resource.h
A ferrari\stdafx.cpp
A ferrari\stdafx.h
A (bin) ferrari.ncb
A ferrari.sln
A (bin) ferrari.suo
The add command means they are now being watched by subversion (as exposed by the hidden .svn folder in the ferrari subdirectory). However they are not in the repository just yet. We need to commit them. This is fairly simple.
D:\projects\ferrari>svn ci ./ -m "Initial commit of the default project files"
Adding ferrari
Adding ferrari\ChildFrm.cpp
Adding ferrari\ChildFrm.h
Adding ferrari\FerrariDoc.cpp
Adding ferrari\FerrariDoc.h
Adding ferrari\FerrariView.cpp
Adding ferrari\FerrariView.h
Adding ferrari\MainFrm.cpp
Adding ferrari\MainFrm.h
Adding ferrari\ReadMe.txt
Adding ferrari\Resource.h
Adding ferrari\ferrari.cpp
Adding ferrari\ferrari.h
Adding ferrari\ferrari.rc
Adding ferrari\ferrari.vcproj
Adding ferrari\ferrari.vcproj.DIGITAL-UTOPIA.graham.reeds.user
Adding ferrari\res
Adding (bin) ferrari\res\Toolbar.bmp
Adding (bin) ferrari\res\ferrari.ico
Adding ferrari\res\ferrari.rc2
Adding (bin) ferrari\res\ferrariDoc.ico
Adding ferrari\stdafx.cpp
Adding ferrari\stdafx.h
Adding (bin) ferrari.ncb
Adding ferrari.sln
Adding (bin) ferrari.suo
Transmitting file data ........................
Committed revision 2.
This can be confirmed by the ls command:
D:\projects\ferrari>svn ls svn://localhost/ferrari/trunk -R
ferrari/
ferrari/ChildFrm.cpp
ferrari/ChildFrm.h
ferrari/FerrariDoc.cpp
ferrari/FerrariDoc.h
ferrari/FerrariView.cpp
ferrari/FerrariView.h
ferrari/MainFrm.cpp
ferrari/MainFrm.h
ferrari/ReadMe.txt
ferrari/Resource.h
ferrari/ferrari.cpp
ferrari/ferrari.h
ferrari/ferrari.rc
ferrari/ferrari.vcproj
ferrari/ferrari.vcproj.DIGITAL-UTOPIA.graham.reeds.user
ferrari/res/
ferrari/res/Toolbar.bmp
ferrari/res/ferrari.ico
ferrari/res/ferrari.rc2
ferrari/res/ferrariDoc.ico
ferrari/stdafx.cpp
ferrari/stdafx.h
ferrari.ncb
ferrari.sln
ferrari.suo
We can now proceed with the project right? Well you could but you would be missing probably the most important thing about source control. Imagine you were working on an important project, you have pushed the latest release out the door and now are working on some very exciting new technologies extending it when your manager walks over and tells you that the important client has a problem in the FooBar when accessed by the Baz. He also informs you he has sent you an example set of data that demonstrates this flaw attached to an email and expects that the fix will be prompt and rigorously tested. Sure enough, once stepped through in a debugger you can see it and the fix is fairly trivial and has zero impact you can discern, but you are partway through an enhancement – there are partially written dialogs and functionality is greatly missing and won’t be ready for weeks. What can you do?
Well that’s where branching comes in handy. A rule of mine is that trunk should always be in a compilable state – no exceptions. So if that is the rule, how can we implement it? Well with branching. A branch is a fork of the code. With that code you can make as many adjustments as you like, and if the above situation occurs you can simply make another branch, work on that and then when the adjustments/modifications/fixes are made you can merge them back in with the main trunk. With due care branching can improve efficiency amongst a team, but it’s not with out drawbacks. That will be the topic of my next blog entry.
That’s about it – remember you can do the same stuff for the bugatti project also.
Let’s face it – if you are looking at this right now the chances are you already know what Subversion is, so I will skip the tedious ‘yadda, yadda, free, yadda, yadda, great, yadda, yadda’.
So let’s take a look at setting one up – there are a lot of these, some good and some bad. Most go into details of setting up Apache and allowing you access from a small orbital platform stationed above Mars, but the chances you need remote access like that is minimal. If you do then I suggest you go read those – by the way they are only written by guys with beards.
The first thing we’ll do is download the latest Subversion Windows binary installer which is currently 1.5. In the future it will be different, but the concepts will probably remain the same.
Double click the installer and allow it to install naturally. Once that is complete we could run svnserve and be done, but it can be so much more beautiful. Let’s run it as a service.
Now Subversion has one slight annoyance. It has a global revision number. So if you have a single repository with multiple projects all projects will use the same incrementing revision system. That’s not particularly nice – especially when a single line change of code will result in a several hundred (or thousand) revision leap because of activity on another project.
So I prefer multiple repositories. It’s pretty easy to do. Let’s say you name your projects after famous marques. So let’s create a couple of projects:
svnadmin create "d:\svn\ferrari"
svnadmin create "d:\svn\bugatti"
I use D as my development drive and have short monikers for all my folders – \dev, \svn, \db, etc.
Notice svnadmin created a few directories under both ferrari and bugatti. You need to go into each of these and edit the conf/svnserve.conf and the passwd files.
Uncomment the following lines in the conf/svnserve.conf file by removing the pound character from the start of each line:
anon-access = none
auth-access = write
password-db = passwd
Since the chances of working with a harry and sally are next to nil, delete their lines from passwd and replace it with your own:
graham.reeds = password
You will need to do this for each as outside the aforementioned Apache there is no real way of doing that.
Now that is complete let’s perform the final step of installing Subversion as a Windows service so that it is always available. Under OS’s other than XP you will need to find sc.exe otherwise Just issue the following command:
sc create svnserver binpath= "c:\program files\subversion\bin\svnserve.exe --service -r d:\svn" displayname= "Subversion" depend= Tcpip start= auto
sc description svnserver "Subversion server service (svnserver)"
It’s set to auto-start so it will start up automatically when your machine restarts but currently it’s not running. We can fix that while still at the command line by typing:
net start svnserver
Now the final thing to do is set it up so that when we do a commit we have an editor to write the comments in. Since svn doesn’t provide one then we will need to provide our own. So lets edit your environment settings and add SVN_EDITOR with the value of %systemroot%\system32\notepad.exe.
You could use Notepad++ but simple notepad is way easier and Notepad++ is too heavyweight for this job. In this one case the traditional notepad is the better option.
Next time I will show you how to populate those repositories.
« Previous Page — Older »
« Newer — Next Page »