<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>LAMPlights &#187; svn</title>
	<atom:link href="http://www.hermanradtke.com/blog/tag/svn/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.hermanradtke.com</link>
	<description>Personal anecdotes from my experiences using the LAMP stack</description>
	<lastBuildDate>Wed, 25 Jan 2012 18:14:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Patching a bug in a pecl extension</title>
		<link>http://www.hermanradtke.com/blog/patching-a-bug-in-a-pecl-extension/</link>
		<comments>http://www.hermanradtke.com/blog/patching-a-bug-in-a-pecl-extension/#comments</comments>
		<pubDate>Sun, 08 May 2011 19:20:09 +0000</pubDate>
		<dc:creator>Herman Radtke</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[memcache]]></category>
		<category><![CDATA[pecl]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://www.hermanradtke.com/?p=659</guid>
		<description><![CDATA[In my last post I explained how to build a development version of a pecl extension.  Now we will go through the bug lifecycle in the pecl/memcache extension.  Besides writing the actual C code to fix the bug, it is considered a best practice to write a test that verifies the bug has been fixed.  [...]]]></description>
			<content:encoded><![CDATA[<p>In my <a title="Building php pecl extensions" href="http://www.hermanradtke.com/blog/building-php-pecl-extensions/" target="_blank">last post</a> I explained how to build a development version of a pecl extension.   Now we will go through the bug lifecycle in the pecl/memcache extension.  Besides writing the actual C code to fix the bug, it is considered a best practice to write a test that verifies the bug has been fixed.  I will use <a title="memcache_set fail with integer value" href="http://pecl.php.net/bugs/bug.php?id=16442" target="_blank">PECL bug #16442 - memcache_set fail with integer value</a> as an example, even though it is already been fixed.<span id="more-659"></span></p>
<p>Whether creating a patch for a bug fix yourself or applying a users patch to an existing bug, the process is pretty much the same.  The very first thing I do is create a <a title="PHP QAT website" href="http://qa.php.net/write-test.php" target="_blank">.phpt</a> test for the bug.  A .phpt test is a functional test used in php core and many pecl extensions.  All bug fixes should include a simple test so we can verify the bug is indeed fixed by the patch and to prevent a regression in the code where the bug is reintroduced.  The .phpt functional tests are quick to write and have such a positive long term investment I rarely find myself not wanting to write them.</p>
<p>Here is an example test:<br />
<code><br />
--TEST--<br />
PECL bug #16442 (memcache_set fail with integer value)<br />
--FILE--<br />
&lt;?php</p>
<p>include 'connect.inc'; </p>
<p>memcache_set($memcache, 'test123112', 1, MEMCACHE_COMPRESSED, 30);<br />
$ret = memcache_get($memcache, 'test123112');<br />
var_dump($ret);<br />
echo "Done\n";<br />
?&gt;<br />
--EXPECT--<br />
int(0)<br />
Done<br />
</code></p>
<p>There are three basic parts to a .phpt file: test information, the test itself and the expected test results.  The test information section is denoted by the "--TEST--" heading.  This is where information about the test is placed.  For bug fixes I normally include the bug number and a brief description of the bug.  The brief description sometimes matches the bug title, but there are cases where the bug title doesn't describe the actual bug so I will make a better description up.</p>
<p>After the informational block  is the actual test itself, denoted by the "--FILE--" heading.  The test itself is always normal php code.  You will notice that the test includes a 'connect.inc' file.  This is a standard convention for tests that depend on some outside system or environment.  In the case of pecl/memcache, the connect.inc sets up a number of connections to memcache using various ip addresses, ports and protocols (tcp and udp).  This is done to make sure all tests are testing against the same servers and to reduce the amount of boilerplate code in the tests.  It is considered a best practice to use var_dump() for any kind of test output.  This makes the output as explicit as possible.  You will also notice many tests end with an echo "OK\n" or an echo "Done\n" statement.  This is done to explicitly define the end of the test.  This can help catch extra test output, such as warnings or errors, that should cause the test to fail.</p>
<p>The last section is the expected test results section.  There are a number of different ways to express test results, including normal string comparison (--EXPECT--), printf style formatting (--EXPECTF--) and regular expressions(--EXPECTREGEX--).  Explaining how each of them work and when to use each one is would take an entire blog article itself.  Luckily, the PHP QA team has an <a href="http://qa.php.net/write-test.php" target="_blank">article</a> that discussions each one in detail.  I almost always use EXPECTF for the test results, even if I am not using any format characters.  This is more the result of copy/paste than any explicit decision on my part.  You should try to be as generic in your test output as possible.  For example, if you are expecting a warning to show in the test results, make sure you do not explicitly check for your local path to the file in the warning output.  This will cause the test to fail for anyone else.</p>
<p>I mentioned earlier that there are three parts to a .php test, but I lied.  There are actually a few more, but they are less commonly used.  I suggest you read through the PHP QA <a href="http://qa.php.net/write-test.php" target="_blank">article</a> on writing .phpt tests for a full explanation of .phpt test syntax and usage.  I am merely highlighting the major points to get us up and running.</p>
<p>I have noticed that there is a general best practice to naming .phpt test files.  Non bug fix .phpt tests are sequentially numbers starting from 001.  I call these feature tests.  As development continues on a package, new tests are created.  You will notice there are over 100 features tests in pecl/memcache/branches/NON_BLOCKING_IO/tests.  For bug fixes, .phpt tests follow the format of 'pecl{bug #}.phpt'.  This means I would name the .phpt test file for PECL bug #16442 as pecl16442.phpt.</p>
<p>Naturally we want to run the test once it is written.  The php community has provided a tool, called run-tests.php, that runs all or a subset of tests for a given package.  The run-tests.php script is pretty flexible.  You can specify a directory to run all tests in, specify a list of tests to run or specify a single test to run.  Here are some examples:<br />
<code><br />
# run a single test<br />
TEST_PHP_EXECUTABLE=/usr/local/php/bin/php php run-tests.php tests/pecl16442.phpt</p>
<p># run a two tests<br />
TEST_PHP_EXECUTABLE=/usr/local/php/bin/php php run-tests.php tests/pecl16442.phpt tests/pecl16536.phpt</p>
<p># run all tests in the tests/ directory<br />
TEST_PHP_EXECUTABLE=/usr/local/php/bin/php php run-tests.php tests/<br />
</code></p>
<p>The syntax of these commands might look a little strange.  The run-tests.php does not try to assume which php executable you want to run the tests against.  Without this variable being set, the script will throw an error that looks like: "<em>ERROR: environment variable TEST_PHP_EXECUTABLE must be set to specify PHP executable!</em>".  I am using a bash trick to set the PHP_TEST_EXECUTABLE variable before running each test.  You can also export this variable so it is available each time you run the tests.  If you decide to export it, you should consider adding it to your .bash_profile so you don't have to do it each time you login.  Whichever way you do it, as long as you set this variable before running the run-tests.php script you will be fine.</p>
<p>Running the tests will generate some nicely formatted output.  The output is self-explanatory, so I will not go over it here.  I do want to talk about some interesting things that happen when a test fails.  I changed the "--EXPECT--" portion of my test example to "int(0)".  If you run this test you will notice it listed in the "FAILED TEST SUMMARY".  What you don't see is the actual test output or even more importantly <em>why</em> test failed.  Thankfully, run-tests.php has us covered.  If you look at the output of the tests/ directory you will notice some new files:<br />
<code><br />
tests/pecl16442.diff # a diff of the expected output and results<br />
tests/pecl16442.exp # the expected output<br />
tests/pecl16442.log # a log of the test run<br />
tests/pecl16442.out # the actual test output<br />
tests/pecl16442.php # the php code used to run the test<br />
</code></p>
<p>I find the .out and .php files most useful when debugging code.  When trying to fix a bug I will run the test using run-tests.php once and the continually test against the .php file until I am reasonably sure I have fixed the bug.  I will then use run-tests.php again and see if it passed.  The .out file is useful to see exactly what the test result actually was.  I sometimes use the .diff file when I am head scratching as to why a test I think should have passed is not passing.  Some trivial issues such as newlines and extra spacing can sometimes create a false positive in an otherwise passing test.</p>
<p>After applying the fix to the memcache source code to allow integer values in memcache_set and using run-tests.php to check if the test pecl16442.phpt passes, we need to make sure we run all the tests.  As I mentioned earlier, the existing tests are a there to help prevent regressions in the source code.  One should always check that all tests pass before committing any new code.  I will mention that this can be frustrating when working with a pecl extension that has tests that always seem to fail.  If this is the case, use your best judgement.  You may also want to fix the failing tests before doing any new work on the extension too.</p>
<p>Once all the tests pass, commit your changed source code files and the .phpt test file(s).  Make sure you do not include any of the failed test files that are automatically generated.  If you do not have commit access, include the source code files in the bug report along with the test.  There is nothing any pecl maintainer likes more than having tests included with the patch.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hermanradtke.com/blog/patching-a-bug-in-a-pecl-extension/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Building php pecl extensions</title>
		<link>http://www.hermanradtke.com/blog/building-php-pecl-extensions/</link>
		<comments>http://www.hermanradtke.com/blog/building-php-pecl-extensions/#comments</comments>
		<pubDate>Sat, 07 May 2011 17:04:56 +0000</pubDate>
		<dc:creator>Herman Radtke</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[gdb]]></category>
		<category><![CDATA[pecl]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://www.hermanradtke.com/?p=648</guid>
		<description><![CDATA[My last post I explained how to efficiently checkout the php svn repository.  Now we need to start building pecl extensions and even php itself.  I prefer to use Cent OS for my linux needs and naturally use rpm's to track all my packages.  This means I have a stable version of php installed with [...]]]></description>
			<content:encoded><![CDATA[<p>My <a title="Working with the PHP source tree" href="http://www.hermanradtke.com/blog/working-with-the-php-source-tree/" target="_blank">last post</a> I explained how to efficiently checkout the php svn repository.  Now we need to start building pecl extensions and even php itself.  I prefer to use Cent OS for my linux needs and naturally use rpm's to track all my packages.  This means I have a stable version of php installed with all the various extensions that I could want.  Rather than messing with this stable version, I am going to build a custom debug build of php in /usr/local.  I say "debug", because this build of php will use the --enable-debug option to allow easy debugging using gdb.  Since I am doing pecl extension development, I don't want to build the trunk version of php.  I want to build my pecl extensions against the most recent stable version of php to isolate environmental issues as much as possible.<span id="more-648"></span></p>
<p>Now building php from an svn tag is more tricky than building from a snapshot.  The goal is to start building extensions, so rather than waste time navigating the hurdles of building from svn, I will just grab the latest stable version of php from php.net.  Building php becomes very similar to any other program you have compiled from source.</p>
<p><code><br />
wget http://www.php.net/get/php-5.3.6.tar.gz/from/this/mirror<br />
tar xzf php-5.3.6.tar.gz<br />
cd php-5.3.6<br />
./configure --prefix=/usr/local/php-5.3.6 --with-config-file-path=/usr/local/php-5.3.6/etc --enable-debug<br />
make<br />
make test #optional<br />
sudo make install<br />
sudo cp php.ini-development /usr/local/php-5.3.6/etc/php.ini<br />
sudo ln -s /usr/local/php-5.3.6 /usr/local/php<br />
</code></p>
<p>You will notice that I specified a version specific prefix for php to be installed at.  I do this so I can build multiple versions without clobbering an older build.  However, this makes maintaining any helper scripts a pain as the version continually changes.  To make things easier, I created a symlink so I can specify /usr/local/php for any helper scripts.  You may also want to add /usr/local/php/bin to your PATH in .bash_profile.</p>
<p>Now let's compile the pecl/memcache extesnsion.<br />
<code><br />
cd php/src/pecl/memcache/trunk<br />
phpize<br />
./configure --enable-debug<br />
make<br />
make test<br />
</code></p>
<p>The phpize script is a bash script that bootstraps the environment for the pecl extension based on your installed version of php.  If you have multiple php versions installed, it is very important that you are using the correct phpize script.  I suggest using 'which phpize' to make sure that /usr/local/php/bin/phpize is the script you are using.</p>
<p>Now you will notice that I did not perform a 'make install'.  I generally don't install my extensions while developing with them.  I sometimes bounce back and forth between a few different version of an extension trying to fix various bugs and implement new features.  I prefer to specify the full path to the extension in my php.ini file.  The extension line will look something like this:<br />
<code><br />
extension=/home/hradtke/projects/php/src/pecl/memcache/trunk/modules/memcache.so<br />
</code><br />
Once that line is added you can verify the extension is loaded properly by running 'php -m'.  If you want more detail, you can run 'php -i'.</p>
<p>Now you can start playing with the code.  If you are unsure where to start, I suggest reading these articles:</p>
<ul>
<li><a href="http://devzone.zend.com/node/view/id/1021" target="_blank">Extension Writing Part I: Introduction to PHP and Zend</a></li>
<li><a href="http://devzone.zend.com/node/view/id/1022" target="_blank">Extension Writing Part II: Parameters, Arrays, and ZVALs</a></li>
<li><a href="http://devzone.zend.com/node/view/id/1024" target="_blank">Extension Writing Part III: Resources</a></li>
<li><a href="http://blog.golemon.com/2006/06/what-heck-is-tsrmlscc-anyway.html" target="_blank">What the heck is TSRMLS_CC, anyway?</a></li>
<li><a href="http://www.phpbuilder.com/manual/en/zend.variables.php" target="_blank">Zend API: Hacking the Core of PHP</a></li>
<li><a href="http://talks.somabo.de/200711_php_code_camp.pdf" target="_blank">Extending PHP</a></li>
</ul>
<p>If you get through all that and still want to know more, I suggest purchasing Sara Goleman's book <a href="http://www.amazon.com/Extending-Embedding-PHP-Sara-Golemon/dp/067232704X" target="_blank">Extending and Embedding PHP</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hermanradtke.com/blog/building-php-pecl-extensions/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Working with the PHP source tree</title>
		<link>http://www.hermanradtke.com/blog/working-with-the-php-source-tree/</link>
		<comments>http://www.hermanradtke.com/blog/working-with-the-php-source-tree/#comments</comments>
		<pubDate>Mon, 02 May 2011 15:17:12 +0000</pubDate>
		<dc:creator>Herman Radtke</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[pecl]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://www.hermanradtke.com/?p=638</guid>
		<description><![CDATA[The svn repository for PHP is rather large.  Trying to checkout the entire repo is both time consuming and wastes a lot of space.  Most people, including myself, are only concerned with a subset of the repository.  One of the advantages svn has over git is the ability to do partial checkouts of the repository.  [...]]]></description>
			<content:encoded><![CDATA[<p>The svn repository for PHP is rather large.  Trying to checkout the entire repo is both time consuming and wastes a lot of space.  Most people, including myself, are only concerned with a subset of the repository.  One of the advantages svn has over git is the ability to do partial checkouts of the repository.  I am going to borrow from an old <a title="svn checkout suggestion" href="http://www.mail-archive.com/internals@lists.php.net/msg43154.html" target="_blank">email</a> Rasmus sent that details how to do a partial checkout of the PHP source code.<span id="more-638"></span>I mostly work on pecl/memcache and pecl/gearman and send the occasional patch for a php core extension.  I will ignore any other branches of the PHP svn repository that I am not currently working on.</p>
<p>Here is my checkout process:</p>
<ul>
<li><strong>svn co http://svn.php.net/repository --depth empty src</strong>
<ul>
<li>Checkout the intial, empty, repository</li>
</ul>
</li>
<li><strong>svn co http://svn.php.net/repository/php http://svn.php.net/repository/pecl --depth immediates src</strong>
<ul>
<li>Checkout the immediate files and directories in the php and pecl directories of the repository.  This will checkout empty directories for all the pecl extensions and empty directories for the php modules.</li>
</ul>
</li>
<li><strong>cd src/php/php-src</strong></li>
<li><strong>svn up branches tags --set-depth immediates </strong>
<ul>
<li>Checkout empty directories for all branches and tags under php-src.  Any branches or tags created in the future will automatically be created as an empty directory on a future svn update.</li>
</ul>
</li>
<li><strong>svn up trunk branches/PHP_5_3/ --set-depth infinity</strong>
<ul>
<li>Checkout all the source code for trunk and the PHP 5.3 development branch.</li>
</ul>
</li>
<li><strong>cd ../../pecl/</strong></li>
<li><strong>svn up gearman memcache --set-depth infinity</strong>
<ul>
<li>Checkout trunk, branches and tags for the pecl/gearman and pecl/memcache extensions</li>
</ul>
</li>
</ul>
<p>The great thing about this approach is that I can show and hide other  parts of the PHP svn repository at will with only a few svn update  commands.  I regularly add an remove other parts of the PHP svn repository at will.  Combined with <a href="http://lxr.php.net/">http://lxr.php.net/</a>, I can quickly find examples and code I am looking for.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hermanradtke.com/blog/working-with-the-php-source-tree/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Canonical Version Numbers with Git</title>
		<link>http://www.hermanradtke.com/blog/canonical-version-numbers-with-git/</link>
		<comments>http://www.hermanradtke.com/blog/canonical-version-numbers-with-git/#comments</comments>
		<pubDate>Fri, 05 Feb 2010 17:25:07 +0000</pubDate>
		<dc:creator>Herman Radtke</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[versioning]]></category>

		<guid isPermaLink="false">http://www.hermanradtke.com/blog/?p=315</guid>
		<description><![CDATA[Brandon Savage wrote a controversial blog post about why subversion is still more relevant than git.  His main point was that enterprise requires canonical version numbering to track progress in the application and that git cannot do this.   There was a lot of debate about this on Brandson's, but a recent comment by Morgan proved [...]]]></description>
			<content:encoded><![CDATA[<p>Brandon Savage wrote a <a href="http://www.brandonsavage.net/why-subversion-still-beats-git/" target="_blank">controversial blog post</a> about why subversion is still more relevant than git.  His main point was that enterprise requires canonical version numbering to track progress in the application and that git cannot do this.   There was a lot of debate about this on Brandson's, but a recent comment by Morgan proved Brandon wrong.</p>
<p><span id="more-315"></span></p>
<p>I have never had a problem with the lack of canonical version numbers, but I can see why companies who have used CVS or subversion for a long time would be wary of getting rid of them.  Morgan explains how to use the <a href="http://www.kernel.org/pub/software/scm/git/docs/git-describe.html" target="_blank">git describe</a> command to generate canonical version numbers.  I have used git for a while for personal projects and at HauteLook, but have never used this command.  I thought this was a great solution to a problem a lot of companies face when trying to migrate from subversion to git.</p>
<p>Morgan's comment:</p>
<blockquote><p>git describe –tags –long</p>
<p>This gives you a string like (in the case of one of my projects)</p>
<p>2.1pre5-4-g675eae1</p>
<p>which is formatted as</p>
<p>{last reachable tag name}-{# of commits since that tag}-#{SHA of HEAD}</p>
<p>This gives you a ‘canonical version number’ (spelling corrected) that is monotonically increasing by commits, and unique across multiple repositories of development. If we’re all on the same HEAD, it will return the same value. If we all share the same most-recent-tag, but have different commits, the SHA will be different.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.hermanradtke.com/blog/canonical-version-numbers-with-git/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

