<?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>Doing better &#187; Tools</title>
	<atom:link href="http://www.longacre-scm.com/blog/index.php/category/tools/feed" rel="self" type="application/rss+xml" />
	<link>http://www.longacre-scm.com/blog</link>
	<description>Opinions on CM, software development, and process automation from Longacre.</description>
	<lastBuildDate>Wed, 15 Dec 2010 04:21:35 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>You&apos;re doing it wrong:  GNot Invented Here</title>
		<link>http://www.longacre-scm.com/blog/index.php/2010/12/youre-doing-it-wrong-gnot-invented-here</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2010/12/youre-doing-it-wrong-gnot-invented-here#comments</comments>
		<pubDate>Wed, 15 Dec 2010 03:11:37 +0000</pubDate>
		<dc:creator>Austin Hastings</dc:creator>
				<category><![CDATA[Practice]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[gnu]]></category>
		<category><![CDATA[make]]></category>
		<category><![CDATA[sunos]]></category>
		<category><![CDATA[syntax]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/index.php/2010/12/youre-doing-it-wrong-gnot-invented-here</guid>
		<description><![CDATA[A while ago, I was working at a company in South Florida. And I happened to be reading the manual for their build tool, which was called &#8216;make&#8217;, and it mentioned a special syntax available for cases where more than one output file could be built by a single application of a rule.
The example most [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago, I was working at a company in South Florida. And I happened to be reading the manual for their build tool, which was called &#8216;make&#8217;, and it mentioned a special syntax available for cases where more than one output file could be built by a single application of a rule.</p>
<p>The example most programmers will understand today is with a yacc-like tool (or lex, for that matter):</p>
<p><tt>y.tab.c y.tab.h : whatever.yacc</tt></p>
<p><tt> &#160; &#160; &#160; &#160;$(YACC) $(YFLAGS) $&lt;</tt></p>
<p>If you&#8217;ve ever used yacc, or the GNU equivalent, <i>bison,</i> or any other code generator, you&#8217;ll understand the pattern. There&#8217;s a set of input files, usually either just one, or one plus some other files generated by a lexer generator. And the input files are read by the code generator tool, and the code generator tool produces a bunch of different output files <i>all at the same time.</i></p>
<p><span id="more-110"></span></p>
<p>The syntax that this &#8216;make&#8217; tool I was reading about used to indicate this was a plus sign:</p>
<p><tt>y.tab.c + y.tab.h : whatever.yacc</tt></p>
<p>And that plus sign was enough to let the &#8216;make&#8217; tool know what was going on with the simultaneous generation of both files.</p>
<p>The company in question was not a client. It was my second serious job after college. I started working there in the (late) 1980&#8217;s. And the &#8216;make&#8217; tool in question was <i>make,</i> as provided with SunOS 3 and 4. (<i>Not </i>Solaris. That came later.)</p>
<h2>Yeah, so?</h2>
<p>I told that story for a reason: to point out that this somewhat niche-market problem has been solved, in a widely-available system, using a trivial syntax enhancement. The solution has been around for more than 20 years. And GNU make still gets it wrong.</p>
<p>The latest GNU make version provides a feature that almost solves the same problem. Except that it doesn&#8217;t. And that &#8220;feature&#8221; is a hack.</p>
<p>It&#8217;s documented in the manual, but not mentioned in a header in the contents, so you have to just know, or have someone give you a link. Google won&#8217;t help you find it. (It&#8217;s <a href="http://www.gnu.org/software/make/manual/make.html#Pattern-Examples">here.</a>)</p>
<p>And of course the syntax used for the GNU make not-quite-but-maybe-almost hack is: two targets separated by spaces.</p>
<p>That&#8217;s right, the GNU version looks like:</p>
<p><tt>a b : input</tt></p>
<p>Which you might find confusing, because the GNU make syntax for two targets that <i>do not </i>all get regenerated at the same time, but instead require the recipe to be executed once for each output looks like:</p>
<p><tt>a b : input</tt></p>
<p>See the difference? Of course not, because at this level of abstraction there is no difference. The rules look exactly the same.</p>
<p>If you don&#8217;t know the secret &#8211; which is that the run-once or run-multiple-times behavior depends on whether the rule is a <i>pattern rule </i>or not &#8211; then you&#8217;re SOL, because there&#8217;s no visible indicator.</p>
<p>It&#8217;s worth pointing out that there&#8217;s a method to the madness of the GNU make weenies. The justification, if I were dumb enough to ask for one, would be something like this: the <i>only time </i>this kind of thing ever arises (in C) is when you&#8217;re using yacc or rpcgen. (Rpcgen is the reason the Sun guys added the rule, I&#8217;m fairly sure.) And yacc/rpcgen always get used in such a way that the filenames always have a common root. So making this incredibly lame hack makes total sense, because nobody ever does this, but if they did they&#8217;d be happy it was this way.</p>
<h2>Bah, humbug!</h2>
<p>I don&#8217;t do a lot of C programming any more. There are other languages that are generally much more suited to what I&#8217;m trying to do. Some of those languages are &#8220;static&#8221; languages, like C++, Java, and D. And some of those languages are &#8220;dynamic&#8221; languages, like sh, perl, and scheme.</p>
<p>But in <i>both </i>camps, you&#8217;ll find languages that use directory names and file names to reflect the classes, modules, packages, units, or whatever-it&#8217;s-called defined inside them.</p>
<p>This is important because if I&#8217;m going to generate code, I want to be free to generate code using file and directory names that are meaningful to, and constrained in, the context of the programming language I&#8217;m actually using.</p>
<p>I really, really, really don&#8217;t want to have to conform to a naming convention inspired by a tool I&#8217;m not using in a language I don&#8217;t care about that is the basis for a syntax hack in make!</p>
<p>Ultimately, I think this is an example of a couple of things. First, that the GNU make guys are suffering a vision problem because they&#8217;re focused on building a core set of applications, using a small set of languages.</p>
<p>Second, I think they&#8217;re afraid to admit that other people, when faced with a similar set of problems as them, have come up with useful solutions. Back when GNU make got started, SunOS was the dominant Unix. And the guys at Sun were doing a fine job of carrying forward the tool suite. But heavens! For GNU to copy a useful feature of a popular tool would be to admit that we aren&#8217;t the sole source of clever ideas. Oh, noes!</p>
<p>Thus, we have the open source curse: Gnot Invented Here syndrome. </p>
<p>And also thus &#8211; more of a pain in my tuchus, thus &#8211; we have a version of GNU make that forces me to jump through a bunch of hoops to accomplish something that I could have done in <i>two lines </i>back in 1988. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2010/12/youre-doing-it-wrong-gnot-invented-here/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Crossing Over</title>
		<link>http://www.longacre-scm.com/blog/index.php/2010/10/crossing-over</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2010/10/crossing-over#comments</comments>
		<pubDate>Mon, 18 Oct 2010 05:08:48 +0000</pubDate>
		<dc:creator>Austin Hastings</dc:creator>
				<category><![CDATA[Off-topic]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/?p=106</guid>
		<description><![CDATA[Recently I&#8217;ve been doing a lot of work at a very low level. Not &#8220;should I use a primitive type or a class&#8221; low, but more like &#8220;how many cycles will this take?&#8221; low.
Today I was chatting with some folks on IRC, and the subject of binary searching came up. Now, I don&#8217;t know if [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I&#8217;ve been doing a lot of work at a very low level. Not &#8220;should I use a primitive type or a class&#8221; low, but more like &#8220;how many cycles will this take?&#8221; low.</p>
<p>Today I was chatting with some folks on IRC, and the subject of binary searching came up. Now, I don&#8217;t know if this is going to surprise you, but in the last few years there has been some &#8220;movement&#8221; in the performance arena as far as thing we just &#8220;know&#8221;. It turns out, for example, that the &#8220;qsort&#8221; function isn&#8217;t the fastest horse in the race any more. And it turns out that <em>bsearch</em> is getting a little long in the tooth, too.</p>
<p><em>&#8220;Mon dieu! How can this be?,&#8221;</em> you ask. Well, it&#8217;s templates.</p>
<p><span id="more-106"></span></p>
<p>The C++ guys apparently listened to Philip Greenspun, and decided that the way to better performance was to build a lisp interpreter into the compiler. That lisp interpreter is called &#8220;template metaprogramming&#8221; (TMP), and the languages like C++ that support TMP can use it in some surprising ways.</p>
<p>The key thing to realize here is that there&#8217;s a trade-off involved. The old C standard library functions are &#8211; no question &#8211; about as fast as they can be. But the TMP guys came to the realization that the library functions were just that: functions. And so calling qsort or bsearch means passing in a callback function that takes a couple of pointers and compares whatever they point to.</p>
<p>This is very generic, but it comes at a fairly high cost in terms of run-time. Calling a function to make a comparison is a huge performance lose, especially on a fast CPU with a good sized cache. All that stuff you&#8217;ve heard about cache misses and branch prediction and what-not? Well, it becomes relevant if you have to call through a pointer to the compare function, and it gets doubly relevant if your compare function turns around and calls some other function &#8211; like <em>strcmp.</em></p>
<p>So the template version of all this uses the same logic as the hoary old C standard library chestnuts, but it uses templates to dynamically build a special-purpose function for doing just exactly the Quicksort or binary search that you need to do right now.</p>
<p>The obvious down side? Each place where you invoke qsort or bsearch generates a different function. Big code bloat here, folks.</p>
<p>The up side? Breaking through the &#8220;call a function to compare two items&#8221; barrier. For small types &#8211; like int, float, etc. &#8211; and for &#8220;fully equipped&#8221; types like strings, there will be enough code laying around that the compiler can in-line some, if not most or all, of the comparison logic. Comparing strings will always require looping through arrays. But comparing two structs? That&#8217;s easy to inline. Comparing two ints? Please!</p>
<h2>Crossing Over</h2>
<p>So with this in mind, I set out to find the &#8220;cross over&#8221; point. Put simply, where do the performance curves of linear seach (lsearch) and binary search (bsearch) cross? That is, for N = how many items does it make more sense to use a binary search than to iterate?</p>
<p>Now, here&#8217;s what we know about bsearch: it has performance characteristic <em>O( log n ).</em>  And we know that lsearch has performance characteristic <em>O( n ).</em> But what does that mean, exactly?</p>
<p>First, every routine has some overhead. When a subroutine is called, you push some information on the stack, initialize some variables, and then do your work. And later, you takes stuff off the stack, free your resources, and return. That&#8217;s overhead.</p>
<p>Next, in the process of doing the actual work, you have to perform interim computations. For example, linear search basically requires some mechanism for iterating through the array you are searching. And that&#8217;s going to be a pointer or an integer or something. Updating that iterator is part of the structural cost of the algorithm. A bsearch algorithm typically involves computing (low + (high-low)/2). That&#8217;s the middle point for the search, and that&#8217;s a part of the structural cost.</p>
<p>Those structural costs can be high, sometimes. So saying that an O( log n ) function is faster than an O( n ) function automatically implies a caveat, <em>so long as n is big enough that the structural and overhead costs get washed out. </em>And that&#8217;s why I was curious about the cross-over number. Because with templates, the call-a-function-through-a-pointer structural cost is gone. And so my understanding of where the lines cross is no longer valid.</p>
<h2>Great! Another &#8216;D&#8217; in programming&#8230; </h2>
<p>The language in question isn&#8217;t C++, though. It&#8217;s D. Now, D is a lousy name for a programming language, just like C is. Because Google is not your friend if you&#8217;re searching for &#8220;D&#8221;. Nor is &#8220;file.d&#8221; going to be a win, either, because that&#8217;s the default name for dependency files in a lot of build systems. So D wasn&#8217;t the best possible choice of names, and it can be hard to find info about it. To save you some grief, have a look at http://www.digitalmars.com/d &#8211; that&#8217;s the &#8220;official&#8221; D site, if there is such a thing. (For myself, I&#8217;ve taken to using &#8220;PL/D&#8221; as an abbreviation.)</p>
<p>PL/D version 2.0 supports templates. So here&#8217;s bsearch, as a can-find type function:</p>
<pre>
bool bsearch( T, alias cmp = "a < b" )(T[ ] array, T key )
{
	int left = 0;
	int right = array.length;

	while( left + 1 < right ) {

		int middle = ( left + right ) / 2;
		T am = array[ middle ];

		if( binaryFun!( cmp )( key, am ) ) {

			right = middle;
		}
		else {

			left = middle;
		}
	}

	// return a[0] == key
	return ! binaryFun!( cmp )( key, array[ 0 ] )
		&#038;&#038; ! BinaryFun!( cmp )( array[ 0 ], key );
}
</pre>
<p>Now I know that this version doesn't do early exit. But it's a little more readable to folks who might be new to the whole template thing, especially with PL/D. One thing I like more about D than C++ is that templates are instantiated like foo!( T )( a, b ) instead of foo< T >( a, b ). If nothing else, it's more html friendly.<br />
I won't explain all the neat-o features of the language here - see the link above for that. I will point out that this version generates a binary function using "a < b" by default, and generates a direct call to that function in the comparisons. As a result of the direct (instead of indirect - through a pointer) function calls, the compiler can inline them, resulting in the comparison being made right in the function itself.<br />
The testbed was an array of randomly-generated integers. The driver code looked like this:</p>
<pre>
	// ========================
	Thread.sleep( 1 );
	timer.start();

	foreach (iter; 0 .. ITERATIONS )
		bsearch(a[], cast(int)(rand() % ELEMENTS));

	timer.stop();
	writefln( "Bsearch: %f usec (avg)", cast( float ) timer.microseconds / ITERATIONS );
	writefln( " .... Cycle: %f usec (avg)", ( timer.microseconds - overhead ) / ITERATIONS );

	// ========================
	Thread.sleep( 1 );
	timer.start();

	foreach (iter; 0 .. ITERATIONS ) {
		int key = rand() % ELEMENTS;
		csearch( &#038;key, &#038;a[ 0 ], ELEMENTS, int.sizeof, &#038;compare_ints );
	}

	timer.stop();
	writefln( "Csearch: %f usec (avg)", cast( float ) timer.microseconds / ITERATIONS );
	writefln( " .... Cycle: %f usec (avg)", ( timer.microseconds - overhead ) / ITERATIONS );
</pre>
<p>Where most things should be obvious, but I&#8217;ll point out that the Thread.sleep calls were for 100 nanoseconds each &#8211; just enough to give control back to Windows so it hopefully wouldn&#8217;t interrupt the loops. The &#8220;csearch&#8221; call in the second block is actually a call to the bsearch function in the C standard library &#8211; I created an alias for it since I already had a bsearch function.</p>
<p>Overall, for ELEMENTS = 1000, the cycle time for the template based bsearch was about 0.12 usec. The cycle time for the call-a-function C library version was about 0.165 usec. So for trivial comparisons, the template-based version gives a 25+% speed benefit &#8211; that&#8217;s why I was interested in running the tests!</p>
<p>Obviously, this number depends on the number of comparisons. For ELEMENTS = 100, you&#8217;re looking at log n = 7 instead of 10 comparisons &#8211; csearch should catch up a little bit. For ELEMENTS = 100,000, it would be 17 instead of 10 and presumably the template version would show even better performance.</p>
<h2>The Edge of Seventeen</h2>
<p>But that&#8217;s not why I started this. I wanted to know how well the template bsearch code would do against lsearch &#8211; linearly scanning the array. It seemed like a safe bet that 1,000 elements would be a win for the binary search&#8230;and it was. (<em>whew!</em>) But would the same be true for 100 elements? 10?</p>
<p>Well, for me, the number is 17. If ELEMENTS = 17, then lsearching the array (using a template based lsearch) is faster than bsearching the array (using a template based bsearch). (On the other hand, template based lsearch crosses over C-style bsearch at 61 items!)</p>
<p>Those performance numbers depend on a lot of things. Most importantly, they depend on the relative speed of your comparison code versus the structural code of the search function.</p>
<p>What does that mean? Well, take a look at the a program called git-bisect. This program is a shell script that uses a binary search to find a build failure. Bisect knows the list of changes that were made to your source code, so it can pull out a version, build it, test it, and decide whether the problem is in that version or elsewhere.</p>
<p>The issue, though, is that the &#8220;comparison function&#8221; involves pulling out your 30 million lines of code, running a build, and then running the test that identifies whether the bug is in this version or not. The build and test process takes so much longer than the &#8220;add two numbers and divide by two&#8221; of the binary search that it&#8217;s a no brainer &#8211; you&#8217;re almost always going to use the bsearch version.</p>
<p>But when the compare is a single CPU instruction, it&#8217;s a different story. In that case, the overhead of the bsearch pushes the crossover point far out past where it is in theory. If your compiler is smart enough, and when you&#8217;ve got enough memory to allow it to inline these kinds of functions&#8230;well, we have to draw a line somewhere.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2010/10/crossing-over/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Doxygen&#8217;s \test command with C++</title>
		<link>http://www.longacre-scm.com/blog/index.php/2010/08/using-doxygens-test-command-with-c</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2010/08/using-doxygens-test-command-with-c#comments</comments>
		<pubDate>Sat, 28 Aug 2010 21:19:39 +0000</pubDate>
		<dc:creator>Austin Hastings</dc:creator>
				<category><![CDATA[Off-topic]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/?p=95</guid>
		<description><![CDATA[I&#8217;m working on some C++ code that is documented using Doxygen. Nothing earth-shattering there.
But I&#8217;m doing unit testing, and writing unit tests. In this case, I&#8217;m using the boost C++ libraries. That means my tests don&#8217;t look like classes, the way they might look if I was using CppUnit or CxxUnit. Instead, they look like [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m working on some C++ code that is documented using <a href="http://www.doxygen.org">Doxygen.</a> Nothing earth-shattering there.</p>
<p>But I&#8217;m doing unit testing, and writing unit tests. In this case, I&#8217;m using the <a href="http://www.boost.org">boost C++ libraries.</a> That means my tests don&#8217;t look like classes, the way they might look if I was using CppUnit or CxxUnit. Instead, they look like macros:<br />
<code><br />
BOOST_AUTO_TEST_CASE( null_ctor ) {</p>
<p>	Arena &#038; sut = Simple::Arena();<br />
	BOOST_CHECK( sut.capacity() != 0 );<br />
}<br />
</code></p>
<p>The macro expansion is really quite clever, in a Lovecraftian &#8220;there are secrets man was not meant to know&#8221; fashion. And reading them has certainly improved my knowledge of C++. (But it also permanently lowered my SAN by a few points, I think.)</p>
<p>Anyway, Doxygen offers this command called <b>\test</b> that seems tailor-made for testing.</p>
<p>Well, it&#8217;s not. The command description is very &#8220;vague,&#8221; in that you use it to add entries (paragraphs) to the &#8220;test list.&#8221; </p>
<p>Some experimentation will show that the apparent use is to document something (a class, a function) and add a bunch of these \test entries, just like adding \param commands. And the entity you are documenting will then have a <b>Test:</b> section in its documentation.</p>
<p>This is totally not what I want. And I&#8217;m pretty sure it&#8217;s not what anybody doing TDD wants. What I want is to somehow tie my tests, which are in a separate location (different file, different class, different namespace, etc.), back to the class or function that I&#8217;m testing.</p>
<p>The best way I&#8217;ve found so far to accomplish this is to <em>lie</em> to Doxygen about what is being documented. Here&#8217;s my current scheme:<br />
<code><br />
#define BOOST_TEST_DYN_LINK<br />
#include &lt;boost/test/unit_test.hpp&gt;</p>
<p>#include &lt;Bronze/Memory/Simple/Arena.h&gt;</p>
<p>using namespace Bronze::Memory;</p>
<p>BOOST_AUTO_TEST_SUITE( Memory_SimpleArena )</p>
<p>/// \class Bronze::Memory::Simple::Arena<br />
/// \test \b null_ctor Confims that a SimpleArena no-args construction will<br />
/// use the default size, whatever that is. (1m)</p>
<p>BOOST_AUTO_TEST_CASE( null_ctor ) {</p>
<p>	Arena &#038; sut = Simple::Arena();<br />
	BOOST_CHECK( sut.capacity() != 0 );<br />
}<br />
</code></p>
<p>Adding the <tt>\class</tt> command tells Doxygen to re-open the documentation of the target class. The <tt>\test</tt> command is then associated with the &#8220;right&#8221; class, and I include the testcase name in bold as part of the test description. </p>
<p>This still doesn&#8217;t generate a link to the right source file (containing the test), and it doesn&#8217;t really know anything about the test case. So it&#8217;s not a perfect solution. But it does enable me to put my testcase documentation with my testcases, while having the documentation actually show up attached to the right class.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2010/08/using-doxygens-test-command-with-c/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Which &#8216;which&#8217; is which?</title>
		<link>http://www.longacre-scm.com/blog/index.php/2010/08/which-which-is-which</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2010/08/which-which-is-which#comments</comments>
		<pubDate>Tue, 10 Aug 2010 22:13:27 +0000</pubDate>
		<dc:creator>Austin Hastings</dc:creator>
				<category><![CDATA[Off-topic]]></category>
		<category><![CDATA[Practice]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/?p=91</guid>
		<description><![CDATA[The &#8216;which&#8217; utility is one of those really useful commands that never seems to cross the bridge from Unix to Windows. The CMD.EXE special %$PATH:f syntax seems to promise some relief, but of course it&#8217;s never that simple &#8211; I at least want to type &#8220;which foo&#8221; rather than &#8220;which foo.exe&#8221;.
So here&#8217;s which.cmd &#8211; a [...]]]></description>
			<content:encoded><![CDATA[<p>The &#8216;which&#8217; utility is one of those really useful commands that never seems to cross the bridge from Unix to Windows. The CMD.EXE special %$PATH:f syntax seems to promise some relief, but of course it&#8217;s never that simple &#8211; <strong>I</strong> at least want to type &#8220;which foo&#8221; rather than &#8220;which foo.exe&#8221;.</p>
<p>So here&#8217;s <code>which.cmd</code> &#8211; a script that tries to DWIW. </p>
<p>Note that this script is wrong in one key detail: it searches inside-out. That is, any &#8220;foo.COM&#8221; will take precedence over any &#8220;foo.EXE&#8221; even if the .exe version occurs earlier in the PATH.</p>
<pre>
@echo off
REM Copyright (c) 2010, Austin Hastings.
REM This file may be used for any purpose without restriction.

REM NOTE: This script does not handle multiple entries with different
REM extensions correctly. It returns the first matching EXTENSION, rather
REM than returning the first DIRECTORY with any EXTENSION.

REM Analogous to unix 'which' command, look for a matching runnable
REM in %PATH% and print the location.

SETLOCAL ENABLEDELAYEDEXPANSION

set check_extensions= ;%PATHEXT%

:ext_loop
if "%check_extensions%" == "" goto done

for /F "tokens=1* delims=;" %%E in ( "%check_extensions%" ) do (
	set check_extensions=%%F
	set target=%1%%E
	for %%W in (  !target! ) do set answer=%%~f$PATH:W
)

if "%answer%" == "" goto ext_loop

:done
if "%answer%" == "" goto not_found

@echo %answer%
goto exit

:not_found
@echo No runnable matching '%1' was found.

:exit
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2010/08/which-which-is-which/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Some bash goodness</title>
		<link>http://www.longacre-scm.com/blog/index.php/2009/10/some-bash-goodness</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2009/10/some-bash-goodness#comments</comments>
		<pubDate>Wed, 28 Oct 2009 15:09:48 +0000</pubDate>
		<dc:creator>Austin Hastings</dc:creator>
				<category><![CDATA[Off-topic]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/index.php/2009/10/some-bash-goodness</guid>
		<description><![CDATA[Here&#8217;s some bash goodness (well, not really) to make &#8216;less&#8217; a little bit more useful.
&#160;
less() {
 &#160; &#160; &#160; &#160;local -a args
&#160;
 &#160; &#160; &#160; &#160;for arg
 &#160; &#160; &#160; &#160;do
 &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;case &#8220;$arg&#8221; in
 &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;*:[[:digit:]]* )
 &#160; &#160; &#160; &#160; &#160; [...]]]></description>
			<content:encoded><![CDATA[<div>Here&#8217;s some bash goodness (well, not really) to make &#8216;less&#8217; a little bit more useful.</div>
<div>&#160;</div>
<div>less() {</div>
<div> &#160; &#160; &#160; &#160;local -a args</div>
<div>&#160;</div>
<div> &#160; &#160; &#160; &#160;for arg</div>
<div> &#160; &#160; &#160; &#160;do</div>
<div> &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;case &#8220;$arg&#8221; in</div>
<div> &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;*:[[:digit:]]* )</div>
<div> &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;line=${arg/#+(?):/}</div>
<div> &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;args[${#args[*]}]=&#8221;+$line&#8221;</div>
<div> &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;arg=${arg/%:+(?)/}</div>
<div> &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;;;</div>
<div> &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;esac</div>
<div>&#160;</div>
<div> &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;args[${#args[*]}]=$arg</div>
<div> &#160; &#160; &#160; &#160;done</div>
<div>&#160;</div>
<div> &#160; &#160; &#160; &#160;$( which less ) &#8220;${args[@]}&#8221;</div>
<div>}</div>
<div>&#160;</div>
<div>Basically, this shell function loads when you tell it to (in your .profile, likely), and it replaces the &#8216;less&#8217; command. When you type &#8216;less &#8230;&#8217; on the command line, the function runs.</div>
<div>&#160;</div>
<div>It scans through the args, looking for one like filename.c:24, and if it finds that kind of arg, it replaces it with +24 filename.c &#8212; translating the syntax used by a *lot* of compilers into the syntax used by less for opening a file and jumping directly to the line number.</div>
<div>&#160;</div>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2009/10/some-bash-goodness/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unit tests for MySQL scripts</title>
		<link>http://www.longacre-scm.com/blog/index.php/2009/04/unit-tests-for-mysql-scripts</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2009/04/unit-tests-for-mysql-scripts#comments</comments>
		<pubDate>Sun, 26 Apr 2009 01:07:09 +0000</pubDate>
		<dc:creator>Austin Hastings</dc:creator>
				<category><![CDATA[Practice]]></category>
		<category><![CDATA[Software CM]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[database]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/index.php/2009/04/58</guid>
		<description><![CDATA[Recently I had the opportunity to develop a unit testing framework for MySQL scripts in mostly-pure SQL. While I can&#8217;t share the code, I can certainly describe what we did, and why we did it. Hopefully it will be useful to you.

My client was reorganizing a development team into an agile mode in order to [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I had the opportunity to develop a unit testing framework for MySQL scripts in mostly-pure SQL. While I can&#8217;t share the code, I can certainly describe what we did, and why we did it. Hopefully it will be useful to you.<br />
<span id="more-58"></span></p>
<p>My client was reorganizing a development team into an agile mode in order to deal with an outsourcing disaster. It was one of those horror stories that starts out like &#8220;We were 3 years in to a 10 month project, when &#8230;&#8221; I was brought on to help ramp up their build and deployment processes, to get continuous integration and testing systems up, and to help mechanize their deployments.</p>
<p>The impetus for the MySQL unit test framework came from a short term contractor. The one &#8220;constant&#8221; in the otherwise highly-variable environment had been that the team wasn&#8217;t changing. Suddenly, that stopped being true. We had a handful of contractors in for a short term surge, and none of them were familiar with the application, or with SQL (it seemed). The offender was using the CI server as his syntax checker for database scripts. Yikes!</p>
<p>Luckily, the garbage he delivered was syntactically invalid. The mysql command-line client rejected the script and exited with an error status, which caused the CI script to log a failure, and &#8230; voila! Everyone credited me with doing a great job of implementing CI, because it was even checking the database stuff. Like a good consultant, I said &#8220;Yes. Of course.&#8221; Then I ran back to my desk, thinking &#8220;Oh, no! I&#8217;ve got to come up with a unit test framework for the MySQL stuff, pronto!&#8221; And I did.</p>
<p><strong>Solutions</strong></p>
<p>The software was a pretty complex web app, and the target environment was a mixture of Linux and Windows. As a result, when I looked at existing SQL unit test frameworks (<a href="http://www.dbunit.org/">dbUnit</a> and <a href="http://sqlunit.sourceforge.net/">sqlUnit,</a> respectively) I had to reject them. They are decent products &#8211; and free &#8211; but the fact is that they expect certain things about their runtime environment that we couldn&#8217;t deliver. We had to build our own MySQL unit test framework, ideally in &#8220;pure&#8221; MySQL.</p>
<p>Fortunately for me, a nice guy named Giuseppe Maxia maintains a web site at <a href="http://www.datacharmer.org">datacharmer.org,</a> and he has written a library of general-purpose MySQL code. (Called the General Purpose Stored Routine library, or gp_sr_lib.) Among the all this well-written, free, already debugged code was a set of testing routines. Thirty minutes into my development effort, I was already 80% done. Woo-hoo!</p>
<p>The GP library test routines are a good start on a mysqlUnit library, and I strongly recommend that if you need such a library you stop reading here and go download the code. Right now. </p>
<p><strong>Rolling (y)our Own</strong></p>
<p>There are a couple of gotchas that you&#8217;ll want to watch out for in your own unit testing library. First, the tests should be able to integrate into your CI engine. In particular, you need to decide on and implement some kind of failure mode &#8211; either fail when the first problem occurs, or fail after running all test cases. If you&#8217;re running the mysql client via some kind of exec call, be aware that while syntax errors will cause the client to exit with a failure code, other errors will not cause a failure. Instead, the client prints a diagnostic and returns zero. What&#8217;s more, the syntax does not support a deliberate abort from within the SQL engine.</p>
<p>In my own case, I chose to follow the model that Maxia has provided, and NOT fail as soon as a test fails. Rather, my code collected the results of all the tests that were run, and summarized them. In order to get &#8220;fail on error&#8221; behavior out of the mysql command line client, I coded a routine that would perform a &#8220;SELECT force_mysql_client_abort FROM no_such_table&#8221;. This definitely does cause the client to abort, at least until some developer creates a table called &#8220;no_such_table.&#8221; Then I wrapped the test cases in an &#8220;ignore failure&#8221; script that called the summarizer after all the cases had run, which in turn would call the abort routine if the error count was non-zero.</p>
<p>Another thing I chose to &#8220;fix&#8221; was the routine names. Maxia&#8217;s code includes both functions and procedures, but the names are not really in keeping with the style used in the various xUnit test frameworks. The library contains a procedure for asserting the existence of a database table. It is called as:</p>
<p><code>CALL check_table('db name', 'table name');<br />
</code></p>
<p>I opted to &#8220;embrace and extend&#8221; the library. I wrapped these types of checks into functions, like this:</p>
<p><code><br />
set_database('db name');<br />
assert_table_exists('table name');<br />
assert_table_exists_in_db('other table', 'other db');<br />
</code></p>
<p>And in general, wherever there is a straight-ahead assert, I also added an &#8220;assert_not&#8221;. In terms of effect, there is no real difference in behavior between Maxia&#8217;s naming and my own. But I felt that the developers, who were using jUnit and nUnit, would be more comfortable learning a set of routines that had a similar structure and style.</p>
<p><strong>Going Most of the Way: DDL</strong></p>
<p>I tried to make a list of the various things that SQL scripts might do. The most obvious &#8212; and this probably accounted for two thirds or more of the scripts we had &#8212; is DDL statements. DDL (Data Definition Language) is that subset of SQL that relates to defining databases, tables, indexes, triggers, and the like. While the most frequently executed SQL statements are DML (Data Manipulation Language), DDL is where it&#8217;s at for most of the human-generated script files: CREATE TABLE, ADD INDEX, etc.</p>
<p>The great thing is that the assertions for these statements are trivial to write. Maxia&#8217;s library includes the CHECK_TABLE procedure, and some code for looking up procedures and functions. Adding other stuff, like keys and constraints, is pretty straightforward. By the end of the day you should have a long list of functions like assert_table_exists, assert_index_exists, assert_database_exists, and  assert_column_has_type.</p>
<p><strong>Deploy Early</strong></p>
<p>At this point, you&#8217;re ready to go live. Except that you need to build a framework to run these tests. That&#8217;s going to depend a lot on your deployment process, and on your particular CI environment. Sorry. The simplest idea would be to write a script that matches the file names of test files, and runs them one at a time. Call that script from CI, and make sure the exit status is meaningful.</p>
<p>Forget the next couple of sections, because most of the database changes you&#8217;re likely to see are DDL. Developers and DBAs do a lot of adding fields, adding indexes, and sometimes adding tables. If you have just the existence assertions for each kind of object, your library will cover two-thirds or more of the statements being delivered. That&#8217;s not a trivial amount of test coverage for a day or two of work. Ship it! Your developers will need some training, and you&#8217;ll need to beat on the thing once it&#8217;s deployed to your CI servers to make sure that the errors are coming out correctly. </p>
<p><strong>Sell to the Development Team</strong></p>
<p>I recommend that you write some simple tests of things you know to be true. Confirm the positive cases first. Then sit down with a smart, involved developer and pair develop some unit tests for code he hasn&#8217;t written yet. Do it the way you want the developers to do it, including deciding how to handle assertions that don&#8217;t exist yet. </p>
<p>In our case, the DBAs had already established a naming convention for database update files. I chose to duplicate the file names, which would look like ####_description.sql, changing the .sql extension to .test.sql. This let the testing framework associate the test with the delivered change. When running a &#8220;from zero&#8221; deployment, the test framework would then run TEST-CHANGE-TEST and expect the first test to fail and the second to pass. This demonstrated that the test was meaningful for the change (remember, the change is supposed to repair a shortcoming that is demonstrated by the test).</p>
<p>Once you&#8217;ve got buy-in from your chosen developer, sit down and develop a presentation that the two of you can give. Point to specific examples of blown deployments as reasons for unit testing the SQL. Then get the coder to explain the available test assertions. Then explain the framework you&#8217;ve developed to integrate the testing library with CI, and explain what failures are going to look like. And don&#8217;t forget to point them at the documentation you&#8217;ve written on the project wiki. This should get your team on board, and now you can start looking for other assertions to write. You can also start tightening the screws on your framework. Make it so that no change can be delivered without at least one test.</p>
<p><strong>Simple DML Checking</strong></p>
<p>The next obvious category of SQL statements to check is simple DML. These are the CRUD verbs: INSERT, SELECT, UPDATE and DELETE.  Except that SELECT can be pretty hard to check within SQL, so it&#8217;s best to ignore it for now in favor of the others. The problem with DML is knowing what to check for. If you insert a row, should you check that the ROW_COUNT() returns 1? Or should you query for the particular key of that row? </p>
<p>I&#8217;m pretty convinced that DML commands in scripts are going to be metadata related. That is, your application may be inserting customer records, or video titles, or whatever you track. But if a developer codes a DELETE, INSERT, or UPDATE into a deployable script, I think the intent is either to perform some kind of bulk fix (convert data fields, or eliminate nulls) or it is adjusting the &#8220;background&#8221; data &#8212; the list of postal codes, state and province names, etc. that your application relies on. In the case of the simple background data, if you added or updated it, you should check it explicitly: assert that for a specific key, the values are as expected. </p>
<p>Some examples of helpful functions would be <code>assert_statement_affects_rowcount(prepared_statement, num_rows), assert_table_column_matches_count('table name', 'column', value, count),</code> and their negatives. The way to do dynamic programming in MySQL is with prepared statements. You can construct a string containing a SQL statement, use PREPARE to assign it to an identifier, and then EXECUTE the identifier:</p>
<p><code><br />
PREPARE stmt<br />
    FROM<br />
        CONCAT("SELECT COUNT(*) FROM ", table_name, " WHERE ", field_name, " = ?");<br />
</code></p>
<p><code><br />
EXECUTE stmt USING value;<br />
</code></p>
<p>In the more complex case of a data format or type update, the update should be encoded in a stored procedure. This way you can unit test the stored procedure with sample data. Once the procedure is ready to go, write a script that calls the procedure &#8211; confident already that the procedure will work &#8211; and test the invocation by confirming random elements of the data have converted correctly.</p>
<p><strong>Testing Result Sets</strong></p>
<p>As mentioned, testing SELECT can be a real challenge. While it is easy to create an assert_row_count(num) to confirm that your query returned the right number of values, it can be much harder to create a function to assert that a particular ordering exists, or that the results are truly grouped by postal code.</p>
<p>The first thing to do is go ahead and write the assertion functions for number of rows returned by the query. That&#8217;s simple, straightforward, and it can stand in place of more complex stuff for a long time. You may not ever get around to writing the more challenging assertions &#8212; if the tests are designed well enough, the number of results may be meaningful enough. If you do need to write more, especially if the query is complex, pass the query as a string to your assertion, prepare it as a statement, and make sure the results go into a temporary table. Then you can write whatever horribly complex code you need against the temporary table, without having to worry about losing context.</p>
<p><strong>Testing Triggers</strong></p>
<p>Triggers are going to be harder to test than other pieces of code because of the diverse ways you can invoke them. For example, a DELETE trigger may need to be checked with a simple delete statement as well as with a CASCADE from a foreign key relationship. Beyond creating assertions for the existence and type of triggers (BEFORE/AFTER, INSERT/UPDATE/DELETE, etc.) there isn&#8217;t really any obvious set of assertions to write. It&#8217;s more a question of deciding how to test the effects of the triggers, and of documenting the ways the trigger can be invoked.</p>
<p><strong>Conclusion</strong></p>
<p>Unit testing, and test-first development, are well established best practices. But it&#8217;s easy to overlook the &#8220;small stuff&#8221; when developers are setting up frameworks for testing their code. Database updates are small, but when they go wrong they can take out the rest of the system. It&#8217;s important to apply the same techniques, and get the same value, to this part of your development. Now you can.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2009/04/unit-tests-for-mysql-scripts/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Gotcha: XML include processing in CruiseControl.NET</title>
		<link>http://www.longacre-scm.com/blog/index.php/2008/06/gotcha-xml-include-processing-in-cruisecontrolnet</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2008/06/gotcha-xml-include-processing-in-cruisecontrolnet#comments</comments>
		<pubDate>Tue, 24 Jun 2008 16:24:36 +0000</pubDate>
		<dc:creator>Austin Hastings</dc:creator>
				<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/index.php/2008/06/gotcha-xml-include-processing-in-cruisecontrolnet</guid>
		<description><![CDATA[Release 1.4 of CruiseControl.NET includes a new Configuration Preprocessor. The great thing is that this provides a C preprocessor-like macro syntax, so projects can be made using relatively powerful templates.
The bad thing is that it&#8217;s new, and so there are some gotcha&#8217;s laying around. I just found one:
I defined a ccnet.config file structured like this:


&#60;cruisecontrol
 [...]]]></description>
			<content:encoded><![CDATA[<p>Release 1.4 of CruiseControl.NET includes a new <a href="http://confluence.public.thoughtworks.org/display/CCNET/Configuration+Preprocessor">Configuration Preprocessor</a>. The great thing is that this provides a C preprocessor-like macro syntax, so projects can be made using relatively powerful templates.</p>
<p>The bad thing is that it&#8217;s new, and so there are some gotcha&#8217;s laying around. I just found one:</p>
<p>I defined a ccnet.config file structured like this:</p>
<blockquote><pre>

&lt;cruisecontrol
  xmlns:cb="urn:ccnet.config.builder"
  >
  &lt;!-- Define some local configuration symbols -->
  &lt;cb:define
    FOO="bar"
    />
  &lt;!-- Define a CCnet project template called "cb:PROJECT" -->
  &lt;cb:define
    name="PROJECT"
    >
    &lt;project
      name = "$(projectName)"
      >
      &lt;!--
          guts go here
          -->
    &lt;/project>
  &lt;/cb>
  &lt;!-- Use template -->
  &lt;cb:PROJECT
    projectName = "My dog has fleas"
    />
&lt;/cruisecontrol>
</pre>
</blockquote>
<p>That worked fine, and I could see how to rubber-stamp that project template to all my various continuous-integration areas and other workspaces.</p>
<p>But then I got clever, and decided to separate out the template from the local configuration.</p>
<blockquote><pre>

&lt;cruisecontrol
  xmlns:cb="urn:ccnet.config.builder"
  >

  &lt;!-- Define some local configuration symbols -->
  &lt;cb:define
    FOO="bar"
    />

  <strong>&lt;!-- Include template(s) file -->
  &lt;cb:include
    href = "project-template.xml"
    /></strong>

  &lt;!-- Use template -->
  &lt;cb:PROJECT  projectName = "My dog has fleas"  />
&lt;/cruisecontrol>
</pre>
</blockquote>
<p>By unfortunate coincidence, I had to reboot my laptop at this point &#8212; I kicked the power strip under the desk, removing power to the docking station. The Lenovo I&#8217;m using (client provided) doesn&#8217;t handle this at all, so it was restart time. When I came back up, the CruiseControl.NET service wouldn&#8217;t start.</p>
<p>Debugging is simple and easy with the &#8220;ccnet.exe&#8221; command line utility. Just run<br />
<code><br />
ccnet.exe -config:ccnet.config -validate</p>
<p></code></p>
<p>The error, though, was incomprehensible:</p>
<blockquote><pre>
C:\Program Files\CruiseControl.NET\server>ccnet -config:ccnet.config -validate
CruiseControl.NET Server 1.4.0.3400 -- .NET Continuous Integration Server
Copyright c 2008 ThoughtWorks Inc.  All Rights Reserved.
.NET Runtime Version: 2.0.50727.1433    Image Runtime Version: v2.0.50727
OS Version: Microsoft Windows NT 5.1.2600 Service Pack 3        Server locale: e
n-US

[CCNet Server:DEBUG] The trace level is currently set to debug.  This will cause
 CCNet to log at the most verbose level, which is useful for setting up or debug
ging the server.  Once your server is running smoothly, we recommend changing th
is setting in C:\Program Files\CruiseControl.NET\server\ccnet.exe.config to a lo
wer level.
[CCNet Server:INFO] Reading configuration file "C:\Program Files\CruiseControl.NET\server\ccnet.config"
[CCNet Server:ERROR] Exception: The configuration file contains invalid xml: C:\Program Files\CruiseControl.NET\server\ccnet.config
----------
ThoughtWorks.CruiseControl.Core.Config.ConfigurationException: The configuration file contains invalid xml: C:\Program Files\CruiseControl.NET\server\ccnet.config ---> System.Xml.XmlException: 'cb' is an undeclared namespace. Line 1, position 2.
   at System.Xml.XmlTextReaderImpl.Throw(Exception e)
   at System.Xml.XmlTextReaderImpl.Throw(String res, String arg, Int32 lineNo, Int32 linePos)
   at System.Xml.XmlTextReaderImpl.LookupNamespace(NodeData node)
   at System.Xml.XmlTextReaderImpl.ElementNamespaceLookup()
   at System.Xml.XmlTextReaderImpl.ParseAttributes()
   at System.Xml.XmlTextReaderImpl.ParseElement()
   at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
   at System.Xml.XmlTextReaderImpl.Read()
   at System.Xml.XPath.XPathDocument.LoadFromReader(XmlReader reader, XmlSpace space)
   at System.Xml.XPath.XPathDocument..ctor(Stream stream)
   at ThoughtWorks.CruiseControl.Core.Config.Preprocessor.ConfigPreprocessorEnvironment.push_include(String href)
   at ThoughtWorks.CruiseControl.Core.Config.Preprocessor.ConfigPreprocessor.PreProcess(XmlReader input, XmlWriter output, PreprocessorUrlResolver resolver, Uri input_uri)
   at ThoughtWorks.CruiseControl.Core.Config.DefaultConfigurationFileLoader.CreateXmlValidatingLoader(FileInfo configFile)
   at ThoughtWorks.CruiseControl.Core.Config.DefaultConfigurationFileLoader.AttemptLoadConfiguration(FileInfo configFile)
   --- End of inner exception stack trace ---
   at ThoughtWorks.CruiseControl.Core.Config.DefaultConfigurationFileLoader.AttemptLoadConfiguration(FileInfo configFile)
   at ThoughtWorks.CruiseControl.Core.Config.DefaultConfigurationFileLoader.Load(FileInfo configFile)
   at ThoughtWorks.CruiseControl.Core.Config.FileConfigurationService.Load()
   at ThoughtWorks.CruiseControl.Core.Config.FileWatcherConfigurationService.Load()
   at ThoughtWorks.CruiseControl.Core.Config.CachingConfigurationService.Load()
   at ThoughtWorks.CruiseControl.Core.CruiseServer..ctor(IConfigurationService configurationService, ProjectIntegratorListFactory projectIntegratorListFactory, IProjectSerializer projectSerializer)
   at ThoughtWorks.CruiseControl.Core.CruiseServerFactory.Create(Boolean remote, String configFile)
   at ThoughtWorks.CruiseControl.Core.ConsoleRunner.Run()
   at ThoughtWorks.CruiseControl.Console.ConsoleMain.Main(String[] args)
----------
</pre>
</blockquote>
<p>Even worse, the error message is presented in white text on a glaring red background, so as to be all but unreadable. Looking at it now, in retrospect (and black &#038; white), I can see clues that I missed the first time. Specifically, the string &#8220;push_include.&#8221;</p>
<p>Anyway, the problem turned out to be the way the Configuration Processor deals with XML includes. It is <strong>not</strong> a C preprocessor &#8212; it includes subtrees, not text. </p>
<p>The answer turns out to be in the included file. References in the included file to the &#8220;cb:&#8221; XML namespace have to be accompanied in that file by some definition. Adding the same xmlns= statement does the trick:</p>
<blockquote><pre>

&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;cb:define  <strong>xmlns:cb="urn:ccnet.config.builder"</strong>  name = "PROJECT"  >
  &lt;!-- blah blah -->
&lt;/cb:define>
</pre>
</blockquote>
<p>Problem solved. Now let the rubber-stamping begin!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2008/06/gotcha-xml-include-processing-in-cruisecontrolnet/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[wiki &#124; reviews:byname:guiffy_suremerge:20060706]</title>
		<link>http://www.longacre-scm.com/blog/index.php/2008/04/reviews-byname-guiffy_suremerge-20060706</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2008/04/reviews-byname-guiffy_suremerge-20060706#comments</comments>
		<pubDate>Sat, 19 Apr 2008 01:15:50 +0000</pubDate>
		<dc:creator>Austin Hastings</dc:creator>
				<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/index.php/2008/04/[[reviews:byname:guiffy_suremerge:20060706]]</guid>
		<description><![CDATA[

Table of Contents



Review of Guiffy SureMerge

Editorial Notes
Product Explanation
Two-way Comparison
Three-way Comparison
Merging
Directory Compare
Features

Jiff command-line utility
SureMerge command-line utility
HTML comparison reports
International Character Encodings
Java API


Support
Accuracy
Performance
Ease of Use
Effectiveness
Cost
Conclusion






Review of Guiffy SureMerge




Editorial Notes



 Date: March 2006
 Product: Guiffy SureMerge 7.2 “Dogwood”
 Vendor: Guiffy Software (http://www.guiffy.com)
 Reviewer: Austin Hastings




Bill Ritcher, coder and CEO of Guiffy, is aware of the review. He became aware [...]]]></description>
			<content:encoded><![CDATA[<div class="dokuwiki">
<div class="toc">
<div class="tocheader toctoggle" id="toc__header">Table of Contents</div>
<div id="toc__inside">

<ul class="toc">
<li class="level1"><div class="li"><span class="li"><a href="#review_of_guiffy_suremerge" class="toc">Review of Guiffy SureMerge</a></span></div>
<ul class="toc">
<li class="level2"><div class="li"><span class="li"><a href="#editorial_notes" class="toc">Editorial Notes</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#product_explanation" class="toc">Product Explanation</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#two-way_comparison" class="toc">Two-way Comparison</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#three-way_comparison" class="toc">Three-way Comparison</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#merging" class="toc">Merging</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#directory_compare" class="toc">Directory Compare</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#features" class="toc">Features</a></span></div>
<ul class="toc">
<li class="level3"><div class="li"><span class="li"><a href="#jiff_command-line_utility" class="toc">Jiff command-line utility</a></span></div></li>
<li class="level3"><div class="li"><span class="li"><a href="#suremerge_command-line_utility" class="toc">SureMerge command-line utility</a></span></div></li>
<li class="level3"><div class="li"><span class="li"><a href="#html_comparison_reports" class="toc">HTML comparison reports</a></span></div></li>
<li class="level3"><div class="li"><span class="li"><a href="#international_character_encodings" class="toc">International Character Encodings</a></span></div></li>
<li class="level3"><div class="li"><span class="li"><a href="#java_api" class="toc">Java API</a></span></div></li>
</ul>
</li>
<li class="level2"><div class="li"><span class="li"><a href="#support" class="toc">Support</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#accuracy" class="toc">Accuracy</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#performance" class="toc">Performance</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#ease_of_use" class="toc">Ease of Use</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#effectiveness" class="toc">Effectiveness</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#cost" class="toc">Cost</a></span></div></li>
<li class="level2"><div class="li"><span class="li"><a href="#conclusion" class="toc">Conclusion</a></span></div></li></ul>
</li></ul>
</div>
</div>



<h1><a name="review_of_guiffy_suremerge" id="review_of_guiffy_suremerge">Review of Guiffy SureMerge</a></h1>
<div class="level1">

</div>
<!-- SECTION "Review of Guiffy SureMerge" [1-42] -->
<h2><a name="editorial_notes" id="editorial_notes">Editorial Notes</a></h2>
<div class="level2">

<p>
 <strong>Date: March 2006</strong><br/>
 <strong>Product: Guiffy SureMerge 7.2 “Dogwood”</strong><br/>
 <strong>Vendor: Guiffy Software (<a href="http://www.guiffy.com" class="urlextern" title="http://www.guiffy.com"  rel="nofollow">http://www.guiffy.com</a>)</strong><br/>
 <strong>Reviewer: Austin Hastings</strong><br/>

</p>

<p>
Bill Ritcher, coder and CEO of Guiffy, is aware of the review. He became aware  about half-way through when I was contacting him for help with various issues.  After the review was published, Guiffy began providing a link to the review  from their product web site.
</p>

</div>
<!-- SECTION "Editorial Notes" [43-498] -->
<h2><a name="product_explanation" id="product_explanation">Product Explanation</a></h2>
<div class="level2">

<p>
 Guiffy (pronounced “Goofy” according to owner/developer Bill Ritcher) SureMerge is a java-based, platform-neutral visual compare and merge utility for software and content developers. It is compatible with Java 5 (as well as earlier releases) and is available for OpenVMS and <acronym title="Operating System">OS</acronym>/2, as well as less-popular operating systems like Linux, Windows, and Mac <acronym title="Operating System">OS</acronym>/X. 
</p>

<p>
Most of the time, comparison and merge tools are listed as being tools for developers. In reality, though, this is not true. Comparison and merge tools are tools for leads, build managers, and SCMs—the folks who get called when something goes wrong. But we all wish that developers would fix the problems they introduce, so most companies distribute these tools to everyone. SureMerge supports developers with “the usual” range of compare and merge features, discussed below. In addition, it contains features that will be near and dear to the heart of build managers, team leads, and change managers everywhere—tools that make it easy to deal with whole development teams and whole trees of files.
</p>

<p>
The product comes with a collection of executables including stand-alone compare and merge command line tools. One of those programs is a command-line merge utility called <code>suremerge.</code> The <acronym title="Graphical User Interface">GUI</acronym> version is named <code>guiffy.</code> I will refer to them by name when it is relevant. Otherwise I will call the whole software bundle SureMerge, and the company Guiffy.
</p>

</div>
<!-- SECTION "Product Explanation" [499-1963] -->
<h2><a name="two-way_comparison" id="two-way_comparison">Two-way Comparison</a></h2>
<div class="level2">

<p>
 Two-way comparison of files is what comes to mind immediately when you think about comparisons: put two files next to each other and see where the changes are. Most readers will be familiar with the <code>diff</code> and <code>sdiff</code> commands for comparing files and displaying the results. A graphical rendition is much clearer and easier to understand.
</p>

<p>
When you evaluate SureMerge, the Guiffy web site (<a href="http://www.guiffy.com" class="urlextern" title="http://www.guiffy.com"  rel="nofollow">http://www.guiffy.com</a>) includes a white paper with a series of test cases. The white paper highlights different kinds of changes and how they are handled by merge &amp; compare tools, using Guiffy source code in the examples. This screen shot was taken using one of the included test cases. (No, I don&#039;t have access to Guiffy&#039;s source code.)
</p>

<p>
<a href="/wiki/lib/exe/detail.php/reviews/byname/guiffy_suremerge/1-twowaycompare.png?id=reviews%3Abyname%3Aguiffy_suremerge%3A20060706&amp;cache=cache" class="media" title="reviews:byname:guiffy_suremerge:1-twowaycompare.png"><img src="/wiki/lib/exe/fetch.php/reviews/byname/guiffy_suremerge/1-twowaycompare.png?w=400&amp;h=&amp;cache=cache" class="media" title="Screenshot of 2-way Compare" alt="Screenshot of 2-way Compare" width="400" /></a>
</p>

<p>
A very nice feature of the <code>guiffy</code> <acronym title="Graphical User Interface">GUI</acronym> <a href="#fn__1" name="fnt__1" id="fnt__1" class="fn_top">1)</a> is character-by-character highlighting of differences. If you are using a language that tends to have &#039;dense&#039; statements, this can be a life-saver, highlighting where a full stop (&#039;.&#039;) changed to a comma or where a single quote became a back tick. Be careful with character-by-character differencing: like all compare algorithms, it is prone to look for similarities that may not be there:
</p>

<p>
<a href="/wiki/lib/exe/detail.php/reviews/byname/guiffy_suremerge/2-characterbycharacter.png?id=reviews%3Abyname%3Aguiffy_suremerge%3A20060706&amp;cache=cache" class="media" title="reviews:byname:guiffy_suremerge:2-characterbycharacter.png"><img src="/wiki/lib/exe/fetch.php/reviews/byname/guiffy_suremerge/2-characterbycharacter.png?w=250&amp;h=&amp;cache=cache" class="media" title="Character-by-character highlighting of changes" alt="Character-by-character highlighting of changes" width="250" /></a>
</p>

<p>
The example shows two random DNA sequences. I used perl to randomly emit the four letters A, C, G, T. As you can see, <code>guiffy</code> was willing to “walk a mile” to show me the exact changes, when in fact I just made up two totally different sequences. <a href="#fn__2" name="fnt__2" id="fnt__2" class="fn_top">2)</a>
</p>

<p>
That was a dumb example made to demonstrate a point: <code>guiffy</code> offers a configuration setting that lets you determine how much change is “too much”. A better example is refactoring code. Consider this change, taken from Michael Schwern&#039;s excellent <acronym title="Practical Extraction and Report Language">Perl</acronym> <a href="http://www.perl.com/pub/a/2003/10/09/refactoring.html" class="urlextern" title="http://www.perl.com/pub/a/2003/10/09/refactoring.html"  rel="nofollow">refactoring tutorial:</a>
</p>

<p>
<a href="/wiki/lib/exe/detail.php/reviews/byname/guiffy_suremerge/3-inlinetoohigh.png?id=reviews%3Abyname%3Aguiffy_suremerge%3A20060706&amp;cache=cache" class="media" title="reviews:byname:guiffy_suremerge:3-inlinetoohigh.png"><img src="/wiki/lib/exe/fetch.php/reviews/byname/guiffy_suremerge/3-inlinetoohigh.png?w=400&amp;h=&amp;cache=cache" class="media" title="" alt="" width="400" /></a>
</p>

<p>
This example also has character highlighting turned on, so what happened? The answer lies in a configuration dialog, Options&gt;Show:
</p>

<p>
<a href="/wiki/lib/exe/detail.php/reviews/byname/guiffy_suremerge/4-showinlinediffs.png?id=reviews%3Abyname%3Aguiffy_suremerge%3A20060706&amp;cache=cache" class="media" title="reviews:byname:guiffy_suremerge:4-showinlinediffs.png"><img src="/wiki/lib/exe/fetch.php/reviews/byname/guiffy_suremerge/4-showinlinediffs.png?w=&amp;h=&amp;cache=cache" class="media" title="" alt="" /></a>
</p>

<p>
You can choose to show difference that are up to 100% of the line, which is what I did for the DNA sequence above. The default is 50%, as shown, but when you are merging source code the devil is in the details. In the example above, line 9 changed by more than 50% because of the long variable names. As a result, it was “too much change” to highlight. With a single buttonpress, a mouseclick, and &#039;Enter&#039; I have a different picture:
</p>

<p>
<a href="/wiki/lib/exe/detail.php/reviews/byname/guiffy_suremerge/5-inlinediffsokay.png?id=reviews%3Abyname%3Aguiffy_suremerge%3A20060706&amp;cache=cache" class="media" title="reviews:byname:guiffy_suremerge:5-inlinediffsokay.png"><img src="/wiki/lib/exe/fetch.php/reviews/byname/guiffy_suremerge/5-inlinediffsokay.png?w=400&amp;h=&amp;cache=cache" class="media" title="" alt="" width="400" /></a>
</p>

<p>
This is how the same code looks at a 75% change cutoff. Suddenly it&#039;s clear that the perl variables have been pulled out of the <acronym title="Structured Query Language">SQL</acronym> statement and replaced by bind variables. And the variables are now passed to <code>$sth&rarr;execute</code> as method args. This is great stuff! Just to be a little nit-picky, I&#039;m going to suggest that Guiffy make the Show Options page into a toolbar control or some kind of dockable: when you are looking at differences in code it can be important to quickly toggle back and forth.
</p>

</div>
<!-- SECTION "Two-way Comparison" [1964-5416] -->
<h2><a name="three-way_comparison" id="three-way_comparison">Three-way Comparison</a></h2>
<div class="level2">

<p>
 Beyond two-way comparison lies three-way. (Relax: three is the limit!) With three-way comparison, and three-way merging, you are comparing a single common ancestor with two different changed files. This is the tool to use when two developers have made different changes to the same file, and you&#039;re stuck merging them together. Sound familiar?
</p>

<p>
In the illustration (below) you can see how guiffy presents two changes that conflict with each other. In this case, different developers have allocated the constant value 7 to different purposes: the names CWP and ENA. 
</p>

<p>
<a href="/wiki/lib/exe/detail.php/reviews/byname/guiffy_suremerge/6-threewaycompare.png?id=reviews%3Abyname%3Aguiffy_suremerge%3A20060706&amp;cache=cache" class="media" title="reviews:byname:guiffy_suremerge:6-threewaycompare.png"><img src="/wiki/lib/exe/fetch.php/reviews/byname/guiffy_suremerge/6-threewaycompare.png?w=400&amp;h=&amp;cache=cache" class="media" title="Screenshot of 3-way compare" alt="Screenshot of 3-way compare" width="400" /></a>
</p>

<p>
To merge the changes it isn&#039;t sufficient to copy both new lines into the resulting file. Instead, one line will have to be manually edited to convert its value from 7 to 8. The tool compares both changed files against the parent, and then compares the change sets. For each part of the file, the possibilities are: 
</p>
<table class="inline">
	<tr>
		<th class="centeralign">  Parent vs. Me  </th><th class="centeralign">  Other vs. Me  </th><th class="centeralign">  Other vs. Parent  </th><th> Interpretation </th>
	</tr>
	<tr>
		<td class="centeralign">  Same           </td><td class="centeralign">  Same          </td><td class="centeralign">  Same              </td><td> Unchanged in both branches. </td>
	</tr>
	<tr>
		<td class="centeralign">  Same           </td><td class="centeralign">  Different     </td><td class="centeralign">  Different         </td><td> Changed only in <em>other</em> branch. Take that change. </td>
	</tr>
	<tr>
		<td class="centeralign">  Different      </td><td class="centeralign">  Same          </td><td class="centeralign">  Different         </td><td> Changed identically in both branches. Take this change. </td>
	</tr>
	<tr>
		<td class="centeralign">  Different      </td><td class="centeralign">  Different     </td><td class="centeralign">  Same              </td><td> Changed only in <em>this</em> branch. Take this change. </td>
	</tr>
	<tr>
		<td class="centeralign">  Different      </td><td class="centeralign">  Different     </td><td class="centeralign">  Different         </td><td> Changed in <em>both</em> branches. Merge these changes by hand. </td>
	</tr>
</table>

<p>
 Nearly all merge programs use this kind of logic to determine how to respond to changes. There are a couple of potential problems, however. First comes finding the smallest region in the file that constitutes a single change. We&#039;ve all seen cases where a compare program finds a single closing curly brace that is “equal” to similar text in the other file and so declares that point the end of one change and the start of another. Finding the boundaries of a “single” change can be challenging. 
</p>

<p>
Some cases aren&#039;t so clear-cut. For example, what if two developers insert code in the same location in the file, as illustrated above. You or I can tell it&#039;s a conflict (two allocations of the number 7), but some tools won&#039;t, since the two changes can be automatically merged by inserting both! The white paper I mentioned above has 5 simple scenarios for compare &amp; merge. I was surprised to learn that every other tool in the market gets at least one of those scenarios wrong! The cases are simple, and source code is provided: try them yourself.
</p>

<p>
Knowing what to ignore can be an issue, too. If the files in question have been translated from one operating system to another, or edited with different tools, things like white space and line terminators may be different. Having the ability to ignore these trivial changes is important. SureMerge has the ability, in spades. You can ignore whitespace at the beginning, at the end, or everywhere in the file. You can ignore changes matching a regex, or changes in a certain range of columns. The only thing SureMerge won&#039;t ignore for you is phone calls from your boss.
</p>

<p>
Finally, there is the risk of an identical-but-wrong change. In this scenario, possibly caused by out-of-band sharing, one part of a change might be present in both child versions but be fatal to one of the changes. Typically, you&#039;ll see this when the two developers have discussed the changes but haven&#039;t explicitly thought about each change. There&#039;s no way to catch these mechanically—your best bet is good unit testing.
</p>

<p>
<code>guiffy</code> does offer a nice feature that comes close to being psychic when these changes happen within a few lines: it reports an &#039;attention&#039; on code changes that are not in conflict, but are close together. If two developers made changes just a few lines apart, the software knows that it could merge them automatically, but is smart enough to say, “Hey! Somebody should check this.” Just like the Federal Aviation Administration, it considers even a near miss to be something important. Very nice.
</p>

</div>
<!-- SECTION "Three-way Comparison" [5417-9605] -->
<h2><a name="merging" id="merging">Merging</a></h2>
<div class="level2">

<p>
 As you might expect from a product named SureMerge, merging is a strong feature. There are a lot of different ways you can “merge” code via the <acronym title="Graphical User Interface">GUI</acronym>: 
</p>
<ol>
<li class="level1"><div class="li"> Just start typing. If you are using <code>guiffy</code> in merge mode, type (or copy &amp; paste) what you want into the “merged” window—<code>guiffy</code> won&#039;t let you change either of the original inputs. If you are using compare mode, you can edit in either file just like a text editor.</div>
</li>
<li class="level1"><div class="li"> Use Two-way merging. If all you have is two different files, you can choose between alternatives: <a href="/wiki/lib/exe/detail.php/reviews/byname/guiffy_suremerge/7-twowaymerge.png?id=reviews%3Abyname%3Aguiffy_suremerge%3A20060706&amp;cache=cache" class="media" title="reviews:byname:guiffy_suremerge:7-twowaymerge.png"><img src="/wiki/lib/exe/fetch.php/reviews/byname/guiffy_suremerge/7-twowaymerge.png?w=400&amp;h=&amp;cache=cache" class="mediacenter" title="" alt="" width="400" /></a> Of course, you can also just type: sometimes the merge process isn&#039;t about selecting between two alternatives, but combining them. If you need to type, or copy and paste, to get the results you want, just point and click.</div>
</li>
<li class="level1"><div class="li"> Use Three-way merging. As mentioned above, <code>guiffy</code> is excellent at determining just exactly which changes can be merged automatically, and which changes really do require the attention of a human. Of the five scenarios described above, only 1 requires a human to help with the work. In my experience, this reflects reality fairly well: I&#039;d guess that the number of &#039;real world&#039; merge steps requiring human attention is somewhere between 5 and 30 percent, depending on your code.</div>
</li>
</ol>

<p>
 Regardless, <code>guiffy</code> gives you the same basic interface (the &#039;parent&#039; is used to compute the changes, but isn&#039;t shown) as with two-way merging, and lets you do the same things: select code from either source as a starting point, then edit the code to the result you want.
</p>

</div>
<!-- SECTION "Merging" [9606-11211] -->
<h2><a name="directory_compare" id="directory_compare">Directory Compare</a></h2>
<div class="level2">

<p>
 Another nice feature of <code>guiffy</code> is the directory tree compare <acronym title="Graphical User Interface">GUI</acronym>. This uses the same color scheme as the file compare to show you files that have been added, deleted, or changed between two directory trees:
</p>

<p>
<a href="/wiki/lib/exe/detail.php/reviews/byname/guiffy_suremerge/8-directorycompare.png?id=reviews%3Abyname%3Aguiffy_suremerge%3A20060706&amp;cache=cache" class="media" title="reviews:byname:guiffy_suremerge:8-directorycompare.png"><img src="/wiki/lib/exe/fetch.php/reviews/byname/guiffy_suremerge/8-directorycompare.png?w=400&amp;h=&amp;cache=cache" class="media" title="Screenshot of directory compare" alt="Screenshot of directory compare" width="400" /></a>
</p>

<p>
This is a great place to start when you are trying to understand what has happened to your code. Seeing the higher-level view of what has been changed lets you organize your approach to understanding and/or merging the changes. The interface is visually clean and attractive, as well as intuitive. The obvious tools to fix to directory tree issues—copying, renaming, and and deleting files—are supported in the tree view. I do have a few gripes about this interface, however:  
</p>
<ul>
<li class="level1"><div class="li"> First, there is no indication at the directory level that children have changed. For a deep source tree this may make it harder to grasp the whole impact of a change. Mitigating this is the fact that the <acronym title="Graphical User Interface">GUI</acronym> takes you right to the first change, and you can use the next/previous change buttons to navigate.</div>
</li>
<li class="level1"><div class="li"> Second, <code>guiffy</code> doesn&#039;t do the “obvious” thing when dealing with trees. If I invoke <code>guiffy</code> with three or four directory names, as I would do for merging files, the tool doesn&#039;t automatically create the new “merged” directory tree. Neither does it correctly populate the “parent” field when I try to SureMerge a changed file. </div>
</li>
</ul>

<p>
 The former is evidence of how addictive and intuitive the rest of the product is: <em>of course</em> it will work this way—just bring up the directories and start resolving conflicts! It actually took me a while to grasp that I was wrong. The latter behavior—incorrectly populating the parent field—seems to be just a bug. <code>guiffy</code> remembers the last value I used, instead of populating it from the command line.
</p>
<ul>
<li class="level1"><div class="li"> Third, there is no good way to move files from one directory to another: the &#039;move&#039; operation is  an extended version of &#039;rename&#039;. I suspect this is a drag &amp; drop problem—there are some other issues with drag &amp; drop discussed later. For Java development in particular, this may be a problem when refactoring. (Or not: much refactoring will involve opening the &#039;rename&#039; dialog anyway—maybe combining move with rename won&#039;t be a problem.)</div>
</li>
</ul>

</div>
<!-- SECTION "Directory Compare" [11212-13555] -->
<h2><a name="features" id="features">Features</a></h2>
<div class="level2">

<p>
 In addition to fast, accurate 2- and 3-way merging, SureMerge includes
</p>
<ul>
<li class="level1"><div class="li"> jiff – a command-line compare utility</div>
</li>
</ul>
<ul>
<li class="level1"><div class="li"> suremerge – a command-line merge utility</div>
</li>
</ul>
<ul>
<li class="level1"><div class="li"> Recursive comparison of directory hierarchies in guiffy and jiff</div>
</li>
</ul>
<ul>
<li class="level1"><div class="li"> <acronym title="HyperText Markup Language">HTML</acronym> comparison reports in guiffy</div>
</li>
</ul>
<ul>
<li class="level1"><div class="li"> Support for international character encodings</div>
</li>
</ul>
<ul>
<li class="level1"><div class="li"> A Java <acronym title="Application Programming Interface">API</acronym> for integrating SureMerge functionality into your own programs.</div>
</li>
</ul>
<ul>
<li class="level1"><div class="li"> Really responsive support</div>
</li>
</ul>

<p>
There&#039;s a wealth of other features listed at <a href="http://www.guiffy.com" class="urlextern" title="http://www.guiffy.com"  rel="nofollow">http://www.guiffy.com</a> but these stand out as being important for automation and build/team management.
</p>

</div>
<!-- SECTION "Features" [13556-14162] -->
<h3><a name="jiff_command-line_utility" id="jiff_command-line_utility">Jiff command-line utility</a></h3>
<div class="level3">

<p>
 <code>jiff</code> is not <code>diff.</code> Instead, it is a command-line tool for showing differences. It does not use the diff algorithms (a feature: Guiffy claims their algorithms are better), it does not produce the eleventy-four different specialized formats for feeding to other tools. It does not use the same command-line switches: another feature, since <code>diff</code> does not have a switch for specifying the character encoding of the input files, while <code>jiff</code> does.
</p>

<p>
What <code>jiff</code> does is produce a very readable, very comprehensible text version of the results shown by the guiffy <acronym title="Graphical User Interface">GUI</acronym>. Here&#039;s an example:
</p>
<pre class="code">C:\\temp\\Guiffy review\\perl&gt;jiff db2.pl db4.pl
  1  1 open (INPUT, &quot;&lt; $filepageid&quot;) || &amp;file_open_error(&quot;$filepageid&quot;);
  2  2
  3  3 while ($riga=&lt;INPUT&gt;){
  4  4     $nump++;
  5  5     chop($riga);
  6  6     $pagina[$nump] = $riga;
  7  7
  8   &lt;    $sth= $dbh-&gt;prepare(&quot;SELECT count(*) FROM lognew WHERE
  9   &lt;                         pageid=&#039;$pagina[$nump]&#039; and data&gt;=&#039;$startdate&#039;&quot;);
 10   &lt;    $sth-&gt;execute;
 11   &lt;    $totalvisit[$nump] = $sth-&gt;fetchrow_array();
     8&gt;    my $totalvisit_sth = $dbh-&gt;prepare(&#039;SELECT count(*) FROM lognew WHERE
     9&gt;                                        pageid=? and data&gt;=?&#039;);
    10&gt;    $totalvisit_sth-&gt;execute($pagina[$nump], $startdate);
    11&gt;    $totalvisit[$nump] = $totalvisit_sth-&gt;fetchrow_array();
 12 12</pre>

<p>
 <code>jiff</code> offers a directory-compare behavior similar to <code>guiffy</code>, but I had a few problems with this. 
</p>
<ul>
<li class="level1"><div class="li"> First, I expected <code>jiff -r</code> to behave just like <code>diff -r</code>: that was arguably my problem. Instead, <code>jiff -r</code> does just a tree comparison: it does not show file differences as it goes.</div>
</li>
</ul>
<ul>
<li class="level1"><div class="li"> Second, getting <code>jiff -r</code> to show files that have changed between the two trees requires specifying the <code>-bxt</code> (Verify files match) option: this one even stumped the author for a while. <a href="#fn__3" name="fnt__3" id="fnt__3" class="fn_top">3)</a></div>
</li>
</ul>
<ul>
<li class="level1"><div class="li"> Third, the option syntax is awkward: <code>-diffs</code> shows “only the differences” for files, but <code>-nomats</code> shows “no matching files” for folder comparisons.</div>
</li>
</ul>
<ul>
<li class="level1"><div class="li"> Finally, the folder compare wants to show the names of folders it has checked, even if there were no differences: <code>-nomats</code> didn&#039;t prevent it from burying my file changes amid a maze of directory names, all alike:</div>
</li>
</ul>
<pre class="code">    &lt;DIR&gt;     10-Apr-2006 22:48:55 libs
    &lt;DIR&gt;     10-Apr-2006 22:48:45 \\libs\\action
    &lt;DIR&gt;     10-Apr-2006 22:48:45 \\libs\\action\\controller
    &lt;DIR&gt;     10-Apr-2006 22:48:45 \\libs\\action\\controller\\http
    &lt;DIR&gt;     10-Apr-2006 22:48:45 \\libs\\action\\controller\\session
    &lt;DIR&gt;     10-Apr-2006 22:48:45 \\libs\\action\\controller\\templates
    &lt;DIR&gt;     10-Apr-2006 22:48:45 \\libs\\action\\view
    &lt;DIR&gt;     10-Apr-2006 22:48:46 \\libs\\active
    &lt;DIR&gt;     10-Apr-2006 22:50:47 \\libs\\active\\record
&lt;       4,284 10-Apr-2006 22:55:50 \\libs\\active\\record\\Field.php
&lt;          13 10-Apr-2006 22:50:47 \\libs\\active\\record\\NewFile.php
&gt;       4,288 10-Apr-2006 22:56:24 \\libs\\active\\record\\Field.php
    &lt;DIR&gt;     10-Apr-2006 22:48:46 \\libs\\active\\support
    &lt;DIR&gt;     10-Apr-2006 22:48:46 \\libs\\configurator
    &lt;DIR&gt;     10-Apr-2006 22:48:46 \\libs\\context
    &lt;DIR&gt;     10-Apr-2006 22:48:53 \\libs\\creole
    &lt;DIR&gt;     10-Apr-2006 22:48:48 \\libs\\creole\\common
    &lt;DIR&gt;     10-Apr-2006 22:48:48 \\libs\\creole\\contrib
    &lt;DIR&gt;     10-Apr-2006 22:48:53 \\libs\\creole\\drivers
    &lt;DIR&gt;     10-Apr-2006 22:48:49 \\libs\\creole\\drivers\\mssql
    &lt;DIR&gt;     10-Apr-2006 22:48:49 \\libs\\creole\\drivers\\mssql\\metadata
    &lt;DIR&gt;     10-Apr-2006 22:48:50 \\libs\\creole\\drivers\\mysql
    &lt;DIR&gt;     10-Apr-2006 22:48:50 \\libs\\creole\\drivers\\mysql\\metadata
    &lt;DIR&gt;     10-Apr-2006 22:48:51 \\libs\\creole\\drivers\\mysqli</pre>

</div>
<!-- SECTION "Jiff command-line utility" [14163-18092] -->
<h3><a name="suremerge_command-line_utility" id="suremerge_command-line_utility">SureMerge command-line utility</a></h3>
<div class="level3">

<p>
 Where <code>jiff</code> would accept a relative path on the command line, like <code>jiff  med2\\libs\\active\\record\\field.php  med3\\libs\\active\\record\\field.php</code> <code>suremerge</code> would not. Needless to say, <code>suremerge</code> and I did not get off to a great start. 
</p>

<p>
In addition, it has problems parsing directory names that include spaces on Windows. When I specified a directory with a leading quote, as “C:\\MyDocuments\\Sources\\Php Data Layer”\\med2\\&hellip; all was well. If I tried to use quotes inside the directory, as C:\\MyDocuments\\Sources\\“Php Data Layer”\\med2\\&hellip; then I got a usage statement, and eventually a sore forehead from banging it against my desk. This is documented in the help text, but it&#039;s just a little bit different from common Windows behavior. 
</p>

<p>
Apparently, <code>suremerge</code> makes no use whatsoever of the current directory. It does not resolve relative paths against it, and it will not use it to resolve its output file, either. Once you overcome these challenges, though, <code>suremerge</code> does just exactly what you expected it would do: it performs the same merges from the command line that <code>guiffy</code> does from the <acronym title="Graphical User Interface">GUI</acronym>. The remaining problem, of course, is when lines conflict with each other. Anyone who has used <acronym title="Concurrent Versions System">CVS</acronym> will be familiar with the result: 
</p>
<pre class="code">&lt;&lt;&lt;&lt;&lt;&lt;&lt; C:\\mydocuments\\Sources\\php data layer\\med2\\libs\\active\\record\\Field.php
class Field extends Object implements Persistable {
=======
class Field extends Object 
	implements Persistant 
{
&gt;&gt;&gt;&gt;&gt;&gt;&gt; c:\\mydocuments\\Sources\\php data layer\\med3\\libs\\active\\record\\Field.php</pre>

<p>
 Because of Guiffy&#039;s improved algorithms, <code>suremerge</code> will have fewer of these conflict spots than other tools. And once you get the command line quirks figured out, it&#039;s easy to script around them. But it&#039;s still awkward: effective, but awkward.
</p>

</div>
<!-- SECTION "SureMerge command-line utility" [18093-19970] -->
<h3><a name="html_comparison_reports" id="html_comparison_reports">HTML comparison reports</a></h3>
<div class="level3">

<p>
 The <code>guiffy</code> tree comparison feature is a very nice way to get a sense of what has changed in a project. Automatically generating an <acronym title="HyperText Markup Language">HTML</acronym> document that looks like the <acronym title="Graphical User Interface">GUI</acronym> would be really nice. Putting the changes out where everyone can see them provides the kind of easy visibility that is important when project members aren&#039;t working tightly together. 
</p>

<p>
<code>guiffy</code>&#039;s <acronym title="HyperText Markup Language">HTML</acronym> reports don&#039;t look exactly like their <acronym title="Graphical User Interface">GUI</acronym> counterparts, but they sure are close:
</p>

<p>
<a href="/wiki/lib/exe/detail.php/reviews/byname/guiffy_suremerge/9-htmlreport72.png?id=reviews%3Abyname%3Aguiffy_suremerge%3A20060706&amp;cache=cache" class="media" title="reviews:byname:guiffy_suremerge:9-htmlreport72.png"><img src="/wiki/lib/exe/fetch.php/reviews/byname/guiffy_suremerge/9-htmlreport72.png?w=400&amp;h=&amp;cache=cache" class="media" title="" alt="" width="400" /></a>
</p>

<p>
The changes are highlighted using the same colors as the <acronym title="Graphical User Interface">GUI</acronym>, including the character-by-character highlighting. Obviously you can&#039;t change the highlight options in mid-stream, as you can with the <acronym title="Graphical User Interface">GUI</acronym>.
</p>

<p>
The directory comparison is a little less close to the <acronym title="Graphical User Interface">GUI</acronym>. It doesn&#039;t show the folder tree view. Instead, it looks more like the output of <code>jiff -r.</code> Regardless, it gets the information across:
</p>

<p>
<a href="/wiki/lib/exe/detail.php/reviews/byname/guiffy_suremerge/10-htmlreport73.png?id=reviews%3Abyname%3Aguiffy_suremerge%3A20060706&amp;cache=cache" class="media" title="reviews:byname:guiffy_suremerge:10-htmlreport73.png"><img src="/wiki/lib/exe/fetch.php/reviews/byname/guiffy_suremerge/10-htmlreport73.png?w=400&amp;h=&amp;cache=cache" class="media" title="" alt="" width="400" /></a>
</p>

<p>
The <acronym title="HyperText Markup Language">HTML</acronym> reporting capability seems new, according to the release history, and I found some rough spots that support this:
</p>
<ul>
<li class="level1"><div class="li"> Did you notice that the header says the folder compare report was produced by version 7.3—yet this is supposed to be a review of version 7.2? Well, I&#039;ve got a beta! I found a bug in the <acronym title="HyperText Markup Language">HTML</acronym> reporting: <code>guiffy</code> hangs when asked to generate folder reports in version 7.2. So I&#039;m looking at an early image of the next version. (I didn&#039;t install the new .jar until time to come back and finish this section. Everything else for this review was generated on 7.2.)</div>
</li>
</ul>
<ul>
<li class="level1"><div class="li"> I also found a problem with long lines. In the image below you can tell that a character has changed in the left file (because of the red color) but you can&#039;t see what it is:</div>
</li>
</ul>

<p>
 <a href="/wiki/lib/exe/detail.php/reviews/byname/guiffy_suremerge/11-htmlreportlonglineproblemff.png?id=reviews%3Abyname%3Aguiffy_suremerge%3A20060706&amp;cache=cache" class="media" title="reviews:byname:guiffy_suremerge:11-htmlreportlonglineproblemff.png"><img src="/wiki/lib/exe/fetch.php/reviews/byname/guiffy_suremerge/11-htmlreportlonglineproblemff.png?w=400&amp;h=&amp;cache=cache" class="media" title="" alt="" width="400" /></a>
</p>

<p>
This is a Firefox problem, though, not a Guiffy problem. The same page looks fine in Internet Explorer 6.0:
</p>

<p>
<a href="/wiki/lib/exe/detail.php/reviews/byname/guiffy_suremerge/12-htmlreportlonglineproblemie.png?id=reviews%3Abyname%3Aguiffy_suremerge%3A20060706&amp;cache=cache" class="media" title="reviews:byname:guiffy_suremerge:12-htmlreportlonglineproblemie.png"><img src="/wiki/lib/exe/fetch.php/reviews/byname/guiffy_suremerge/12-htmlreportlonglineproblemie.png?w=400&amp;h=&amp;cache=cache" class="media" title="" alt="" width="400" /></a>
</p>

<p>
I had a look at the generated <acronym title="HyperText Markup Language">HTML</acronym>, and it&#039;s <em>clean.</em> I think this one is a Firefox (actually, Gecko rendering engine) error. 
</p>
<ul>
<li class="level1"><div class="li"> Finally, errors like invalid filenames (or missing files, if you prefer) don&#039;t return a status code, they display a dialog box. This is definitely not good for a scripted solution.</div>
</li>
</ul>
<ul>
<li class="level1"><div class="li"> This is a feature request, but I think it would make sense for the <acronym title="HyperText Markup Language">HTML</acronym> report generator to produce a whole web of linked comparison reports: specify a switch, and get a whole series of output files, hyperlinked together, showing all the changed files.</div>
</li>
</ul>

<p>
  The format of the generated <acronym title="HyperText Markup Language">HTML</acronym> is very clean, and uses <acronym title="Cascading Style Sheets">CSS</acronym> tags for displaying changed entries. I think that a good perl coder could probably get the linkages going in a day or so. But it would be better if he didn&#039;t have to.
</p>

</div>
<!-- SECTION "HTML comparison reports" [19971-22827] -->
<h3><a name="international_character_encodings" id="international_character_encodings">International Character Encodings</a></h3>
<div class="level3">

<p>
 Consider this image of a <code>guiffy</code> compare of two versions of a file
</p>

<p>
<a href="/wiki/lib/exe/detail.php/reviews/byname/guiffy_suremerge/13-differentencodings.png?id=reviews%3Abyname%3Aguiffy_suremerge%3A20060706&amp;cache=cache" class="media" title="reviews:byname:guiffy_suremerge:13-differentencodings.png"><img src="/wiki/lib/exe/fetch.php/reviews/byname/guiffy_suremerge/13-differentencodings.png?w=400&amp;h=&amp;cache=cache" class="media" title="" alt="" width="400" /></a>
</p>

<p>
What&#039;s interesting about this result is the nature of the inputs: one of these files is encoded as a plain old <acronym title="American Standard Code for Information Interchange">ASCII</acronym> text file (technically, Windows codepage 1252) while the other is UTF16. Here&#039;s a different way of looking at them: 
</p>
<pre class="code">C:\\MyDocuments\\Sources\\Php Data Layer&gt;sed -ne 41p field.uni.txt|od -t x1z
0000000 00 63 00 6c 00 61 00 73 00 73 00 20 00 46 00 69  &gt;.c.l.a.s.s. .F.i&lt;
0000020 00 65 00 6c 00 64 00 20 00 65 00 78 00 74 00 65  &gt;.e.l.d. .e.x.t.e&lt;
0000040 00 6e 00 64 00 73 00 20 00 4f 00 62 00 6a 00 65  &gt;.n.d.s. .O.b.j.e&lt;
0000060 00 63 00 74 00 20 00 69 00 6d 00 70 00 6c 00 65  &gt;.c.t. .i.m.p.l.e&lt;
0000100 00 6d 00 65 00 6e 00 74 00 73 00 20 00 50 00 65  &gt;.m.e.n.t.s. .P.e&lt;
0000120 00 72 00 73 00 69 00 73 00 74 00 61 00 62 00 6c  &gt;.r.s.i.s.t.a.b.l&lt;
0000140 00 65 00 20 00 7b 00 0d 00 0a                    &gt;.e. .{....&lt;
0000152

C:\\MyDocuments\\Sources\\Php Data Layer&gt;sed -ne 41p field.php|od -t x1z
0000000 63 6c 61 73 73 20 46 69 65 6c 64 20 65 78 74 65  &gt;class Field exte&lt;
0000020 6e 64 73 20 42 61 73 65 20 69 6d 70 6c 65 6d 65  &gt;nds Base impleme&lt;
0000040 6e 74 73 20 50 65 72 73 69 73 74 61 62 6c 65 20  &gt;nts Persistable &lt;
0000060 7b 0a                                            &gt;{.&lt;
0000062</pre>

<p>
 As you can see, the two files are totally different internally: two different character sets, two different encodings. By telling <code>guiffy</code> about the file encodings of each file—via the command line or a dialog box—the compare engine knows to ignore the encoding and focus on what&#039;s important: the contents of the files! 
</p>

<p>
<code>guiffy</code> allows you to separately specify the encodings of the two primary files, the optional parent file for 3-way compare/merge operations, and the output file for merges. I recently worked at a client site where we would have been thankful just to be able to specify the input encodings: what a shame we didn&#039;t have <code>guiffy.</code>
</p>

<p>
One of the problems with multibyte characters is how to deal with “broken” or invalid character sequences. <code>guiffy</code> handles them fairly well: the invalid sequences are displayed as invalid characters. In this scenario you&#039;re probably going to need to hex dump the bytes to see exactly what went wrong (unless you just go fix the program that produced them).
</p>

<p>
The support for output encodings even extends to <acronym title="HyperText Markup Language">HTML</acronym> reports. Specifying the output encoding produces an <acronym title="HyperText Markup Language">HTML</acronym> document with the correct encoding and content-type metadata:
</p>

<p>
<a href="/wiki/lib/exe/detail.php/reviews/byname/guiffy_suremerge/14-htmlheader.png?id=reviews%3Abyname%3Aguiffy_suremerge%3A20060706&amp;cache=cache" class="media" title="reviews:byname:guiffy_suremerge:14-htmlheader.png"><img src="/wiki/lib/exe/fetch.php/reviews/byname/guiffy_suremerge/14-htmlheader.png?w=400&amp;h=&amp;cache=cache" class="media" title="" alt="" width="400" /></a>
</p>

<p>
Or, you could look at it this way (notice the byte-order-mark: U+FEFF): 
</p>
<pre class="code">C:\\MyDocuments\\Sources\\Php Data Layer&gt;head -1 diff.html | od -t x1z
0000000 fe ff 00 3c 00 21 00 44 00 4f 00 43 00 54 00 59  &gt;...&lt;.!.D.O.C.T.Y&lt;
0000020 00 50 00 45 00 20 00 48 00 54 00 4d 00 4c 00 20  &gt;.P.E. .H.T.M.L. &lt;
0000040 00 50 00 55 00 42 00 4c 00 49 00 43 00 20 00 22  &gt;.P.U.B.L.I.C. .&quot;&lt;
0000060 00 2d 00 2f 00 2f 00 57 00 33 00 43 00 2f 00 2f  &gt;.-././.W.3.C././&lt;
0000100 00 44 00 54 00 44 00 20 00 48 00 54 00 4d 00 4c  &gt;.D.T.D. .H.T.M.L&lt;
0000120 00 20 00 34 00 2e 00 30 00 31 00 20 00 54 00 72  &gt;. .4...0.1. .T.r&lt;
0000140 00 61 00 6e 00 73 00 69 00 74 00 69 00 6f 00 6e  &gt;.a.n.s.i.t.i.o.n&lt;
0000160 00 61 00 6c 00 2f 00 2f 00 45 00 4e 00 22 00 20  &gt;.a.l././.E.N.&quot;. &lt;
0000200 00 22 00 68 00 74 00 74 00 70 00 3a 00 2f 00 2f  &gt;.&quot;.h.t.t.p.:././&lt;
0000220 00 77 00 77 00 77 00 2e 00 77 00 33 00 2e 00 6f  &gt;.w.w.w...w.3...o&lt;
0000240 00 72 00 67 00 2f 00 54 00 52 00 2f 00 68 00 74  &gt;.r.g./.T.R./.h.t&lt;
0000260 00 6d 00 6c 00 34 00 2f 00 6c 00 6f 00 6f 00 73  &gt;.m.l.4./.l.o.o.s&lt;
0000300 00 65 00 2e 00 64 00 74 00 64 00 22 00 3e 00 0d  &gt;.e...d.t.d.&quot;.&gt;..&lt;
0000320 00 0a   </pre>

<p>
 Looking at the release history of the product, the release 7.x series seems to have had a strong focus on support for international encodings. It sure looks like they did it right. On a side note, remember this illustration from above?
</p>

<p>
<a href="/wiki/lib/exe/detail.php/reviews/byname/guiffy_suremerge/2-characterbycharacter.png?id=reviews%3Abyname%3Aguiffy_suremerge%3A20060706&amp;cache=cache" class="media" title="reviews:byname:guiffy_suremerge:2-characterbycharacter.png"><img src="/wiki/lib/exe/fetch.php/reviews/byname/guiffy_suremerge/2-characterbycharacter.png?w=&amp;h=&amp;cache=cache" class="media" title="" alt="" /></a>
</p>

<p>
I cheated a little bit: those are actually Unicode “fullwidth” characters used when typesetting mixed Latin and CJK text. This has been an “internationalized” review from the very start!
</p>

</div>
<!-- SECTION "International Character Encodings" [22828-27201] -->
<h3><a name="java_api" id="java_api">Java API</a></h3>
<div class="level3">

<p>
 I didn&#039;t explore the Java <acronym title="Application Programming Interface">API</acronym> for this review. I can document that it exists, and that it&#039;s very complete. It&#039;s called <code>guiffy.inside,</code> and it includes all the functions of all of the different flavors of the product, both <acronym title="Graphical User Interface">GUI</acronym> and command-line. It also includes a “hook” mechanism for modifying the behavior of the existing application.
</p>

<p>
On the command-line side, there are <acronym title="Application Programming Interface">API</acronym> equivalents for the <code>jiff</code> and <code>suremerge</code> commands so that you can create a windowless compare/merge subsystem inside your own programs. Also, there&#039;s a separate <acronym title="Application Programming Interface">API</acronym> for the <acronym title="HyperText Markup Language">HTML</acronym> report generator.
</p>

<p>
There are two interfaces for <acronym title="Graphical User Interface">GUI</acronym> products. The first, called a Frame, essentially pops up the Guiffy application window, menus, dialog boxes, and all. The second, called a Panel, lets you put the Guiffy compare/merge screen inside your application&#039;s window. There&#039;s no menu, and no toolbars, in the Panel version: you get tight integration with your app, but you have to write the supporting code to pick up filenames and encodings and such. 
</p>

<p>
Finally, there&#039;s a hook mechanism so that you can detect the merge result on exit and trigger some behavior. It seems Guiffy is just about as easy as can be to integrate with another application, like a CM tool or a build script or a continuous integration driver. Because this is all in Java, you can build it into an applet running on a web page. Make it a signed applet and your users can do compare and merge operations against their desktop, and you won&#039;t even have to install the product on their machines. (You should probably call and ask about licensing, though.)
</p>

</div>
<!-- SECTION "Java API" [27202-28826] -->
<h2><a name="support" id="support">Support</a></h2>
<div class="level2">

<p>
 Guiffy support is just amazingly responsive!
</p>

<p>
I started this review by visiting the website (<a href="http://www.guiffy.com" class="urlextern" title="http://www.guiffy.com"  rel="nofollow">http://www.guiffy.com</a>) and downloading the demo version, along with the sample scenarios for compare &amp; merge. When I asked questions by e-mail, I was amazed to get responses at four o&#039;clock in the morning. I was happy to find they were knowledgeable technical answers from someone who could understand what tasks I wanted to do, and how they should work. I also got responses in the afternoon and evening. If anyone in Missouri ever sleeps, you couldn&#039;t prove it by me.
</p>

</div>
<!-- SECTION "Support" [28827-29412] -->
<h2><a name="accuracy" id="accuracy">Accuracy</a></h2>
<div class="level2">

<p>
 SureMerge offers two different modes for grouping changes together. You can choose to see more blocks of changed text, with small numbers of lines, or you can permit grouping of changes into a smaller number of individually bigger blocks. I was unable to detect a difference in the modestly sized files I used for testing purposes.
</p>

<p>
<a href="/wiki/lib/exe/detail.php/reviews/byname/guiffy_suremerge/15-accuracy.png?id=reviews%3Abyname%3Aguiffy_suremerge%3A20060706&amp;cache=cache" class="media" title="reviews:byname:guiffy_suremerge:15-accuracy.png"><img src="/wiki/lib/exe/fetch.php/reviews/byname/guiffy_suremerge/15-accuracy.png?w=400&amp;h=&amp;cache=cache" class="media" title="" alt="" width="400" /></a>
</p>

<p>
For my purposes, the accuracy of the tool is &#039;pinpoint.&#039; Changes are identified down to the individual characters that differ. It doesn&#039;t get any better than that.
</p>

</div>
<!-- SECTION "Accuracy" [29413-29990] -->
<h2><a name="performance" id="performance">Performance</a></h2>
<div class="level2">

<p>
 SureMerge is a set of Java applications with a shell or Windows executable front-end. I was a little nervous about this, after having a bad time starting up Eclipse. SureMerge is definitely not Eclipse: it starts up just fine. Likewise, doing compares is quick even for large(-ish) files. I used some international dictionary files to test both large file operations and international character set support. It takes Guiffy about 15 seconds to re-compare two versions of a 1.7MB Russian dictionary on my two-year-old laptop. Very nice!
</p>

<p>
For this test, I wrote a perl script to randomly “mutate” about one percent of the lines: delete or move the line, or insert or transpose characters:
</p>

<p>
<a href="/wiki/lib/exe/detail.php/reviews/byname/guiffy_suremerge/16-largefiles.png?id=reviews%3Abyname%3Aguiffy_suremerge%3A20060706&amp;cache=cache" class="media" title="reviews:byname:guiffy_suremerge:16-largefiles.png"><img src="/wiki/lib/exe/fetch.php/reviews/byname/guiffy_suremerge/16-largefiles.png?w=400&amp;h=&amp;cache=cache" class="media" title="" alt="" width="400" /></a>
</p>

<p>
The help documentation includes notes for comparing large files when the files have large blocks of changes in them. The change is simply to let SureMerge allocate more memory to work in: everything else is taken care of. I guess that change is required if the files are more different than they are similar, because my files were way over the threshold for needing more memory, yet guiffy worked just fine out of the box.
</p>

</div>
<!-- SECTION "Performance" [29991-31191] -->
<h2><a name="ease_of_use" id="ease_of_use">Ease of Use</a></h2>
<div class="level2">

<p>
 SureMerge is a tool with some complex features. Overall, the interface is very smooth and self-explanatory. Most advanced operations are explained well by the surrounding menus and dialog box text, with no need to refer to the online help.
</p>

<p>
That said, I have some complaints. (I&#039;ll bet you didn&#039;t see that coming.) 
</p>
<ul>
<li class="level1"><div class="li"> First is support for drag &amp; drop. I&#039;m using a modern JRE (1.5), and yet the drag &amp; drop is all but unusable: the drop targets are the top and bottom <em>row of pixels</em> of the file name combo boxes on the file open dialog.</div>
</li>
</ul>

<p>
 As I understand it from talking to the author, this is a defect in the Java UI libraries. That doesn&#039;t excuse it at the product level: a one-pixel drop target is not a drop target. As clunky as it may be, Guiffy needs to make this work—either code their own <acronym title="Graphical User Interface">GUI</acronym> widgets (blech!) or add an ugly “Drop Here” box (blech!).  
</p>
<ul>
<li class="level1"><div class="li"> Second, integrating <code>guiffy</code> with Windows Explorer is documented in a Tech Note in the on-line help. I believe the installer should perform the simple steps automatically on installation.</div>
</li>
</ul>
<ul>
<li class="level1"><div class="li"> Finally, the dialog box for choosing character encodings needs work. Presently, the encodings are specified as text entry boxes: you type in the encodings. But since the list of supported encodings is known in advance, this should be a drop-down list or a combo list. It was frustrating to be told I needed an additional file:</div>
</li>
</ul>

<p>
 <a href="/wiki/lib/exe/detail.php/reviews/byname/guiffy_suremerge/17-encodingerror.png?id=reviews%3Abyname%3Aguiffy_suremerge%3A20060706&amp;cache=cache" class="media" title="reviews:byname:guiffy_suremerge:17-encodingerror.png"><img src="/wiki/lib/exe/fetch.php/reviews/byname/guiffy_suremerge/17-encodingerror.png?w=&amp;h=&amp;cache=cache" class="media" title="" alt="" /></a>
</p>

<p>
It was even more frustrating to realize that the encoding I wanted was supported, just spelled differently (&#039;koi8&#039;). I&#039;m sure that if you spend all day every day in a particular encoding you know how to spell it. But if you have to deal with different encodings on a regular basis, a pull-down list is your friend.
</p>

<p>
Overall, the product itself is very easy to use and install. But it could be better integrated with the desktop, and the user interface needs to be a little bit more helpful.
</p>

</div>
<!-- SECTION "Ease of Use" [31192-33164] -->
<h2><a name="effectiveness" id="effectiveness">Effectiveness</a></h2>
<div class="level2">

<p>
 SureMerge gets the job done. It gets the job done <em>well.</em> The tool is fast, it is accurate, and it is easy to use. Using the file-encoding feature lets you view changes at both the &#039;byte&#039; level and at the &#039;code point&#039; level. You can see that a character has changed, or you can switch views and see just exactly how the binary expression of that character has changed. For anyone dealing with i18n issues this is a godsend.
</p>

<p>
Included in the on-line help are instructions for integrating SureMerge with eight different CM tools. For PVCS, Guiffy even includes a specially built executable that replaces the <code>pvcsmerge</code> program for seamless integration. (Support for the other tools is probably just as seamless, but they offer configuration options to let you set the name of the merge tool so Guiffy doesn&#039;t have to ship eight different executables.)
</p>

<p>
The addition of batch reporting facilities and <acronym title="HyperText Markup Language">HTML</acronym> report generation makes SureMerge a valuable tool for a whole team, not just individual developers. Now change sets and impact statements can be automatically displayed from an intranet dashboard. Continuous integration and nightly build scripts can be extended to produce clear, detailed, attractive code change summaries. Sweet!
</p>

</div>
<!-- SECTION "Effectiveness" [33165-34431] -->
<h2><a name="cost" id="cost">Cost</a></h2>
<div class="level2">

<p>
 Single-user licenses for SureMerge are USD $75. Price breaks occur at 3 users (3/$150) and again at 36 users. SureMerge is a good value for managers or team leads looking to provide a standard tool to their developers.
</p>

</div>
<!-- SECTION "Cost" [34432-34669] -->
<h2><a name="conclusion" id="conclusion">Conclusion</a></h2>
<div class="level2">

<p>
 SureMerge is a solid, capable tool, as you would expect from a 7.2 release. It performs well and does a great job helping developers, build managers, team leads, and other players in the development cycle understand exactly what is going on with the code. The <acronym title="Graphical User Interface">GUI</acronym> itself is easy to use and is available in several languages. The tool is obviously growing, with international encoding support and <acronym title="HyperText Markup Language">HTML</acronym> report generations being the most recent major features added. Guiffy, the company, is personified by owner Bill Ritcher: quick to respond, helpful, and willing to work with you to help get over any problems. I like the tool, and you will, too.
</p>

</div>
<!-- SECTION "Conclusion" [34670-] --><div class="footnotes">
<div class="fn"><a href="#fnt__1" id="fn__1" name="fn__1" class="fn_bot">1)</a> 
Yes, that&#039;s “goofy gooey.” I&#039;m sorry, but it&#039;s Bill Ritcher&#039;s fault.</div>
<div class="fn"><a href="#fnt__2" id="fn__2" name="fn__2" class="fn_bot">2)</a> 
On the other hand, if you are a mad scientist trying to turn a monkey into an armadillo, this is the tool for you!</div>
<div class="fn"><a href="#fnt__3" id="fn__3" name="fn__3" class="fn_bot">3)</a> 
According to Bill Ritcher, this will be better documented in the 7.3 release.</div>
</div>

<!-- cachefile /home/ahasting/public_html/wiki/data/cache/c/c7e95af143d233250fe23fb58b0b6c60.xhtml used -->

</div>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2008/04/reviews-byname-guiffy_suremerge-20060706/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[wiki &#124; tools:byname:guiffy_suremerge]</title>
		<link>http://www.longacre-scm.com/blog/index.php/2008/04/tools-byname-guiffy_suremerge</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2008/04/tools-byname-guiffy_suremerge#comments</comments>
		<pubDate>Fri, 18 Apr 2008 13:31:03 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/index.php/2008/04/[[tools:byname:guiffy_suremerge]]</guid>
		<description><![CDATA[



Guiffy SureMerge



 SureMerge is a Java-based tool for both compare and merge operations. The tool is the primary focus of Guiffy Software. Austin Hastings wrote a review of the tool for the CM Crossroads web site. That review is available here, as well. 







]]></description>
			<content:encoded><![CDATA[<div class="dokuwiki">



<h1><a name="guiffy_suremerge" id="guiffy_suremerge">Guiffy SureMerge</a></h1>
<div class="level1">

<p>
 SureMerge is a Java-based tool for both <a href="/wiki/doku.php/tools/compare" class="wikilink1" title="tools:compare">compare</a> and <a href="/wiki/doku.php/tools/merge" class="wikilink2" title="tools:merge">merge</a> operations. The tool is the primary focus of <a href="http://www.guiffy.com" class="urlextern" title="http://www.guiffy.com"  rel="nofollow">Guiffy Software.</a> <a href="mailto:&#x41;&#x75;&#x73;&#x74;&#x69;&#x6e;&#x5f;&#x48;&#x61;&#x73;&#x74;&#x69;&#x6e;&#x67;&#x73;&#x40;&#x4c;&#x6f;&#x6e;&#x67;&#x61;&#x63;&#x72;&#x65;&#x2d;&#x73;&#x63;&#x6d;&#x2e;&#x63;&#x6f;&#x6d;" class="mail JSnocheck" title="&#x41;&#x75;&#x73;&#x74;&#x69;&#x6e;&#x5f;&#x48;&#x61;&#x73;&#x74;&#x69;&#x6e;&#x67;&#x73;&#x40;&#x4c;&#x6f;&#x6e;&#x67;&#x61;&#x63;&#x72;&#x65;&#x2d;&#x73;&#x63;&#x6d;&#x2e;&#x63;&#x6f;&#x6d;">Austin Hastings</a> wrote a <a href="http://www.cmcrossroads.com/content/view/6777/96/" class="urlextern" title="http://www.cmcrossroads.com/content/view/6777/96/"  rel="nofollow">review</a> of the tool for the CM Crossroads web site. That review is available <a href="/wiki/doku.php/reviews/byname/guiffy_suremerge/20060706" class="wikilink1" title="reviews:byname:guiffy_suremerge:20060706">here,</a> as well. 
</p>

</div>

<!-- cachefile /home/ahasting/public_html/wiki/data/cache/0/0b8a8a7261318ff16cab782f67d3c151.xhtml used -->

</div>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2008/04/tools-byname-guiffy_suremerge/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[wiki &#124; tools:compare]</title>
		<link>http://www.longacre-scm.com/blog/index.php/2008/04/tools-compare</link>
		<comments>http://www.longacre-scm.com/blog/index.php/2008/04/tools-compare#comments</comments>
		<pubDate>Fri, 18 Apr 2008 12:50:09 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.longacre-scm.com/blog/index.php/2008/04/[[tools:compare]]</guid>
		<description><![CDATA[



Compare (diff) Tools



 diff is of course the archetype of this class of tools. There are various implementations of the Unix command line diff utility, but the GNU diffutils package is considered representative of all of these.    The tools are: 


 Beyond Compare

 diffutils

 Guiffy SureMerge








]]></description>
			<content:encoded><![CDATA[<div class="dokuwiki">



<h1><a name="compare_diff_tools" id="compare_diff_tools">Compare (diff) Tools</a></h1>
<div class="level1">

<p>
 <code>diff</code> is of course the archetype of this class of tools. There are various implementations of the Unix command line <code>diff</code> utility, but the GNU <code>diffutils</code> package is considered representative of all of these.    The tools are: 
</p>
<ul>
<li class="level1"><div class="li"> <a href="/wiki/doku.php/tools/byname/beyond_compare" class="wikilink2" title="tools:byname:beyond_compare">Beyond Compare</a></div>
</li>
<li class="level1"><div class="li"> <a href="/wiki/doku.php/tools/byname/diffutils" class="wikilink2" title="tools:byname:diffutils">diffutils</a></div>
</li>
<li class="level1"><div class="li"> <a href="/wiki/doku.php/tools/byname/guiffy_suremerge" class="wikilink1" title="tools:byname:guiffy_suremerge">Guiffy SureMerge</a></div>
</li>
</ul>

</div>

<!-- cachefile /home/ahasting/public_html/wiki/data/cache/d/d8e4aca065668e589654fe9246447394.xhtml used -->

</div>
]]></content:encoded>
			<wfw:commentRss>http://www.longacre-scm.com/blog/index.php/2008/04/tools-compare/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

