Yeah I had everything set up and then I realised it wasn't workable. I dunno I think I might be going through a phase of coders block at the moment, completely unable to think clearly. Maybe it's something I'm eating, or not eating. Perhaps I'm not taking enough exercise.
Here's what I had
Code: Select all
/ # root; obviously
/web # one big single repo checkout here
/repo # the repo itself, yes, it's inside a checkout of itself, there's svn:ignore set for it
/sites
/foo
/code
/foo # site specific code
/libA # svn:external included library /lib/libA
/libB # svn:external included library from /lib/libB
/www # document root for this site (vhost)
/log # server specific and svn:ignored
/bar
... much like foo ...
/lib # libraries
/libA
/trunk
.. library code
/branches
/libB
... much like libA ...
I was having to deal with "trunk" sub-folders in order to get access to libraries. But I knew I may not always be using the trunk. Also the constraint of an svn:external having to go in it's own folder was causing me problems.
Everything I've written was really heavily coupled to a very specific file system layout and it had all changed. I used to include all my stuff like this:
Code: Select all
set_include_path('../code'); // outside the doc root and into the code folder
require_once 'MyFramework/Controller/Front.php';
require_once 'simpletest/mock_objects.php';
require_once 'utf8/utf8.php';
require_once 'ThisWebsite/Controller/Action/Index.php';
In order to make my code run I was faced with:
Code: Select all
set_include_path('../code'); // outside the doc root and into the code folder
require_once 'MyFramework/trunk/MyFramework/Controller/Front.php'; // might change
require_once 'simpletest/trunk/mock_object.php'; // might change but probably won't
require_once 'utf8/trunk/utf8.php'; // might change but probably won't
require_once 'ThisWebsite/Controller/Action/Index.php'; // I can't do branching here x(
Also I have a dependency injection system that depends on being able to resolve Underscore_Separated_Class_Names to their/path/counterparts and so the whole thing was completed screwed up.
I've now discovered, this is not the kind of thing you want to solve with trial and error. For me not knowing where my files are is enough to keep me awake at night, this stuff really stressed me out. I've got bits in version control, bits out of version control, stuff on one server, stuff on another, stuff on my desktop machine. For a couple of days I was completely unable to actually run anything.
Here's my proposed solution that I have begun to implement:
Code: Select all
/
/repos # many repos not one
/libs
/libA # a library repo
/libB # another library repo
/sites
/foo # a site repo
/bar # another site repo
/all # a special repo with all the other site repos svn:externaled in
/web
/libs
/libA # checkout of /repos/libs/libA
/trunk
.. library here ..
/branches
/libB
.. much like libA ..
/sites
/foo
/code
/foo
/libA # svn:external included library /repos/libA/trunk (note: trunk!)
/libB # svn:external included library from /lib/libB/trunk
/www # document root for this site (vhost)
/log # server specific and svn:ignored
In that last listing I've shown what is beneath /web but that I now more free to change because it's several checkouts of several different repos. Yes, you can checkout the a single repo at several different points in different places but there's a conceptual difference. For instance there is a greater incentive to ensure that library unit tests can be executed without having to be part of a site. I've also got the flexibility to change access control on a per repo basis and the revision number stays smaller.
In addition I'm beefing up the flexibility of inclusion in all my code with constants. I always thought these were silly because you can use set_include_path() to load anything from anywhere anyway but it turns out they give a lot greater certainly about what is going on and you can reference them in your code later instead of having to explode(PATH_SEPARATOR, get_include_path()) and work out which is which.
So now I can require like this:
Code: Select all
define('LIB_PATH_FRAMEWORK', '../code/MyFramework/');
define('LIB_PATH_SIMPLETEST', '../code/simpletest/');
define('LIB_PATH_PHPUTF8', ../code/'utf8/');
define('SITE_PATH', '../code/ThisWebsite/');
require_once LIB_PATH_FRAMEWORK . 'MyFramework/Controller/Front.php';
require_once LIB_PATH_SIMPLETEST . 'mock_object.php'
require_once LIB_PATH_PHPUTF8 . 'utf8.php'; // might change but probably won't
require_once SITE_PATH . 'Controller/Action/Index.php';
Now, comments:
AC wrote:If the same site requires different versions of the same library, you've got serious problems.
Uh yeah, that would be a problem. I don't have that though.
If its different sites, you'll need to decentralize the library includes and then attempt to get them all up to date.
I'm actually assuming svn:external is going to be good enough. One of the things that worried me is if I go to /sites and type "svn update" will it update all of the externals too? Some of those sites will depend on older revisions so executing "svn update" will break them. I think I'm slightly unique on this front because I don't want my framework to be constrained by backwards compatibility where most people seem to accept that as a necessary part of developing a framework, even a personal one.
svn update --revision for a bandaid fix, svn cat > file to retrieve older versions of the files and then svn commit to revert at the repository.
Thanks for that tip involving cat. I had been doing it a much more awkward way.
Post-commit hooks! Or, if you're not as wild, tar / PEAR / rsync and NFS all can work.
Well I was thinking of using subversion itself. There's the idea behind my "all" repo. I can check that out on as many production servers as I like and just svn update when I need to update them.