Learn / eZ Publish / Using Subversion with eZ Publish

Using Subversion with eZ Publish

What is Subversion?

Subversion is a source code versioning tool. This means that every time you change the code or the design on your eZ Publish site, Subversion stores the change as a "version". This enables you to revert changes to your site to previous versions, and also allows you to monitor and audit changes to your site through the log files that Subversion maintains for each file.

(Subversion is also known by the abbreviation "SVN"; both terms are used interchangeably in this article.)

This article is not an in-depth discussion of the Subversion tool. For more information about Subversion, refer to the Subversion documentation at http://svnbook.red-bean.com/en/1.4/index.html.

Why should I use Subversion?

Remember the first line in the developer's ten commandments:

  1. Use a versioning system

The biggest benefit of using a versioning system is that you can recover from mistakes by reverting to previous code versions. Versioning systems also help with bug hunting and troubleshooting, because you can compare different code versions to discover where the bugs crept in. With a versioning system, everyone's code is stored on a shared server, making back-up simple and preventing losses caused by individual computer failures.

Versioning systems are also very useful for project management. Each time you submit a change to the versioning system, a unique number is assigned to the change. These numbers can be cross-referenced with specific bugs or with project milestones.

When I suggest to people that they use SVN, I often get these responses:

"We do not know Subversion"

If you do not know Subversion, learn how to use it. It is not difficult. In fact, most of your work is done with three simple commands:

If you are learning SVN basics the best thing you can do is to create an SVN repository to use as a sandbox. If you break something, "live" projects will not be affected.

Usually, the SVN repository is stored on a shared computer that is accessible to everyone who works on your eZ Publish projects. Individual developers use local programs ("clients") to access the source code stored on the SVN server.

The Tortoise SVN client is popular among Windows users [ http://tortoisesvn.tigris.org/]. On Mac OS the SvnX client is popular. [ http://www.lachoseinteractive.net/en/community/subversion/svnx/features/] If you are running Linux then you are probably comfortable with the command-line client. (Command-line clients are also available for Windows and Mac.)

In this article, our instructions assume you are using the command-line interface. For example, to commit changes to the repository, we instruct you to use the command "svn commit". Graphical SVN clients (like Tortoise and SvnX) have an equivalent GUI for these commands.

"A Subversion repository takes up too much space on the hard drive"

This is not an excuse. Hard drives are inexpensive. Buy a big hard drive and start using it for all your projects. Losing your work even once due to the lack of good tools will probably cost more than a hard drive.

Creating the SVN repository

To work with SVN, you must first create an SVN repository. This can be done using the "svnadmin" command.

On the server which will host the SVN repository, type this command:

svnadmin create --fs-type fsfs /path/to/the/repository

Note that you can add extra parameters to the svnadmin command. Please refer to the SVN documentation to learn more.

Creating the basic directory structure

After creating the repository, you next create a basic directory structure. If your project is called 'my project' you will have something like this:

myproject
   |-- branches
   |-- tags
   `-- trunk

Putting your eZ Publish instance in SVN

Download the latest eZ Publish version, extract it in the 'trunk' directory and install it on your computer. You will have a result like this:

myproject
   |-- branches
   |-- tags
    `-- trunk</span>
    `-- ezpublish-4.0.0
    |-- ....

This means that the eZ Publish instance is stored under the 'trunk' directory with all the default configuration for the design and connecting to the database.

Note that there are other ways to store an eZ Publish instance. Some people prefer putting all the eZ Publish code right under the 'trunk' directory. I would not recommend doing this if you plan to work with third-party systems combined with eZ Publish, such as bulletin boards, blog engines, etc.

Once you have this basic directory structure, it is time to import it into SVN. This can be with this command:

svn import -m 'initial import of the eZ Publish instance' path/to/myproject http://url/of/the/repository

This will take a few seconds, depending on your bandwith.

Once the import is finished you can check everything is OK by using the "svn list" command:

svn list http:://url/of/my/svnrepository

You should see the files you just imported.

If everything is OK then you can start working with the source code in the repository. Use the "svn checkout" command to make a local copy of the repository on your system. You now work on (and, if you like, build) your own copy of the code. When your changes are complete, use the "svn commit" command to copy your local changes back to the SVN repository.

(Delete the former local copy which you used to create the SVN repository. You shouldn't use it anymore.)

Note: If you do not want to store certain files (such as kernel, libs, translation, etc) in the repository you can use the "svn:external" property [ http://svnbook.red-bean.com/en/1.0/ch07s03.html].

How do I prevent different versions of eZ Publish cache files and log files from being stored in SVN?

Tell SVN to ignore the directories that contain the files.
You can use the "svn propset" command:

http://svnbook.red-bean.com/en/1.4/svn.ref.svn.c.propset.html

http://svnbook.red-bean.com/en/1.4/svn.advanced.props.special.ignore.html

svn propset svn:ignore "*" var/cache
svn propset svn:ignore "*" var/log

Make sure to delete all the files from the cache and log directories and make sure that the directories are no longer versioned. Do not forget to commit the change using the command "svn commit".

How can I prevent changes to the files in the kernel/ and lib/ directories?

You can either use "svn lock" or a more advanced permission system. Choose the solution that best suits your needs.

http://svnbook.red-bean.com/en/1.4/svn.ref.svn.c.lock.html

http://svnbook.red-bean.com/en/1.2/svn.serverconfig.httpd.html#svn.serverconfig.httpd.authz.perdir

Using locking is faster than using the permission system. However, the locking functionality in SVN is not as flexible as the permission system. Even though it is a littile bit more work to set up, I recommend using permissions, as that system is more powerful and flexible.

Can I use Subversion as a deployment system?

Yes!

A project can be broken down into 3 stages:

  • development
  • testing
  • production

This means you have at least three different hosts that store eachpart of the project. The idea is to reproduce these parts in SVN branches:

myproject
   |-- branches
   |  |-- testing
   |  `-- production
   |-- tags
   `-- trunk
   `-- ezpublish-4.0.0

Development is done within the 'trunk' directory. Testing is done within the 'branches/testing' directory. Production is done within the 'branches/production' directory.

What if I have to push some new code from 'trunk' to 'testing' and from 'testing' to 'production'?

Subversion gives you a powerful tool for merging changes between branches: "svn merge" [ http://svnbook.red-bean.com/en/1.4/svn.ref.svn.c.merge.html] Let us consider a complete example:

I have developped a new piece of code located in the extension directory. Since the project is in the development phase, this piece of code is only stored in the 'trunk' directory.

Therefore I have something like this:

extension/myextension

   `-- classes

       `-- myfile.php

What if I want to add this feature to the test version of the project? My changes have to be added to the "testing" branch so that they end up on the test server. First I commit my new extension:

svn commit -m 'my log message' extension/myextension

Second I copy it from "trunk" to "branches/testing":

svn copy ezpublish-4.0.0/extension/myextension ../branches/testing/ezpublish-4.0.0/extension

Third I commit the changes to the 'branches/testing' directory:

svn commit -m 'my log message' ../branches/testing/ezpublish-4.0.0/extension/myextension

In the example above, I am in the "trunk" directory. If your directory structure is different than the one we suggested above, adapt these commands so that the paths resolve correctly.

What if I only want to copy one file (for example myfile.php)?

First I commit my changes:

svn commit -m 'my log message' extension/myextension/myfile.php

Second I merge my changes between the "trunk" directory and the "testing" branch.

svn merge -rX:HEAD /path/to/my/repository/trunk/ezpublish-4.0.0/extension/myextension/classes/myfile.php

... where X is the revision number of the source file and /path/to/my/repository is the URL of the repository http://path/to/my/repository for example.

Here is a complete example of the commands used to merge a file from 'trunk' to 'branches/testing':

cd /path/to/my/repository/trunk/ezpublish-4.0.0/  

vi extension/myextension/classes/myfile2.php

   <modifying myfile2.php>

svn commit -m 'my log message' extension/myextension/classes/myfile2.php

 (the revision number is 51)

cd /path/to/my/repository/branches/testing/ezpublish-4.0.0/extension/myextension/classes/


svn merge -r51:HEAD http://path/to/my/repository/trunk/ezpublish-4.0.0/extension/myextension/classes/myfile2.php

   U   myfile2.php

And then I commit the changes with "svn commit".

You could also use the '-c X' argument with the "svn merge" command. An example is available in the documentation:

http://svnbook.red-bean.com/en/1.4/svn.branchmerge.copychanges.html

Note that the "svn merge" command may be confusing if you are not used to it. You may find this explanation useful:

http://svnbook.red-bean.com/nightly/en/svn.branchmerge.advanced.html#svn.branchmerge.advanced.advancedsyntax.

I have now ported my changes from the development branch to the testing branch. I can use the same technique to port my changes from testing to production by using the "testing" branch as the source and the "production" branch as the destination.

Be careful when merging. If you forget files it can take a long time to track down the problem. Also note that merging an entire directory from one branch to another can take some time.

Subversion's tag system could also be used in this scenario. (It is described here: http://svnbook.red-bean.com/en/1.4/svn.branchmerge.tags.html.) It is a matter of your own preference. For myself, I like the idea of branching and keeping things clean and separate.

How can I use Subversion and SQL?

Using SVN to version SQL Schema is a great idea. Subversion handles SQL files the same as
any other text-based file.

You can also use SVN to store definitions that cannot be exported from the eZ Publish Administration Interface. This makes sense, for example, for the permission system. If you want to export the entire permission system from one environment to another, you can create a SQL export of the "ezrole" and "ezpolicy_xx" tables and import it in another environment.

However, do not expect SVN to be able to store SQL dumps from a production environnment. Subversion is not a SQL backup tool. If you are looking for this use a replication system.

You will encouter this problem when you are using your own configuration to suit your local development environment. There are three ways to address it.

Ignoring the .ini file(s)

You can ignore a specific file (or a group of files) by using "svn propset svn:ignore". However, your environment will not be updated when ini files are changed in the repository. If the communication between your team is good then you can use this technique:

  1. Define an ignore flag with "svn propset".
  2. Do not commit this change (so that this flag is local).
  3. When your team warns you about an ini change remove your ignore flag (by using "svn propdel") and update the ini file(s).

You may have to deal with occasional conflicts, but this is part of the game. Resolving conflicts with SVN is easy and most conflicts can be resolved very quickly.

If you want to know more about conflict managment with SVN you will find this URL useful:

http://svnbook.red-bean.com/en/1.1/ch03s05.html#svn-ch-3-sect-5.4

Updating the versioned .ini file(s)

Another way to deal with shared .ini files in local environments is to commit and checkout versioned ini file(s), but never committing changes that are specific to an environment. However, in my opinion, this is a less secure method and more prone to error.

Using specific identifiers

When using a new configuration that you know needs to be adapted to each development environment, you can use a specific identifier in the .ini files. To indicate that the file contains environment-specific ini settings, developers append '.specific' to the end of the filename.

For example, if each developer needs to connect to his own database you could rename (using "svn rename") site.ini.append.php to site.ini.append.php.specific.

When a developer does a checkout or update of the project, he will download some .specific ini files. This will tell him that he has to rename them and update them.

Note that you can use a PHP or shell script that will automatically rename .specific files to the correct name.

If I use .specific append files how can I port them to the other branches?

You can use a build system.

Build systems are very common and provide a lot of features. Here is a list of a few build systems you might use for your projects:

Use the tool that best fits your needs.

By using a build tool you can automatically create a specific version of your application based upon the rules you have defined. This is just one example of the functionality available with build tools. It is up to you to define which tasks you want to be done in which context.

Before diving in, take time to define what you really need to build and deploy in your application. Here is a quick checklist you may find useful:

  • Checking the projects out
  • Giving correct database rigths to be able to create tables
  • Creating the basic database schema
  • Fixing the rights on this database - you might not need CREATE TABLE anymore ;)
  • Fixing rights on the file system (bin/linux/modfix.sh might help you)
  • Compiling templates (bin/php/eztc.php might help you)
  • ...

I hope I've shown how Subversion can tremendously help you with your eZ Publish projects. The information in this article can also be applied to any other development project. Of course you will have to adapt things to your context but usually the basic concepts still apply.

I have described what I consider best practice to efficiently work with SVN. However there are a lot of different ways to work with Subversion. It is not possible to describe all the possibilities in one article - maybe even a book would not be sufficient. However the simple processes and techniques I have described should be enough to get you going with Subversion and eZ Publish.

eZ debug

Timing: Jan 17 2025 23:39:56
Script start
Timing: Jan 17 2025 23:39:56
Module start 'content'
Timing: Jan 17 2025 23:39:57
Module end 'content'
Timing: Jan 17 2025 23:39:57
Script end

Main resources:

Total runtime0.3971 sec
Peak memory usage4,096.0000 KB
Database Queries166

Timing points:

CheckpointStart (sec)Duration (sec)Memory at start (KB)Memory used (KB)
Script start 0.00000.0068 587.7188180.8281
Module start 'content' 0.00680.1278 768.5469569.7891
Module end 'content' 0.13460.2624 1,338.3359416.0469
Script end 0.3970  1,754.3828 

Time accumulators:

 Accumulator Duration (sec) Duration (%) Count Average (sec)
Ini load
Load cache0.00411.0422210.0002
Check MTime0.00160.3923210.0001
Mysql Total
Database connection0.00070.175310.0007
Mysqli_queries0.264566.60311660.0016
Looping result0.00230.58931640.0000
Template Total0.356889.920.1784
Template load0.00190.485020.0010
Template processing0.354989.369720.1774
Template load and register function0.00010.022910.0001
states
state_id_array0.00100.240810.0010
state_identifier_array0.00100.257620.0005
Override
Cache load0.00200.50481750.0000
Sytem overhead
Fetch class attribute name0.00150.373910.0015
Fetch class attribute can translate value0.00080.208510.0008
class_abstraction
Instantiating content class attribute0.00000.001810.0000
XML
Image XML parsing0.00030.074110.0003
General
dbfile0.00270.6755220.0001
String conversion0.00000.001330.0000
Note: percentages do not add up to 100% because some accumulators overlap

CSS/JS files loaded with "ezjscPacker" during request:

CacheTypePacklevelSourceFiles
CSS0extension/community/design/community/stylesheets/ext/jquery.autocomplete.css
extension/community_design/design/suncana/stylesheets/scrollbars.css
extension/community_design/design/suncana/stylesheets/tabs.css
extension/community_design/design/suncana/stylesheets/roadmap.css
extension/community_design/design/suncana/stylesheets/content.css
extension/community_design/design/suncana/stylesheets/star-rating.css
extension/community_design/design/suncana/stylesheets/syntax_and_custom_tags.css
extension/community_design/design/suncana/stylesheets/buttons.css
extension/community_design/design/suncana/stylesheets/tweetbox.css
extension/community_design/design/suncana/stylesheets/jquery.fancybox-1.3.4.css
extension/bcsmoothgallery/design/standard/stylesheets/magnific-popup.css
extension/sevenx/design/simple/stylesheets/star_rating.css
extension/sevenx/design/simple/stylesheets/libs/fontawesome/css/all.min.css
extension/sevenx/design/simple/stylesheets/main.v02.css
extension/sevenx/design/simple/stylesheets/main.v02.res.css
JS0extension/ezjscore/design/standard/lib/yui/3.17.2/build/yui/yui-min.js
extension/ezjscore/design/standard/javascript/jquery-3.7.0.min.js
extension/community_design/design/suncana/javascript/jquery.ui.core.min.js
extension/community_design/design/suncana/javascript/jquery.ui.widget.min.js
extension/community_design/design/suncana/javascript/jquery.easing.1.3.js
extension/community_design/design/suncana/javascript/jquery.ui.tabs.js
extension/community_design/design/suncana/javascript/jquery.hoverIntent.min.js
extension/community_design/design/suncana/javascript/jquery.popmenu.js
extension/community_design/design/suncana/javascript/jScrollPane.js
extension/community_design/design/suncana/javascript/jquery.mousewheel.js
extension/community_design/design/suncana/javascript/jquery.cycle.all.js
extension/sevenx/design/simple/javascript/jquery.scrollTo.js
extension/community_design/design/suncana/javascript/jquery.cookie.js
extension/community_design/design/suncana/javascript/ezstarrating_jquery.js
extension/community_design/design/suncana/javascript/jquery.initboxes.js
extension/community_design/design/suncana/javascript/app.js
extension/community_design/design/suncana/javascript/twitterwidget.js
extension/community_design/design/suncana/javascript/community.js
extension/community_design/design/suncana/javascript/roadmap.js
extension/community_design/design/suncana/javascript/ez.js
extension/community_design/design/suncana/javascript/ezshareevents.js
extension/sevenx/design/simple/javascript/main.js

Templates used to render the page:

UsageRequested templateTemplateTemplate loadedEditOverride
1node/view/full.tplfull/article.tplextension/sevenx/design/simple/override/templates/full/article.tplEdit templateOverride template
1content/datatype/view/ezxmltext.tpl<No override>extension/community_design/design/suncana/templates/content/datatype/view/ezxmltext.tplEdit templateOverride template
17content/datatype/view/ezxmltags/header.tpl<No override>design/standard/templates/content/datatype/view/ezxmltags/header.tplEdit templateOverride template
53content/datatype/view/ezxmltags/paragraph.tpl<No override>extension/ezwebin/design/ezwebin/templates/content/datatype/view/ezxmltags/paragraph.tplEdit templateOverride template
19content/datatype/view/ezxmltags/link.tpl<No override>design/standard/templates/content/datatype/view/ezxmltags/link.tplEdit templateOverride template
11content/datatype/view/ezxmltags/li.tpl<No override>design/standard/templates/content/datatype/view/ezxmltags/li.tplEdit templateOverride template
2content/datatype/view/ezxmltags/ol.tpl<No override>design/standard/templates/content/datatype/view/ezxmltags/ol.tplEdit templateOverride template
5content/datatype/view/ezxmltags/newpage.tpl<No override>extension/community/design/standard/templates/content/datatype/view/ezxmltags/newpage.tplEdit templateOverride template
4content/datatype/view/ezxmltags/ul.tpl<No override>design/standard/templates/content/datatype/view/ezxmltags/ul.tplEdit templateOverride template
14content/datatype/view/ezxmltags/literal.tpl<No override>extension/community/design/standard/templates/content/datatype/view/ezxmltags/literal.tplEdit templateOverride template
2content/datatype/view/ezxmltags/line.tpl<No override>design/standard/templates/content/datatype/view/ezxmltags/line.tplEdit templateOverride template
3content/datatype/view/ezxmltags/emphasize.tpl<No override>design/standard/templates/content/datatype/view/ezxmltags/emphasize.tplEdit templateOverride template
1pagelayout.tpl<No override>extension/sevenx/design/simple/templates/pagelayout.tplEdit templateOverride template
 Number of times templates used: 133
 Number of unique templates used: 13

Time used to render debug report: 0.0001 secs