Dessert #4 - Keep your Cake fresh (use SVN HEAD)
Posted on 15/9/06 by Felix Geisendörfer
This is something you might already have found your own solutions for, but never the less I think it's a topic people will struggle with when first using CakePHP together with SVN to version their project. However, you should already have an alright understanding for SVN itself to follow this post. If not, checkout this free svn book for information.
Ok, back to the topic. The problem is the following: You use CakePHP (or any foreign vendor, but let's keep it simple for now) to create your project and want to regulary update your version to enjoy the benifits of the frequent changes in the SVN trunk (like bug fixes, new features, etc.).
There are basically 3 options you can accomblish this:
#1 Overwriting your Project Frequently
This method might be the first one you consider, but believe me it's the worst of all. The idea is basically to frequently either export the latest SVN HEAD version from the CakePHP repository, or to visit CakePHP.org and grab the latest nightly build. Aferwards you take the new version of /cake, /index.php, /.htaccess, /VERSION.txt and use them to overwrite them with the existing ones in your working copy. Afterwards you do a commit and voilá you just updated your CakePHP version.
Pro's:
- Easy to understand
- If a CakePHP update breaks the application you can easily roll back
Cons's:
- Manual update required
- Get's hairy when you modified CakePHP core files in your working copy or when updating /app
#2 Use svn:externals
The next idea you might try is to use the svn:externals property to directly link /cake (and eventually the other 3 files in /) to the latest SVN Version. If you use TortoiseSVN (highly recommended for Windows users) this is simply a matter of right clicking the root folder of the working copy of your application's trunks and selecting properties. Then you select the Subversion tab, choose the svn:externals from the drop down on the bottom and enter "cake https://svn.cakephp.org/repo/branches/1.2.x.x/cake" in the text field below (assuming you are using CakePHP 1.2). Make sure you have deleted /cake in your working copy, then run svn update and SVN will automatically fetch the latest SVN version of the /cake folder and put it in your working copy. Whenever you run svn update from now on, you will also get the latest changes from the trunk. I think you could also link to the 3 other files in / with this method, but I haven't tried that so far.
Pro's:
- Easy to setup
- CakePHP Updates flow in almost automatically
- Allows modification of CakePHP core files
Cons's:
- Modifications to CakePHP core files will not be versioned (and therefor not be available to other people using the same repository)
- If a CakePHP update breaks your application rolling those changes back get's a bit hairy
- /app can (should) not be updated this way
#3 Use a vendor branch
Using a vendor branch is probably the most advanced of all approaches, but also the most complicated compared to the other ones. The idea is basically to create a branch for every vendor your project depends on (in our case CakePHP) and to regulary update this branch with the latest version of the vendor library. After updating the vendor branch you simply merge the changes between the previous vendor branch update and the current one into your trunk and only those changes will be applied to your application. To understand this proccess a little better I would recommend you to read this page about vendor branches I already mentioned.
Pro's:
- CakePHP core files can be modifed and versioned
- If a vendor update breaks the application you can easily roll back
- You can easily recieve updates to /app
Cons's:
- Difficult to set up
- Manual update of the vendor branch required (but you could automate this)
Conclusion
There is not perfect way to handle this. When working on an application with a group of developers, using a vendor branch gives you most control about the entire proccess. Personally, when working on a project all by myself I often use method #2 since it's quite simple to setup and easy to maintain. The important thing is that you know about the existing options and their advantages / disadvantages so you can choose which one suits your project best. However, method #1 should be avoided if possible ; ).
Another hint: Right now most changes to CakePHP go into the 1.2.x branch and therefor the stuff above doesn't make a lot of sense if you are working with 1.1.x right now. Currently I'm working on the new ThinkingPHP.org and another project using the 1.2.x branch and it seems pretty stable, however it's not the officially recommended version right now, so I recommend you to only do this if you are pretty familiar with CakePHP and know what you are doing.
Oh and before I forget: You should almost never have to modify anything inside /cake. Often people who do that and post their own fixes on Trac are wrong, and their problems can be solved in /app. However, never say never, being able to modify core files is still a nice option to have, *especially* when using those technics above for including other vendors that don't write as perfect code as the CakePHP developers do ; ).
--Felix Geisendörfer aka the_undefined
You can skip to the end and add a comment.
Hi seb, thanks for being interested in those methods. For method #2: I wasn't sure if you could do it on the individual files, so if svn doesn't allow that you have to manually update them. However, those files should ever rarely change. I only use this method for the /cake folder.
For method #3, there is quite a bit about this topic written already. All I know about it I've got from here: http://svnbook.red-bean.com/en/1.2/svn.advanced.vendorbr.html so reading this should be good enough for getting you started.
I guess you can have vendors folder in your svn tree and make other project link to it with the svn:external. It is some way better then your #2/#3 method, because that method dramatically speeds up updating your projects (you update cake base files for all of them only once).
Hi Guys,
Perhaps I'm missing something but here's what I do. Please let me know if you can spot why this doesn't work.
I only keep my 'app' directory (and all subdirectories of course) under version control on my end. The CakePHP framework is kept under version control on the cakePHP servers so I don't need to do it myself. I just check out the framework itself and check out my app to the root cake directory. When I do check it out, I call it something other than 'app' so the default 'app' directory that comes with the framework is left untouched.
Therefore, if I want to update/commit/revert my app I run that command from inside my 'app' directory, and if I want to update/commit/revert the cakePHP framework I go up one directory and do it from there. If I have my 'app' directory named something other than 'app' then SVN will just see it as an unversioned directory and it will not be affected by any SVN commands meant for the framework files.
How does that sound?
Sonic
Sonic: Sounds workable for one person. However, if you work on a team, you would want to have on SVN repository people are checking out an in from, that contains all important files, including the CakePHP framework. And there are some other issues with your setup, like the fact that you cannot version changes that you make to your vendor (CakePHP). I know you shouldn't have to, and I rarly ever do, but having the option, especially when working with other vendors as well, is great.
So depending on what you are working on you can keep this setup, but for everything more involved I could see it become a pain pretty quickly.
I couldn't get the svn:externals part to work... I'm probably doing something horribly wrong though.
What I have is VMware running a virtual machine, containing an installation of Ubuntu Server. Subversion is installed, so is the standard LAMP stack. I can successfully work with my files, and the cool part is, I have a post-commit hook set up in SVN so that when I commit new versions from my Windows system (whether using Komodo or TortoiseSVN), the working copy I have sitting in my /var/www directory is updated also.
However this doesn't happen with the externals, for some reason, and I can't get them to actually be inserted into my repository at all (the files just don't appear at the other end). Am I doing something stupid? In the interim I've gone with method #1.
Thanks for the info. I'd like to use vendor branches to sync my app with the nightly builds of 1.2, so what is the 'x' in "svn import x /my/app/dir"? (I tried https://svn.cakephp.org/repo/trunk/cake/1.2.x.x, but svn said it doesn't exist).
Greg: Not sure, maybe you need to put the dir in parentheses. Otherwise check svn --help for information. Personally I use TortoiseSVN on windows, and I'm sure there are similar tools for other OS' as well.
Felix,
Thanks for responding. I found that when running an svn checkout on that path, it works fine. I think I am using svn incorrectly as far as the import operation is concerned. According to the manual pages, the svn import looks like "svn import [PATH] URL". So, it appears that I cannot import from a url (as in https://svn.cakephp.org/repo/trunk/cake/1.2.x.x). Also, the example on http://svnbook.red-bean.com/en/1.1/ch07s05.html shows the import as
$ svn import /path/to/libcomplex-1.0 \
http://svn.example.com/repos/vendor/libcomplex/current \
-m 'importing initial 1.0 vendor drop'
which shows exactly that. Where did they get the "/path/to/libcomplex-1.0" initially?
In regards to the cake-1.2 nightly builds, how do I initially get a hold of that path from which to import into my vendors directory? I tried running a svn checkout on the nightly into a temp folder, then imported that temp folder into my vendors directory. But the import removed all versioning (skipped .svn folders), therefore defeating the purpose of using vendor branches, right?
If you could point me in the right direction, I would really appreciate it.
Thanks for your help,
Greg
[...] So here I go with my very first screencast to be published. The topic is how to use vendor branching with CakePHP which is one of many ways to keep your CakePHP version up to date. [...]
Greetings from Québec Felix,
First, many thanks for your screecast. The merge part was a bit foggy for me.
I have use a vendor branche for cake for some months now. One tiny pain I have with this way of doing things is when the core devs delete a file. The way I handle this (painfully) is to check each and every directory in winmerge and tortoisesvn->delete those files.
How would you go about that? Exporting from cake means you don't know about those deleted files.
It may not be very important but what if your app is using one of those deleted files? Since you didn't deleted them in trunk, there're still available to your project... This could be the source of a very *bad* surprise!
Thanks again for this post and screecast,
Louis
Louis: There is a perl script that can help out with this:
(Comment by Travis on the other blog post)
svn devs provide a perl helper called svn_load_dirs : http://subversion.tigris.org/tools_contrib.html#svn_load_dirs_pl
Usage is explained in the book here: http://svnbook.red-bean.com/en/1.0/ch07s04.html
Howto start your CakePHP project in Subversion...
This howto will demonstrate how to start your cakephp project from scratch, taking advantage of subversions “externals definition”. The result will be a basic CakePHP directory structure with only the “/app” part under your svn ...
This post is too old. We do not allow comments here anymore in order to fight spam. If you have real feedback or questions for the post, please contact us.
Thanks for these tips.
When I tried #2 option, I cannot do it for the 3 files (.htaccess, index.php, VERSION.txt).
Checking subversion manual to see that svn:externals works only for folder, not for files atm.
How do you updates theses files? manually?
Can you explain more the #3 please?
for instance:
- folders tree before vendor branch
- after first vendor import
- and after first vendor update
I tried to do it with Cake 1.1.7 as initial and update to 1.2.x SVN branch.