<?xml version="1.0" encoding="UTF-8"?>
<rss 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/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>LeetCode.net</title>
	
	<link>http://leetcode.net/blog</link>
	<description>Open source software engineering</description>
	<lastBuildDate>Wed, 03 Mar 2010 02:18:26 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/leetcode" /><feedburner:info uri="leetcode" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><creativeCommons:license>http://creativecommons.org/licenses/by-nc-nd/2.5/</creativeCommons:license><image><link>http://creativecommons.org/licenses/by-nc-nd/2.5/</link><url>http://creativecommons.org/images/public/somerights20.gif</url><title>Some Rights Reserved</title></image><item>
		<title>PHP Bugs Me, or Where Type Coercion Causes Bugs</title>
		<link>http://feedproxy.google.com/~r/leetcode/~3/70fgatzNFbQ/</link>
		<comments>http://leetcode.net/blog/2010/03/php-bugs-me-or-where-type-coercion-causes-bugs/#comments</comments>
		<pubDate>Wed, 03 Mar 2010 02:18:26 +0000</pubDate>
		<dc:creator>John Reese</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[facepalm]]></category>
		<category><![CDATA[mantisbt]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://leetcode.net/blog/?p=179</guid>
		<description><![CDATA[I really like PHP as a technology, both for its extensibility and its deployment style. I think it is the quickest and most straightforward platform to create web applications with, and frameworks like CodeIgniter make it even better. 
I&#8217;ve long been on the fence regarding PHP&#8217;s type coercion and comparison issues, but a recent bug [...]]]></description>
			<content:encoded><![CDATA[<p>I really like PHP as a technology, both for its extensibility and its deployment style. I think it is the quickest and most straightforward platform to create web applications with, and frameworks like <a href="http://codeigniter.com/">CodeIgniter</a> make it even better. </p>
<p>I&#8217;ve long been on the fence regarding PHP&#8217;s type coercion and comparison issues, but a <a href="http://www.mantisbt.org/bugs/view.php?id=11571">recent bug</a> in <a href="http://www.mantisbt.org">Mantis Bug Tracker</a> has made me /facepalm for the first time in my long history of working with PHP:</p>
<blockquote><p>When I click on &#8220;Edit&#8221; next to 1.2, mantis shows me the 1.20 properties. When I click 1.1 it shows me 1.10!</p></blockquote>
<p>The offending snippet of code:</p>
<p><code>
<pre>
foreach( $g_cache_versions as $t_version ) {
   if(( <strong>$t_version['version'] == $p_version</strong> )
      &amp;&amp; ( $t_version['project_id'] == $c_project_id ) ) {
      return $t_version['id'];
   }
}</pre>
<p></code></p>
<p>At first glance, it seems perfectly normal&#8230; and then you read the commit log, emphasis mine:</p>
<blockquote><p>This is due to an incorrect version name comparison in version_get_id whereby the following check between strings was occurring:</p>
<p>if( &#8220;1.1&#8243; == &#8220;1.10&#8243; ) { &#8230; }</p>
<p>PHP evaluates this expression to true <em>because 1.1 and 1.10 are treated as floats</em>. We however need to preserve the string type during this comparison, thus we need to use the === comparison operator instead.</p></blockquote>
<p>I thought I&#8217;d seen it all&#8230;</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/leetcode?a=70fgatzNFbQ:hzcrziXhV2Q:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=70fgatzNFbQ:hzcrziXhV2Q:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=70fgatzNFbQ:hzcrziXhV2Q:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/leetcode?i=70fgatzNFbQ:hzcrziXhV2Q:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=70fgatzNFbQ:hzcrziXhV2Q:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/leetcode?d=dnMXMwOfBR0" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://leetcode.net/blog/2010/03/php-bugs-me-or-where-type-coercion-causes-bugs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://leetcode.net/blog/2010/03/php-bugs-me-or-where-type-coercion-causes-bugs/</feedburner:origLink></item>
		<item>
		<title>1000 Commits!</title>
		<link>http://feedproxy.google.com/~r/leetcode/~3/7MVh06s7bCg/</link>
		<comments>http://leetcode.net/blog/2009/12/1000-commits/#comments</comments>
		<pubDate>Fri, 04 Dec 2009 00:34:42 +0000</pubDate>
		<dc:creator>John Reese</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[jobs]]></category>
		<category><![CDATA[me]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[resumé]]></category>

		<guid isPermaLink="false">http://leetcode.net/blog/?p=176</guid>
		<description><![CDATA[I&#8217;ve just reached the 1000 commit milestone as recorded by my Ohloh profile.  By far, most of them are related to my work on the MantisBT project and associated plugins.
Now if only I could find a job local to Cincinnati&#8230;  If you are interested in hiring me, or know someone who&#8217;s looking for [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just reached the 1000 commit milestone as recorded by <a href="http://www.ohloh.net/accounts/nuclear_eclipse">my Ohloh profile</a>.  By far, most of them are related to my work on the MantisBT project and associated plugins.</p>
<p>Now if only I could find a job local to Cincinnati&#8230;  If you are interested in hiring me, or know someone who&#8217;s looking for an open source developer, take a look at <a href="http://johnmreese.com/resume">my résumé</a>.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/leetcode?a=7MVh06s7bCg:QBC9roqqAoM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=7MVh06s7bCg:QBC9roqqAoM:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=7MVh06s7bCg:QBC9roqqAoM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/leetcode?i=7MVh06s7bCg:QBC9roqqAoM:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=7MVh06s7bCg:QBC9roqqAoM:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/leetcode?d=dnMXMwOfBR0" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://leetcode.net/blog/2009/12/1000-commits/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://leetcode.net/blog/2009/12/1000-commits/</feedburner:origLink></item>
		<item>
		<title>Detailed Integration of Subversion in MantisBT</title>
		<link>http://feedproxy.google.com/~r/leetcode/~3/D2Dax2nm_v4/</link>
		<comments>http://leetcode.net/blog/2009/10/detailed-integration-of-subversion-in-mantisbt/#comments</comments>
		<pubDate>Thu, 15 Oct 2009 03:31:15 +0000</pubDate>
		<dc:creator>John Reese</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[mantisbt]]></category>
		<category><![CDATA[source integration]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://leetcode.net/blog/?p=171</guid>
		<description><![CDATA[Chris Dornfeld at Unitz has an excellent, detailed overview of the options available when importing Subversion repositories into MantisBT using my Source Integration framework.  My previous article on the topic fails to go into particulars with SVN repositories, mainly because many of the options weren&#8217;t even dreamed of at the time, let alone implemented.
Anyways, [...]]]></description>
			<content:encoded><![CDATA[<p>Chris Dornfeld at <a href="http://www.unitz.com/">Unitz</a> has an excellent, <a href="http://www.unitz.com/u-notez/2009/10/subversion-svn-integration-mantisbt/">detailed overview</a> of the options available when importing Subversion repositories into MantisBT using my Source Integration framework.  My <a href="http://leetcode.net/blog/2009/01/integrating-git-svn-with-mantisbt/">previous article</a> on the topic fails to go into particulars with SVN repositories, mainly because many of the options weren&#8217;t even dreamed of at the time, let alone implemented.</p>
<p>Anyways, the information and explanations presented in his article are pretty accurate.  Until I can get the time to fully document the SVN and Git plugins, or the framework as a whole, consider Chris&#8217;s post to be canonical information.</p>
<p>Cheers</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/leetcode?a=D2Dax2nm_v4:HBgchEmZ2JQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=D2Dax2nm_v4:HBgchEmZ2JQ:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=D2Dax2nm_v4:HBgchEmZ2JQ:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/leetcode?i=D2Dax2nm_v4:HBgchEmZ2JQ:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=D2Dax2nm_v4:HBgchEmZ2JQ:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/leetcode?d=dnMXMwOfBR0" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://leetcode.net/blog/2009/10/detailed-integration-of-subversion-in-mantisbt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://leetcode.net/blog/2009/10/detailed-integration-of-subversion-in-mantisbt/</feedburner:origLink></item>
		<item>
		<title>The Good King Lisp</title>
		<link>http://feedproxy.google.com/~r/leetcode/~3/KD1ejm1W4PI/</link>
		<comments>http://leetcode.net/blog/2009/08/the-good-king-lisp/#comments</comments>
		<pubDate>Wed, 05 Aug 2009 15:35:25 +0000</pubDate>
		<dc:creator>John Reese</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[comment]]></category>
		<category><![CDATA[random]]></category>

		<guid isPermaLink="false">http://leetcode.net/blog/?p=167</guid>
		<description><![CDATA[From HN:
The Good King Lisp raised his glass and toasted with the Knights of Lambda, &#8220;To much recursion!&#8221;
]]></description>
			<content:encoded><![CDATA[<p>From <a href="http://news.ycombinator.com/item?id=743144">HN</a>:</p>
<blockquote cite="http://news.ycombinator.com/item?id=743482"><p>The Good King Lisp raised his glass and toasted with the Knights of Lambda, &#8220;To much recursion!&#8221;</p></blockquote>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/leetcode?a=KD1ejm1W4PI:8qBgzet4bt4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=KD1ejm1W4PI:8qBgzet4bt4:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=KD1ejm1W4PI:8qBgzet4bt4:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/leetcode?i=KD1ejm1W4PI:8qBgzet4bt4:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=KD1ejm1W4PI:8qBgzet4bt4:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/leetcode?d=dnMXMwOfBR0" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://leetcode.net/blog/2009/08/the-good-king-lisp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://leetcode.net/blog/2009/08/the-good-king-lisp/</feedburner:origLink></item>
		<item>
		<title>Twenty Four</title>
		<link>http://feedproxy.google.com/~r/leetcode/~3/aRH8iApxhRM/</link>
		<comments>http://leetcode.net/blog/2009/04/twenty-four/#comments</comments>
		<pubDate>Mon, 27 Apr 2009 13:00:08 +0000</pubDate>
		<dc:creator>John Reese</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[me]]></category>
		<category><![CDATA[random]]></category>

		<guid isPermaLink="false">http://leetcode.net/blog/?p=151</guid>
		<description><![CDATA[What&#8217;s twenty-four?

Six by four
Eight by three
Twelve by two
Six past legal
Three past drinking
One before cheap insurance
Space Shuttle Discovery
SLR cameras

Nifty.
]]></description>
			<content:encoded><![CDATA[<div class="wp-caption aligncenter" style="width: 442px"><a href="http://www.explosm.net/comics/54/"><img alt="Happy birthday to me." src="http://files.leetcode.net/comics/explosm/happybirthday.jpg" width="432" height="388" /></a><p class="wp-caption-text">Happy birthday to me.</p></div>
<p>What&#8217;s twenty-four?</p>
<ul>
<li>Six by four</li>
<li>Eight by three</li>
<li>Twelve by two</li>
<li>Six past legal</li>
<li>Three past drinking</li>
<li>One before cheap insurance</li>
<li>Space Shuttle Discovery</li>
<li>SLR cameras</li>
</ul>
<p>Nifty.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/leetcode?a=aRH8iApxhRM:u0MlyVX4TAc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=aRH8iApxhRM:u0MlyVX4TAc:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=aRH8iApxhRM:u0MlyVX4TAc:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/leetcode?i=aRH8iApxhRM:u0MlyVX4TAc:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=aRH8iApxhRM:u0MlyVX4TAc:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/leetcode?d=dnMXMwOfBR0" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://leetcode.net/blog/2009/04/twenty-four/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://leetcode.net/blog/2009/04/twenty-four/</feedburner:origLink></item>
		<item>
		<title>MantisBT Source Integration – BarCamp Presentation Slides</title>
		<link>http://feedproxy.google.com/~r/leetcode/~3/VlzOYDBow5Q/</link>
		<comments>http://leetcode.net/blog/2009/04/mantisbt-source-integration-barcamp-presentation-slides/#comments</comments>
		<pubDate>Sat, 18 Apr 2009 19:13:55 +0000</pubDate>
		<dc:creator>John Reese</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[barcamp]]></category>
		<category><![CDATA[mantisbt]]></category>
		<category><![CDATA[rit]]></category>
		<category><![CDATA[slides]]></category>

		<guid isPermaLink="false">http://leetcode.net/blog/2009/04/mantisbt-source-integration-barcamp-presentation-slides/</guid>
		<description><![CDATA[Since I&#8217;m about to present the topic, I&#8217;m making the presentation slides available for all.  There will indeed be video of the talk, which I will post as soon I can afterwards.
The slides are hosted directly on Google Docs: http://docs.google.com/Presentation?id=dffhxmhs_1273ct3kc8
]]></description>
			<content:encoded><![CDATA[<p>Since I&#8217;m about to present the topic, I&#8217;m making the presentation slides available for all.  There will indeed be video of the talk, which I will post as soon I can afterwards.</p>
<p>The slides are hosted directly on Google Docs: <a href="http://docs.google.com/Presentation?id=dffhxmhs_1273ct3kc8">http://docs.google.com/Presentation?id=dffhxmhs_1273ct3kc8</a></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/leetcode?a=VlzOYDBow5Q:LHo4YRFq33o:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=VlzOYDBow5Q:LHo4YRFq33o:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=VlzOYDBow5Q:LHo4YRFq33o:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/leetcode?i=VlzOYDBow5Q:LHo4YRFq33o:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=VlzOYDBow5Q:LHo4YRFq33o:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/leetcode?d=dnMXMwOfBR0" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://leetcode.net/blog/2009/04/mantisbt-source-integration-barcamp-presentation-slides/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://leetcode.net/blog/2009/04/mantisbt-source-integration-barcamp-presentation-slides/</feedburner:origLink></item>
		<item>
		<title>BarCamp Rochester</title>
		<link>http://feedproxy.google.com/~r/leetcode/~3/C1gSqAIaxF0/</link>
		<comments>http://leetcode.net/blog/2009/04/barcamp-rochester/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 19:12:26 +0000</pubDate>
		<dc:creator>John Reese</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[barcamp]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[mantisbt]]></category>
		<category><![CDATA[rit]]></category>

		<guid isPermaLink="false">http://leetcode.net/blog/2009/04/barcamp-rochester/</guid>
		<description><![CDATA[Context: BarCamp Rochester &#8212; Anyone and everyone is invited to attend, and everyone is highly encouraged to present something of their own, no matter what it is.  It&#8217;s happening this weekend at RIT, where I&#8217;m studying (and graduating in about a month!) for Software Engineering.
I&#8217;ll be attending it to give a presentation on MantisBT [...]]]></description>
			<content:encoded><![CDATA[<p>Context: <a href="http://www.barcamproc.org">BarCamp Rochester</a> &#8212; Anyone and everyone is invited to attend, and everyone is highly encouraged to present something of their own, no matter what it is.  It&#8217;s happening this weekend at RIT, where I&#8217;m studying (and graduating in about a month!) for Software Engineering.</p>
<p>I&#8217;ll be attending it to give a presentation on MantisBT and the Source Integration framework.  Specifically, I&#8217;ll be covering the myriad of new features that have made it into the project over the past week and a half.  I plan to walk through setting up a project in Mantis, creating a new repository on <a href="http://github.com">GitHub</a>, linking the Source Integration framework to that, and showing how the branch mapping and auto-resolving features work.  Should be interesting.</p>
<p>After the presentation, I plan to post the slides, along with my presentation notes, up here.  If anyone decides to video the talk, I&#8217;ll also make sure I can get a copy of that as well, but no promises.</p>
<p>Cheers!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/leetcode?a=C1gSqAIaxF0:Yr5oouixsQE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=C1gSqAIaxF0:Yr5oouixsQE:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=C1gSqAIaxF0:Yr5oouixsQE:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/leetcode?i=C1gSqAIaxF0:Yr5oouixsQE:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=C1gSqAIaxF0:Yr5oouixsQE:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/leetcode?d=dnMXMwOfBR0" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://leetcode.net/blog/2009/04/barcamp-rochester/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://leetcode.net/blog/2009/04/barcamp-rochester/</feedburner:origLink></item>
		<item>
		<title>Integrating Source Control Tools with Mantis Bug Tracker</title>
		<link>http://feedproxy.google.com/~r/leetcode/~3/_h3pX53THag/</link>
		<comments>http://leetcode.net/blog/2009/03/integrating-source-control-with-mantisbt/#comments</comments>
		<pubDate>Sun, 22 Mar 2009 18:57:58 +0000</pubDate>
		<dc:creator>John Reese</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[bzr]]></category>
		<category><![CDATA[cvs]]></category>
		<category><![CDATA[hg]]></category>
		<category><![CDATA[mantisbt]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[source integration]]></category>

		<guid isPermaLink="false">http://leetcode.net/blog/?p=119</guid>
		<description><![CDATA[Considering that my last post on Integrating Git and SVN has garnered a fair amount of attention, I thought that it would be useful to discuss my Source Integration framework in more detail.  Specifically, I&#8217;ll be covering topics such as the design and implementation of the framework and, more importantly, how developers can go [...]]]></description>
			<content:encoded><![CDATA[<p>Considering that my last post on <a href="http://leetcode.net/blog/2009/01/integrating-git-svn-with-mantisbt/">Integrating Git and SVN</a> has garnered a fair amount of attention, I thought that it would be useful to discuss my Source Integration framework in more detail.  Specifically, I&#8217;ll be covering topics such as the design and implementation of the framework and, more importantly, how developers can go about implementing support for other version control tools.</p>
<p>The point of this is to show that it&#8217;s quite possible to integrate just about any type of version control tool with the Source Integration system; indeed I planned from the beginning to create a generalized framework that would support many different types and paradigms for version control.  This should at least be evident in that I have already created extension plugins for Git and Subversion &#8211; it should be quite possible to extend the concepts further to Mercurial, Bazaar, CVS, or any other tool.</p>
<p>For the point of brevity, I&#8217;ll make the assumption that the developer at least has a fair understanding of PHP, their version control tool, and how events and plugins work in <a href="http://www.mantisbt.org">MantisBT</a>.  If you are not yet familiar with the plugin system, there is currently a basic introduction in the <a href="http://docs.mantisbt.org/master/en/developers/">MantisBT Developer&#8217;s Guide</a>, which I&#8217;ll hopefully be adding more information to in the near future.</p>
<p><span id="more-119"></span></p>
<p><em>Note: the following few sections dive into the concepts of how the framework was designed; for those just interested in creating extension plugins, skip to the <a href="#implementation">implementation</a> section.</em></p>
<p><strong>Design Decisions</strong></p>
<p>I tried to approach the design of this system from the standpoint of both generality and simplicity; there are many source control topics that I have either brushed out of the way, or left up to the implementations of other existing projects.  The end goal was to have a flexible system that could support almost any type of tool currently available, while also abstracting (or delegating) away as much as possible to simplify the implementation.</p>
<p>The biggest part of the design that I chose to delegate away was the topic of viewing file contents and commit differences.  There are so many existing tools out there to handle those tasks within source control repositories, that I figured it was a waste of time to worry about.  This means that my system relies on external viewing applications for any repositories in use; for Git, there&#8217;s <a href="http://github.com">GitHub</a> and <a href="http://git.or.cz/gitwiki/Gitweb">Gitweb</a> support, and <a href="http://websvn.tigris.org/">WebSVN</a> or <a href="http://www.sourceforge.net">SourceForge</a> for Subversion.</p>
<p>Another design abstraction that I decided upon was the handling of tool-specific details, such as how changesets are labelled, or how branches and other such topics are implemented.  I chose to store as neutral a data model as possible, and delegate any display (or interpretation) of the data to the appropriate extension plugins.  For instance, this allows SVN plugins to prepend the standard &#8216;r&#8217; in front of revision numbers (such as &#8220;r123&#8243;), while Git plugins can crop the changeset hash at eight characters for easier user consumption.</p>
<p>The resulting design utilizes the <a href="http://en.wikipedia.org/wiki/Inversion_of_control">Inversion of Control</a> concept to create a &#8220;framework&#8221; that requires as little tool-specific implementations as possible.  The framework does much of the heavy lifting with integrating the data into MantisBT, and delegates only the tasks to extension plugins that require detailed information about the source control tool being integrated.</p>
<p>Much of this design is a direct extension of the plugin system in MantisBT, which I also created using Inversion of Control, and uses its own set of events to handle the delegation of tasks wherever necessary.  This allows anyone to create an extension plugin that hooks into this framework and implement the integration for any source control tool, without needing to know much about how the framework integrates within MantisBT.</p>
<p><strong>Data Modelling</strong></p>
<p>For the actual data modelling, I decided upon three major data structures, and one ancillary structure.  Each structure is given a simple object-oriented API to work with.</p>
<p>The root of the data model is the <em>Repository</em> object, which contains information on the source control repository itself, such as its name, access URL, and &#8220;type&#8221;.  The type is basically a mapping to a specific extension plugin that knows how to retrieve, store, and interpret the data appropriately; examples of the type include &#8220;github&#8221; provided by the SourceGitHub plugin, and &#8220;websvn&#8221; provided by the SourceWebSVN plugin.  Each repository also contains a dictionary of arbitrary information that can be used as storage for any tool-specific data; for the GitHub integration, this extra information includes the GitHub user containing the project repository.</p>
<p>Each repository contains a set of <em>Changeset</em> objects, which naturally contains data for each changeset in the repository history.  Each changeset can have a revision string, a branch name, author information, timestamp, commit message, and a parent revision string.  Most of this is completely optional, meant only for use with tools that support that type of data.  For instance, the changeset revision has no meaning when used with a tool like CVS or SCCS, which only tracks revisions at the file level.  </p>
<p>Note that I also decided, for the sake of simplicity, to only track a single parent revision for each changeset, even though some tools may have multiple parents for some changesets (such as merge commits in Git).  This does throw away a small bit of data, but was done for the sake of maintaining a more simplistic data structure.  Give me a good enough argument, and maybe I&#8217;ll change my mind.  <img src='http://leetcode.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>For each changeset, there may be a set of <em>File</em> objects; these represent any files that have been added, modified, or removed from the repository in that changeset (or potentially any other action you can imagine).  These objects track the filename and/or path, the action, and also track a separate revision string from the changeset object.  This specifically enables usage with source control tools such as CVS that track file revisions.  Note that this object does *not* contain any other information about the file, such as the content or diff, as per my initial decision to keep things simple; the repository itself keeps this information, and for the most part, it&#8217;s unnecessary information for a bugtracker to handle.</p>
<p>Lastly, we come to the one ancillary data model, but arguably the one that is most important to the whole point of this framework.  For each changeset, there is a set of <em>Bug</em> relationships, that only exist to tie source control changesets to issues in the bugtracker.  It also the simplest data in the system, consisting of just a bug ID.</p>
<p>Roughly following the data models described above, are a set of classes defined in Source.API.php (<em>SourceRepo</em>, <em>SourceChangeset</em>, and <em>SourceFile</em>) which contain a set of public variables for the primary data, and static or public methods for simplifying the process of loading, saving, and manipulating groups of objects.  It should be rather straightforward to pick it up based on the information above and the comments in the code (IMHO).</p>
<p><strong>Framework Events</strong></p>
<p>Utilizing the event-based plugin system, the source control integration defines a set of events that delegate tool-specific tasks to appropriate extension plugins, such as viewing changeset information and gathering changeset data from the source control tool itself.</p>
<p>The first event is <em>GET_TYPES</em>, which allows extension plugins to &#8220;register&#8221; themselves with the integration framework, so that it knows what repository types are supported.  </p>
<p>The next set delegates the display of certain information: <em>SHOW_TYPE</em> covers the output of an extension plugin&#8217;s repository type, <em>SHOW_CHANGESET</em> allows manipulation of the changeset string, including how the branch and revision information is displayed, and <em>SHOW_FILE</em> allows the plugin to modify how files associated with a changeset are displayed, including action and revision information.</p>
<p>Another set delegates the URL links for data when displayed: <em>URL_REPO</em> for the URL to the main page of the repository browser, <em>URL_CHANGESET</em> for a link to a page in the browser for changeset, <em>URL_FILE</em> for a link to the entire contents of files in a given changeset, and <em>URL_FILE_DIFF</em> for a link to the diff output of files from a given changeset.</p>
<p>To handle repository type-specific data, two events allow extension plugins to hook their own form elements: <em>UPDATE_REPO_FORM</em> for displaying the form elements, and <em>UPDATE_REPO</em> for retrieving the form data and storing it in the repository object.</p>
<p>The last set of events allow extension plugins to gather data from the repository itself and create data objects and return them to the system: <em>PRECOMMIT</em> to analyze the incoming data from a repository&#8217;s post-commit hook to determine what repository type the data is for, <em>COMMIT</em> to interpret the data and generate objects for an incoming group of changesets, <em>IMPORT_LATEST</em> to pull the latest data from the repository without requiring a post-commit hook, and <em>IMPORT_FULL</em> to wipe and completely re-import changeset data from the repository.</p>
<p><a name="implementation"></a><strong>Implementing an Extension Plugin</strong></p>
<p>So how does this design come together when creating an extension plugin to integrate a new source control tool?  Well, it&#8217;s actually not that complicated; most of the design I discussed in the above sections helps make this portion of the process much simpler and easier to implement.  It even goes so far as to give you an initial head start when creating a new extension plugin, with an abstract class to inherit from with most of the plumbing already taken care of for you.</p>
<p>I&#8217;m going to cover a lot of this topic using a fake version control tool (&#8220;Open Sauce&#8221;) as an example; for almost everything, you&#8217;ll need to substitute code specific to the tool you&#8217;re integrating with Mantis.  You may also be interested in reading through the <a href="http://git.mantisforge.org/w/source-integration.git?a=blob;f=SourceGithub/SourceGithub.php;h=c10d4f56fe96ffbef8965697dd8236a2420443a5;hb=HEAD">SourceGithub</a> and <a href="http://git.mantisforge.org/w/source-integration.git?a=blob;f=SourceWebSVN/SourceWebSVN.php;h=3f1818d0621d4271048aad98ab59be1c74cee0f2;hb=HEAD">SourceWebSVN</a> plugins as &#8220;real world&#8221; examples.  Onwards.</p>
<p>Naturally, your extension plugin will still need to be a valid Mantis plugin, so let&#8217;s start there.  You&#8217;ll need to create a new plugin (see the <a href="http://docs.mantisbt.org/master/en/developers/">MantisBT documentation</a> for this), and the plugin will need to extend the <a href="http://git.mantisforge.org/w/source-integration.git?a=blob;f=Source/MantisSourcePlugin.class.php;h=950ffb086b2f8fb08d4c15e0a0b622c152fe9e6b;hb=HEAD">MantisSourcePlugin</a> class, which is what provides you with the plumbing I mentioned above, such as hooking the framework events, and defining an abstract API for you to implement.  For a rough example of the base plugin declaration:</p>
<pre><code>
&lt;?php
class SourceOpenSauce extends MantisSourcePlugin {
  function register() {
    $this-&gt;name = 'Open Sauce Integration';
    $this-&gt;version = 'One Point Oh';

    $this-&gt;requires = array(
      'MantisCore' =&gt; '1.2.0',
      'Source' =&gt; '0.13',
    );
  }
}

</code></pre>
<p>So that&#8217;s a decent start, but now we&#8217;ll need to start filling in all the pieces of the MantisSourcePlugin interface.  The interface methods each map to an event defined by the main Source Integration framework, and allow your plugin to take control whenever tool-specific details are needed.</p>
<p><strong>Note: for most of these methods, you will need to check that the repository &#8220;type&#8221; is the one your plugin has registered, so that it does not try to handle the wrong repositories.</strong></p>
<p>Let&#8217;s register our repository type and tell the framework how to display it; this could benefit from using internationalized language strings, but that&#8217;s beyond the topic scope:</p>
<pre><code>
  function get_types( $p_event ) {
    return array( 'opensauce' =&gt; 'Open Sauce' );
  }

  function show_type( $p_event, $p_type ) {
    if ( $p_type == 'opensauce' ) {
      return 'Open Sauce';
    }
  }

</code></pre>
<p>So now we can tell the framework how we want changesets and file entries to be displayed; for the purpose of example, we&#8217;ll assume that both changesets and files have revision numbers:</p>
<pre><code>
  function show_changeset( $p_event, $p_repo, $p_changeset ) {
    if ( $p_repo-&gt;type != 'opensauce' ) {
      return;
    }

    return "$p_changeset-&gt;branch #$p_changeset-&gt;revision";
  }

  function show_file( $p_event, $p_repo, $p_changeset, $p_file ) {
    if ( $p_repo-&gt;type != 'opensauce' ) {
      return;
    }

    return "$p_file-&gt;action - $p_file-&gt;filename #$p_changeset-&gt;revision";
  }

</code></pre>
<p>Next up is defining how source control data links to the made-up &#8220;Open Sauce Webview&#8221; application.  Note that we are getting the viewer&#8217;s base URL from the repo object, which we&#8217;ll cover later:</p>
<pre><code>
  function url_repo( $p_event, $p_repo, $p_changeset=null ) {
    if ( $p_repo-&gt;type != 'opensauce' ) {
      return;
    }

    $t_url = $p_repo-&gt;info['viewer_url'];

    if ( !is_null( $p_changeset ) ) {
      $t_rev = $p_changeset-&gt;revision;
    } else {
      $t_rev = false;
    }

    return ( $t_rev ? "$t_url/view/$t_rev" : "$t_url/view" );
  }

  function url_changeset( $p_event, $p_repo, $p_changeset ) {
    ...
  }
  function url_file( $p_event, $p_repo, $p_changeset, $p_file ) {
    ...
  }
  function url_diff( $p_event, $p_repo, $p_changeset, $p_file ) {
    ...
  }

</code></pre>
<p>Next up is hooking some form elements onto the repository management page, so that the MantisBT administrator can set the base URL for the &#8220;Open Sauce Webviewer&#8221;:</p>
<pre><code>
  function update_repo_form( $p_event, $p_repo ) {
    if ( $p_repo-&gt;type != 'opensauce' ) {
      return;
    }

    $t_url = $p_repo-&gt;['viewer_url'];

    echo '&lt;tr ', helper_alternate_class(), '&gt;&lt;td class="category"&gt;',
      'Open Sauce Viewer URL&lt;/td&gt;&lt;td&gt;',
      '&lt;input name="viewer_url" value="',
      string_attribute( $t_url ), '"/&gt;&lt;/td&gt;&lt;/tr&gt;';
  }

  function update_repo( $p_event, $p_repo ) {
    if ( $p_repo-&gt;type != 'opensauce' ) {
      return;
    }

    $p_repo-&gt;info['viewer_url'] = gpc_get_string( 'viewer_url', '' );

    return $p_repo;
  }
</pre>
<p></code></p>
<p>The last piece of the puzzle is the biggest: gathering commit data from the repository and converting it into the generalized data structures provided by the framework.  Here, we'll only cover a skeleton of importing the latest commits; you'll need to extrapolate on your own to cover the other methods of bringing in data:</p>
<pre><code>
  function import_latest( $p_event, $p_repo ) {
    if ( $p_repo-&gt;type != 'opensauce' ) {
      return;
    }

    # randomly make a query to get the latest commit data; our fake
    # viewer "returns" a JSON-encoded payload with commit info...
    $t_data = json_url( $p_repo-&gt;info['viewer_url'] . '/latest' );

    # prepare to aggregate the data
    $t_changesets = array();

    # go through all the changesets
    foreach( $t_data-&gt;commits as $t_commit ) {
      $t_changeset = new SourceChangeset(
        $p_repo-&gt;id,
        $t_commit-&gt;revision,
        $t_commit-&gt;branch,
        $t_commit-&gt;timestamp,
        $t_commit-&gt;author,
        $t_commit-&gt;message
      );

      # go through all the changeset's files
      foreach( $t_commit-&gt;files as $t_file ) {
        $t_file = new SourceFile(
          0, #no changeset id yet
          $t_file-&gt;revision,
          $t_file-&gt;filename,
          $t_file-&gt;action
        );

        #attach the file to the changeset
        $t_changeset-&gt;files[] = $t_file;
      }

      # parse any referenced bugs from the commit message
      $t_changeset-&gt;bugs = Source_Parse_Buglinks( $t_changeset-&gt;message );
      $t_changeset-&gt;save();

      # keep track of all the changesets imported
      $t_changesets[] = $t_changeset;
    }

    # return the set of changesets imported
    return $t_changesets;
  }
</pre>
<p></code></p>
<p><strong>Wrap It Up</strong></p>
<p>At this point, we now have a basic extension plugin that can pull data from the source control tool and interact with the framework to display the data appropriately.  You should now be able to take this to the next level, and create an integration plugin for any source control tool you can imagine.  I'd personally love to see support for Mercurial and Bazaar in the near future.</p>
<p>And here's the kicker: if you are willing to release your integration plugin under an open source license (such as BSD or GPL), I'll gladly include it in my main <a href="http://git.mantisforge.org/w/source-integration.git">source-integration.git</a> repository along with the framework, as I do for the existing Git and SVN plugins.  You'll benefit from any community bug fixes and feature updates, and the community will benefit from having all the plugins in a single location, easy to find and install.  I'll even give you developer access to the repository on MantisForge.org in case you need to update it in the future.</p>
<p>Cheers, and happy integrating!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/leetcode?a=_h3pX53THag:KRZcnLP6jpI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=_h3pX53THag:KRZcnLP6jpI:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=_h3pX53THag:KRZcnLP6jpI:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/leetcode?i=_h3pX53THag:KRZcnLP6jpI:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=_h3pX53THag:KRZcnLP6jpI:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/leetcode?d=dnMXMwOfBR0" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://leetcode.net/blog/2009/03/integrating-source-control-with-mantisbt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://leetcode.net/blog/2009/03/integrating-source-control-with-mantisbt/</feedburner:origLink></item>
		<item>
		<title>Classic Wit</title>
		<link>http://feedproxy.google.com/~r/leetcode/~3/2MjqBY-d_fg/</link>
		<comments>http://leetcode.net/blog/2009/02/classic-wit/#comments</comments>
		<pubDate>Sat, 28 Feb 2009 01:50:46 +0000</pubDate>
		<dc:creator>John Reese</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[comic]]></category>
		<category><![CDATA[explosm]]></category>
		<category><![CDATA[humor]]></category>

		<guid isPermaLink="false">http://leetcode.net/blog/?p=126</guid>
		<description><![CDATA[Thank you Explosm, you&#8217;ve just made my day!  
]]></description>
			<content:encoded><![CDATA[<div id="attachment_127" class="wp-caption aligncenter" style="width: 310px"><a href="http://leetcode.net/blog/files/2009/02/comicbatteriescamera.png"><img src="http://leetcode.net/blog/files/2009/02/comicbatteriescamera-300x91.png" alt="This is how I like to answer these types of questions." width="300" height="91" class="size-medium wp-image-127" /></a><p class="wp-caption-text">This is how I like to answer these types of questions.</p></div>
<p>Thank you <a href="http://www.explosm.net">Explosm</a>, you&#8217;ve just made my day! <img src='http://leetcode.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/leetcode?a=2MjqBY-d_fg:3C_FUPubVyA:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=2MjqBY-d_fg:3C_FUPubVyA:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=2MjqBY-d_fg:3C_FUPubVyA:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/leetcode?i=2MjqBY-d_fg:3C_FUPubVyA:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=2MjqBY-d_fg:3C_FUPubVyA:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/leetcode?d=dnMXMwOfBR0" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://leetcode.net/blog/2009/02/classic-wit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://leetcode.net/blog/2009/02/classic-wit/</feedburner:origLink></item>
		<item>
		<title>Integrating Git and SVN with the Mantis Bug Tracker</title>
		<link>http://feedproxy.google.com/~r/leetcode/~3/mVkg-2mTEAo/</link>
		<comments>http://leetcode.net/blog/2009/01/integrating-git-svn-with-mantisbt/#comments</comments>
		<pubDate>Thu, 08 Jan 2009 00:06:36 +0000</pubDate>
		<dc:creator>John Reese</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[mantisbt]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[source integration]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://leetcode.net/blog/?p=86</guid>
		<description><![CDATA[With the ongoing work towards a 1.2 release, the Mantis Bug Tracker features a brand new plugin and event system, which will allow users to implement entirely new features for MantisBT without ever needing to touch any of the core codebase.  It&#8217;s a very extensible system, and allows plugin authors to implement only what [...]]]></description>
			<content:encoded><![CDATA[<p>With the ongoing work towards a 1.2 release, the <a href="http://www.mantisbt.org">Mantis Bug Tracker</a> features a brand new plugin and event system, which will allow users to implement entirely new features for MantisBT without ever needing to touch any of the core codebase.  It&#8217;s a very extensible system, and allows plugin authors to implement only what they need, while still allowing advanced plugins as much flexibility as possible.  Plugins can be as small as a single file with 20 lines of code, or as large as entire hierarchies of files, pages, with their own API&#8217;s.</p>
<p>As the core developer of the new plugin system, I have been working on a variety of plugins. In particular, I have created a vastly improved method of integrating source control repositories within MantisBT.  The plugin package is named, aptly enough, Source Integration, and implements a generic framework that will allow integration with multiple repositories, each potentially using any source control systems available, simply by creating an extension plugin for each new tool.  Currently, I have implemented integration packages for both Git and Subversion, my two source control tools of choice.</p>
<p>The Source Integration package tracks repository information based on a series of changesets, each of which may have a list of affected files.  The data representation is generic enough to cover version control concepts used by all types of tools, from the ubiquitous CVS and Subversion, to modern distributed tools like Git and Hg.  However, the system takes the stance of implementing as few details as possible, so it relies on existing repository-viewing tools for tasks such as viewing commit diffs, file contents, tree browsing, etc.  Extension plugins handle translating tool-specific information, like history logs or checkin data, into the generalized data objects used by the framework.  Extensions also generate URL&#8217;s for viewing files and diffs, but everything else is handled automatically by the core framework.</p>
<p>The true benefit of the Source Integration package lies in the amount of repository integration that it implements within MantisBT.  When importing changesets from your repository, Source looks at the commit message of each changeset for references to bug numbers in your tracker, and sets up links in the database for any bugs mentioned.  When viewing bugs mentioned in commit messages, a new section is displayed after the bugnotes called &#8220;Related Changesets&#8221;, giving a list of linked changes, including information about the changeset, such as the branch, author, timestamp, and a list of changed files.</p>
<p><span id="more-86"></span></p>
<p>Since a picture is worth a thousand words, and I&#8217;m not that great of a writer, few screenshots for your viewing pleasure:</p>
<div id="attachment_103" class="wp-caption aligncenter" style="width: 310px"><a href="http://leetcode.net/blog/files/2009/01/si-repos.png"><img src="http://leetcode.net/blog/files/2009/01/si-repos-300x59.png" alt="List of integrated repositories." width="300" height="59" class="size-medium wp-image-103" /></a><p class="wp-caption-text">List of integrated repositories.</p></div><br />
<div id="attachment_111" class="wp-caption aligncenter" style="width: 310px"><a href="http://leetcode.net/blog/files/2009/01/si-search.png"><img src="http://leetcode.net/blog/files/2009/01/si-search-300x171.png" alt="Search for imported changesets that match a set of filter criterion." width="300" height="171" class="size-medium wp-image-111" /></a><p class="wp-caption-text">Search for imported changesets that match a set of filter criterion.</p></div><br />
<div id="attachment_110" class="wp-caption aligncenter" style="width: 310px"><a href="http://leetcode.net/blog/files/2009/01/si-browse.png"><img src="http://leetcode.net/blog/files/2009/01/si-browse-300x80.png" alt="List of changesets for a repository or search result." width="300" height="80" class="size-medium wp-image-110" /></a><p class="wp-caption-text">List of changesets for a repository or search result.</p></div><br />
<div id="attachment_99" class="wp-caption aligncenter" style="width: 310px"><a href="http://leetcode.net/blog/files/2009/01/si-related.png"><img src="http://leetcode.net/blog/files/2009/01/si-related-300x68.png" alt="List of repository changesets attached to the current issue." width="300" height="68" class="size-medium wp-image-99" /></a><p class="wp-caption-text">List of repository changesets attached to the current issue.</p></div><br />
<div id="attachment_100" class="wp-caption aligncenter" style="width: 310px"><a href="http://leetcode.net/blog/files/2009/01/si-details.png"><img src="http://leetcode.net/blog/files/2009/01/si-details-300x93.png" alt="Detailed information about the selected changeset." width="300" height="93" class="size-medium wp-image-100" /></a><p class="wp-caption-text">Detailed information about the selected changeset.</p></div>
<p><strong>Installation, Configuration, and Integration</strong></p>
<p>So how do you get this source control goodness in your own MantisBT installation?  Well, first, you need to make sure you meet a few basic requirements:</p>
<ul>
<li>a development snapshot of MantisBT version 1.2.x &#8211; either download a <a href="http://www.mantisbt.org/builds">nightly build</a>, or a snapshot from the <a href="http://git.mantisbt.org">MantisBT Gitweb</a> &#8211; the old 1.2.0a2 release tarball will not work.</li>
<li>to integrate Git, you need EITHER</li>
<ul>
<li>a public GitHub repository, OR</li>
<li>a Gitweb installation (repo.or.cz works well)</li>
</ul>
<li>to integrate Subversion, you need EITHER</li>
<ul>
<li>a public SourceForge repository, OR</li>
<li>a WebSVN installation to view diffs and/or file contents</li>
</ul>
</ul>
<p><em>Note that the Source Integration package relies on external viewers for Git integration, as it does yet support local repository access.</em></p>
<p>Assuming that you meet the above requirements, you can begin the installation and integration process.  The latest version of the plugins can be found at the <a href="http://git.mantisforge.org">MantisForge Gitweb</a> by clicking on the &#8217;snapshot&#8217; link next to each repository.</p>
<ol>
<li>Install or upgrade to the latest Mantis 1.2.x (remember, the 1.2.0a2 release will not work)</li>
<li>Install the Meta plugin</li>
<li>Install the Source plugin</li>
<li>Install the appropriate Source extension plugin or plugins:</li>
<ul>
<li>SourceGithub for GitHub</li>
<li>SourceGitweb for Gitweb and repo.or.cz</li>
<li>SourceSFSVN for SourceForge</li>
<li>SourceWebSVN for WebSVN</li>
</ul>
<div id="attachment_102" class="wp-caption aligncenter" style="width: 310px"><a href="http://leetcode.net/blog/files/2009/01/si-plugin.png"><img src="http://leetcode.net/blog/files/2009/01/si-plugin-300x143.png" alt="Installed plugins." width="300" height="143" class="size-medium wp-image-102" /></a><p class="wp-caption-text">Installed plugins.</p></div>
<li>You&#8217;ll now have a new link in your MantisBT menu, named &#8220;Repositories&#8221;; click on it now</li>
<div id="attachment_103" class="wp-caption aligncenter" style="width: 310px"><a href="http://leetcode.net/blog/files/2009/01/si-repos.png"><img src="http://leetcode.net/blog/files/2009/01/si-repos-300x59.png" alt="List of integrated repositories." width="300" height="59" class="size-medium wp-image-103" /></a><p class="wp-caption-text">List of integrated repositories.</p></div>
<li>Optional:  Click on the &#8220;Configuration&#8221; link to change the regular expressions used to match bug references in commit messages to match the style used in your project.  By default, it will match text like &#8220;issue #xxx&#8221; or &#8220;bugs #xxx, #yyy&#8221;, etc. Note that the first regex finds groups of references, and the second regex matches the actual issue numbers.</li>
<div id="attachment_105" class="wp-caption aligncenter" style="width: 310px"><a href="http://leetcode.net/blog/files/2009/01/si-regexes.png"><img src="http://leetcode.net/blog/files/2009/01/si-regexes-300x46.png" alt="Default regular expressions for extracting commit message bug references." width="300" height="46" class="size-medium wp-image-105" /></a><p class="wp-caption-text">Default regular expressions for extracting commit message bug references.</p></div>
<li>Fill in the &#8220;Create Repository&#8221; form, with an appropriate name, and selecting the appropriate repository type from the list of installed extensions</li>
<div id="attachment_106" class="wp-caption aligncenter" style="width: 310px"><a href="http://leetcode.net/blog/files/2009/01/si-create.png"><img src="http://leetcode.net/blog/files/2009/01/si-create-300x80.png" alt="Form used to create a new repository integration." width="300" height="80" class="size-medium wp-image-106" /></a><p class="wp-caption-text">Form used to create a new repository integration.</p></div>
<li>You&#8217;ll be taken to a second form with a new set of options based on the repository type you&#8217;ve chosen.  Fill in the appropriate information, and click &#8220;Update Repository&#8221; to save the information</li>
<div id="attachment_107" class="wp-caption aligncenter" style="width: 310px"><a href="http://leetcode.net/blog/files/2009/01/si-update.png"><img src="http://leetcode.net/blog/files/2009/01/si-update-300x137.png" alt="Form for updating specific repository information." width="300" height="137" class="size-medium wp-image-107" /></a><p class="wp-caption-text">Form for updating specific repository information.</p></div>
<li>You should be ready to begin the data import process.  Click &#8220;Import Latest Data&#8221; to begin.  <em>Note that for large repositories, you may need to repeat this step, due to limits or timeouts, until it has finished importing the entire repository.</em></li>
</ol>
<p>At this point, you should have your repository imported and integrated with your MantisBT installation, but you still need to do some further effort to make sure MantisBT stays up to date with the latest changes from the repository:</p>
<ul>
<li>For GitHub, enable remote checkins for address &#8220;65.74.0.0&#8243; to allow GitHub&#8217;s servers access, and point your repository&#8217;s post-receive URL to &#8220;http://yoururl.xyz/mantisbt/plugin.php?page=Source/checkin&#8221;</li>
<div id="attachment_108" class="wp-caption aligncenter" style="width: 310px"><a href="http://leetcode.net/blog/files/2009/01/si-remote-checkin.png"><img src="http://leetcode.net/blog/files/2009/01/si-remote-checkin-300x75.png" alt="Configuring remote checkin options." width="300" height="75" class="size-medium wp-image-108" /></a><p class="wp-caption-text">Configuring remote checkin options.</p></div>
<li>For Gitweb, SourceForge, or WebSVN integration, find your repository&#8217;s ID, and setup a cronjob (or something equivalent) to run &#8220;curl http://yoururl.xyz/mantisbt/plugin.php?page=Source/repo_import_latest&amp;id=XX&#8221;</li>
<li>For WebSVN, you may optionally use the included post-commit hook found in the plugin directory.</li>
</ul>
<p>So now you should be done setting up integration between your repository and MantisBT.  Congratulations!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/leetcode?a=mVkg-2mTEAo:IZGxy12S7qw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=mVkg-2mTEAo:IZGxy12S7qw:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/leetcode?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=mVkg-2mTEAo:IZGxy12S7qw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/leetcode?i=mVkg-2mTEAo:IZGxy12S7qw:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/leetcode?a=mVkg-2mTEAo:IZGxy12S7qw:dnMXMwOfBR0"><img src="http://feeds.feedburner.com/~ff/leetcode?d=dnMXMwOfBR0" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://leetcode.net/blog/2009/01/integrating-git-svn-with-mantisbt/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://leetcode.net/blog/2009/01/integrating-git-svn-with-mantisbt/</feedburner:origLink></item>
	</channel>
</rss>
