<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss version="2.0"><channel><title>Developer Blog Posts</title><link>http://www.review-board.org/news/</link><description>Latest Review Board developer blog posts</description><language>en-us</language><lastBuildDate>Sun, 21 Jun 2009 07:47:36 -0700</lastBuildDate><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/ReviewBoard" type="application/rss+xml" /><item><title>Review Board 1.0 Released!
</title><link>http://www.chipx86.com/blog/2009/06/20/review-board-10-released/</link><description>&lt;p&gt;&lt;a href="http://www.review-board.org/"&gt;&lt;img alt="Review Board 1.0" class="alignleft size-full wp-image-319" height="123" src="http://www.chipx86.com/blog/wp-content/uploads/2009/06/rb10.png" title="Review Board 1.0" width="130" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Tonight, we hit a milestone in the &lt;a href="http://www.review-board.org/"&gt;Review Board&lt;/a&gt; project that we&amp;#8217;ve been working toward for over two years. We finally pushed out our 1.0 release. A lot of blood, sweat and tears went into this release (okay, so not literally, but it was A LOT OF WORK!). The last few months in particular have been challenging, as we&amp;#8217;ve had to solve some tricky bugs and scalability problems, but the end result is pretty great.&lt;/p&gt;
&lt;p&gt;Just a short while ago, we &lt;a href="http://www.review-board.org/news/2009/06/20/review-board-10-released/"&gt;announced&lt;/a&gt; the release and put up an &lt;a href="http://www.review-board.org/docs/releasenotes/dev/reviewboard/1.0/"&gt;overview&lt;/a&gt; of the entire release and product. We&amp;#8217;ve already had some nice congratulatory e-mails and tweets, which is really nice :)&lt;/p&gt;
&lt;p&gt;Some stats for this release:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2 years, 9 months, 25 days have passed since our first commit.&lt;/li&gt;
&lt;li&gt;120 contributors have contributed to Review Board so far (in terms of code contributions).&lt;/li&gt;
&lt;li&gt;2,019 commits were made.&lt;/li&gt;
&lt;li&gt;899 review requests have been posted to our project&amp;#8217;s actual &lt;a href="http://reviews.review-board.org/"&gt;Review Board server&lt;/a&gt;. 1,650 users are registered on there.&lt;/li&gt;
&lt;li&gt;Our &lt;a href="http://demo.review-board.org/"&gt;demo server&lt;/a&gt;, in comparison, has 2,082 review requests filed and 10,154 users.&lt;/li&gt;
&lt;li&gt;938 bugs were filed. 812 were fixed.&lt;/li&gt;
&lt;li&gt;232 feature requests were filed. 101 were implemented. Most remaining ones are scheduled for releases.&lt;/li&gt;
&lt;li&gt;An estimated 200+ companies are now using Review Board. 26 have let us &lt;a href="http://www.review-board.org/users/"&gt;list them publicly&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The largest known Review Board install has over 83,000 filed review requests and over 2,000 users, doing upwards of 10GB of traffic per day.&lt;/li&gt;
&lt;li&gt;5 presentations on Review Board are known to have been given, 3 by us, 2 by others.&lt;/li&gt;
&lt;li&gt;552 users have joined our main mailing list, and 3,674 e-mails have been sent.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now that Review Board 1.0 is out, we can get started on some awesome new features we&amp;#8217;ve had planned. I have a little notebook full of ideas for our 1.1 and 1.5 releases (which may become 1.5 and 2.0, respectively, as this list grows). Some of the new features are actually ready to be committed within the next couple of days, so those of you using nightlies will start to see them soon.&lt;/p&gt;
&lt;p&gt;We were accepted into this year&amp;#8217;s &lt;a href="http://review-board.org/summer-of-code/"&gt;Summer of Code&lt;/a&gt;, and have three students working on exciting projects for us, so hopefully we&amp;#8217;ll start to see these trickle into the upcoming nightlies as well. Among these projects include diff viewer improvements (moved region detection, better whitespace-only change detection), IDE integration with Eclipse, and improved notification hooks and e-mail support.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re also working on providing support for third-party extensions, which will allow developers to extend Review Board in new, exciting ways without having to modify Review Board itself. This is especially handy for companies who wish to integrate better with their sandboxes, bug trackers or unit testing services. This will likely land in 1.5 (2.0?) at the earliest, as it&amp;#8217;s a large change, but the code for this mostly works today. It&amp;#8217;s just a matter of getting the codebase ready and figuring out what APIs we want to stabilize and expose.&lt;/p&gt;
&lt;p&gt;As I mentioned in the &lt;a href="http://www.review-board.org/news/2009/06/20/review-board-10-released/"&gt;release announcement&lt;/a&gt;, we&amp;#8217;re planning a release party, tentatively on July 11th, 2009, in the Bay Area (somewhere around Palo Alto, CA). If any Review Board users want to join us, please &lt;a href="http://tinyurl.com/rb1-release-party"&gt;RSVP!&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=vySeBU86Ujg:uJHUZuLTCYc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=vySeBU86Ujg:uJHUZuLTCYc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=vySeBU86Ujg:uJHUZuLTCYc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=vySeBU86Ujg:uJHUZuLTCYc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=vySeBU86Ujg:uJHUZuLTCYc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=vySeBU86Ujg:uJHUZuLTCYc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=vySeBU86Ujg:uJHUZuLTCYc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><author>chipx86@chipx86.com (chipx86)</author><pubDate>Sun, 21 Jun 2009 07:47:36 -0700</pubDate><guid>http://www.chipx86.com/blog/2009/06/20/review-board-10-released/</guid></item><item><title>Review Board: Summer of Code, Roadmap and Future Plans
</title><link>http://www.chipx86.com/blog/2009/04/02/review-board-summer-of-code-roadmap-and-future-plans/</link><description>&lt;p&gt;&lt;b&gt;Summer of Code&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;This year, we (the &lt;a href="http://www.review-board.org/"&gt;Review Board&lt;/a&gt; project) was given the opportunity to participate in Google&amp;#8217;s Summer of Code. We&amp;#8217;ve received some great student proposals so far, and I think we&amp;#8217;ll see exciting work done on Review Board this summer.&lt;/p&gt;
&lt;p&gt;The deadline for Summer of Code is coming up fast (April 3rd, 19:00 UTC). If you&amp;#8217;re interested in working on Review Board and haven&amp;#8217;t yet applied, it&amp;#8217;s not too late, but you&amp;#8217;ll want to hurry. Skim through our &lt;a href="http://www.review-board.org/wiki/Summer_of_Code_Ideas"&gt;ideas&lt;/a&gt; page and, if you find something interesting or have a great idea not listed here, then &lt;a href="http://socghop.appspot.com/"&gt;apply&lt;/a&gt; and tell us your plans. I can say we&amp;#8217;ve received several proposals so far for the installer and admin UI, so unless you feel strongly about either of those, you&amp;#8217;ll increase your chances with other proposals.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re also offering &lt;a href="http://www.review-board.org/summer-of-code/hosting/"&gt;free Review Board hosting&lt;/a&gt; for open source projects participating in Summer of Code. If you&amp;#8217;re a mentoring organization and would like to give Review Board a try for reviewing and managing student code, go ahead and contact us and we&amp;#8217;ll get you set up.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Roadmap&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re finally nearing 1.0. We recently put out our 1.0 beta 2 release and are now in a feature freeze. We&amp;#8217;re working to get some bug, performance and usability fixes in for beta 3, which I&amp;#8217;m shooting for in a few weeks. Then we&amp;#8217;ll branch for 1.0, put out a Release Candidate or two, and then finally release 1.0!&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s a lot of really cool features planned after 1.0, namely &lt;b&gt;extensions&lt;/b&gt; and &lt;b&gt;policy customization&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Extensions&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Our bug tracker is filled with feature requests for all kinds of things, ranging from bug tracker integration, instant messaging, a method for offering bribes for code reviews, and so on. We clearly can&amp;#8217;t put all the requested features in the codebase, so we&amp;#8217;ve decided instead to add support for third-party extensions. Coming soon, developers will be able to write extensions to Review Board in the form of Python modules to extend or alter the functionality of Review Board. The extension framework will allow them to do the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Access the database using the existing Review Board database models.&lt;/li&gt;
&lt;li&gt;Add new database models for storing data.&lt;/li&gt;
&lt;li&gt;Listen for signals (new review request published, review request submitted, etc.) and act on them.&lt;/li&gt;
&lt;li&gt;Add custom URLs.&lt;/li&gt;
&lt;li&gt;Replace existing URLs, for advanced capabilities such as replacing the diff viewer.&lt;/li&gt;
&lt;li&gt;Add new API handlers.&lt;/li&gt;
&lt;li&gt;Add &amp;#8220;action&amp;#8221; links to existing review requests and reviews.&lt;/li&gt;
&lt;li&gt;Add columns and sidebar entries to the dashboard.&lt;/li&gt;
&lt;li&gt;Add pages to the administration UI.&lt;/li&gt;
&lt;li&gt;Communicate with other extensions.&lt;/li&gt;
&lt;li&gt;Provide a settings page, which stores data in Review Board-provided models (we even auto-generate the settings page for the extension by default).&lt;/li&gt;
&lt;li&gt;And more!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A lot of this already exists in a private development branch, and it will be one of our primary focuses as soon as 1.0 goes out.&lt;/p&gt;
&lt;p&gt;In time, we&amp;#8217;ll add a new section to the Review Board website where developers can list their extensions for download and for sale. Administrators will be able to browse and search for extensions directly from the administration UI and install them without having to even open a terminal (in most cases).&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re hoping this will solve a lot of in-house integration issues. For example, many companies have custom sandbox architectures, bug trackers, and statistics software which they&amp;#8217;ll now be able to tie in with Review Board.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Policy Customization&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;We&amp;#8217;ve found that a lot of companies have very specific ways they want to handle policy and access restrictions. For example, many companies want to limit who can see certain parts of a repository (and therefore certain diffs), or want to allow anybody to create review groups, or want to disallow people from joining review groups. Some also want to dictate what constitutes approval for submitting a change.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re looking into the various requests and attempting to come up with a policy model that is flexible enough to handle these needs. One of the ideas is to provide some basic level of access control on a per-repository, per-path, and per-group basis. We&amp;#8217;d then piggy-back on the extension framework to allow for more specific policy control. The advantage is that developers could write their own policy rules that interface with some part of their company&amp;#8217;s infrastructure.&lt;/p&gt;
&lt;p&gt;If people have any input on this, we&amp;#8217;d love to hear it.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=QRspFP8F_60:KQd3NmatfKY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=QRspFP8F_60:KQd3NmatfKY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=QRspFP8F_60:KQd3NmatfKY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=QRspFP8F_60:KQd3NmatfKY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=QRspFP8F_60:KQd3NmatfKY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=QRspFP8F_60:KQd3NmatfKY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=QRspFP8F_60:KQd3NmatfKY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><author>chipx86@chipx86.com (chipx86)</author><pubDate>Thu, 02 Apr 2009 21:53:39 -0700</pubDate><guid>http://www.chipx86.com/blog/2009/04/02/review-board-summer-of-code-roadmap-and-future-plans/</guid></item><item><title>Improving browser performance in Review Board
</title><link>http://www.chipx86.com/blog/2009/01/27/improving-browser-performance-in-review-board/</link><description>&lt;p&gt;This past Sunday, I landed a set of changes into &lt;a href="http://www.review-board.org/"&gt;Review Board&lt;/a&gt; that provide improved performance, such as aggressive browser-side caching of media and pages. It&amp;#8217;s just a start, but has already significantly reduced page load times in all of my tests, in some case by several seconds. We implemented these methods for Review Board, but they&amp;#8217;re methods that can be applied to any &lt;a href="http://www.djangoproject.com/"&gt;Django&lt;/a&gt; project out there.&lt;/p&gt;
&lt;p&gt;There are several key things that Review Board now does to improve performance:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tells browsers to cache all media for one year.&lt;/li&gt;
&lt;li&gt;Only sends page data if new data is available.&lt;/li&gt;
&lt;li&gt;Compresses all media files to reduce transfer time.&lt;/li&gt;
&lt;li&gt;Parallelizes media downloads.&lt;/li&gt;
&lt;li&gt;Loads CSS files as early as possible.&lt;/li&gt;
&lt;li&gt;Loads JavaScript files as late as possible.&lt;/li&gt;
&lt;li&gt;Progressively loads expensive data.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A lot of the performance improvements come straight from Yahoo!&amp;#8217;s &lt;a href="http://developer.yahoo.com/performance/rules.html"&gt;Best Practices for Speeding Up Your Site&lt;/a&gt;. We&amp;#8217;re not doing everything there &lt;i&gt;yet&lt;/i&gt;, but we&amp;#8217;re working toward it. That&amp;#8217;s a great resource, by the way, and I recommend that everyone who has even made a website before go and read it.&lt;/p&gt;
&lt;p&gt;So what do the above techniques buy us, and how are we doing them? Let me go into more details&amp;#8230;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Caching all media for a year&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The average site has one or more CSS files, JavaScript files, and several images. This translates to a lot of requests to the server, which may leave the site feeling slow. On top of this, a browser only makes a few requests to a server at a time, in order to avoid swamping the server, which will further hinder load times. This happens every time a user visits a page on your site.&lt;/p&gt;
&lt;p&gt;Aggressive caching makes a huge difference and can greatly reduce load times for users. Review Board now tells the browser to cache media files for a year. Once a user downloads a JavaScript or CSS file, they won&amp;#8217;t have to download it again, meaning that in general the only requests the browser needs to make is for the page requests and AJAX requests.&lt;/p&gt;
&lt;p&gt;The big pitfall with long-term caching is that the cached resources can go stale. For example, if a new version of an image was uploaded, the browser wouldn&amp;#8217;t even know about it, since it was told it should keep its old version for a year before checking again.&lt;/p&gt;
&lt;p&gt;We solve this by introducing &amp;#8220;media serials,&amp;#8221; timestamps that are appended to all media paths. Instead of caching &lt;tt&gt;/js/myscript.js&lt;/tt&gt;, the browser would cache &lt;tt&gt;/js/myscript.js?1273618736&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;These media serials are computed on the first page request by our &lt;tt&gt;djblets.util.context_processors.ajaxSerial&lt;/tt&gt; context processor. This quickly scans all media files known to the program, finding out the latest modification timestamp. It then provides a &lt;tt&gt;{{MEDIA_SERIAL}}&lt;/tt&gt; variable for templates to append to media URLs as part of the query string.&lt;/p&gt;
&lt;p&gt;The benefit to this method is that we can cache media files for a year and not worry about users having stale cached resources the next time we upgrade a copy of Review Board. The filenames requested will be different, browsers will see that the new file is not in the cache, and make a request, caching the new file for a year.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Only send page data if new data is available&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Aggressive caching of media files is great and saves a lot of time, but it doesn&amp;#8217;t help for dynamically generated content. For this, we need a new strategy.&lt;/p&gt;
&lt;p&gt;When a browser makes a request, it can send a &lt;tt&gt;If-Modified-Since&lt;/tt&gt; header to the server containing the &lt;tt&gt;Last-Modified&lt;/tt&gt; value it received the last time it downloaded that page. This is a very valuable header, and there&amp;#8217;s some things we can do with it to save both the server and the browser a lot of trouble.&lt;/p&gt;
&lt;p&gt;If the browser sends &lt;tt&gt;If-Modified-Since&lt;/tt&gt;, and we know that no new data has been generated since the timestamp provided, we can send an &lt;tt&gt;HttpResponseNotModified&lt;/tt&gt; (HTTP response code 304). This will tell the browser it already has the newest version of the page. The sooner we do this, the better, as it means we don&amp;#8217;t have to waste time building templates or doing any expensive database queries.&lt;/p&gt;
&lt;p&gt;Djblets, once again, provides some functions to help out here: &lt;tt&gt;djblets.util.http.set_last_modified&lt;/tt&gt; and &lt;tt&gt;djblets.util.http.get_modified_since&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;The general usage pattern is that we first build a timestamp representing the latest version of the page. This could be the timestamp for a particular object that the page represents. We then check if we can bail early by calling:&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="python python" style="font-family: monospace;"&gt;&lt;span style="color: #ff7700; font-weight: bold;"&gt;if&lt;/span&gt; get_modified_since&lt;span style="color: black;"&gt;&amp;#40;&lt;/span&gt;request, timestamp&lt;span style="color: black;"&gt;&amp;#41;&lt;/span&gt;:
    &lt;span style="color: #ff7700; font-weight: bold;"&gt;return&lt;/span&gt; HttpResponseNotModified&lt;span style="color: black;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;#41;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Further down, after building the page, we must set the &lt;tt&gt;Last-Modified&lt;/tt&gt; timestamp, using the same timestamp as above, like so:&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="python python" style="font-family: monospace;"&gt;set_last_modified&lt;span style="color: black;"&gt;&amp;#40;&lt;/span&gt;response, timestamp&lt;span style="color: black;"&gt;&amp;#41;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We&amp;#8217;re using this in only a few places right now, such as the review request details page, but it drastically improves load times. If the review request hasn&amp;#8217;t changed and nobody&amp;#8217;s commented on it since the browser last loaded the page, a reload of the page will be almost instant.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Compress all media files&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Our Apache and lighttpd config files now enable compression by default. By compressing these files, we can turn a relatively large JavaScript file (such as the jquery and jquery-ui files) into a very small file before sending it over to the browser. This reduces transfer times at the expense of compression/decompression time (which is small enough to not worry for deployments of this size, and can be offset by caching of compressed files server-side).&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Parallelize media downloads&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s important to not mix loads of media files of different types. The browser parallelizes media downloads of the same type, in page load order, but if you load one CSS file, one JavaScript file, another CSS file, and then another JavaScript file, the browser will only attempt one load at a time. If you load all the CSS files before all JavaScript files, it will parallelize the CSS file download and then the JavaScript downloads. By enforcing the separation of loads, we can achieve faster page download/render times.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Load CSS files as soon as possible&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Loading CSS files before the browser starts to display the page can make the page appear to load smoother. The browser will already know &lt;i&gt;how&lt;/i&gt; things should look and will lay the page out accordingly, instead of laying the page out once and then updating that once the CSS files have loaded.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Load JavaScript files as late as possible&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;JavaScript loads block the browser, as the browser must parse and interpet the JavaScript before it can continue. Sometimes it&amp;#8217;s necessary to load a JavaScript file early, but in many cases the files can be loaded late. When possible, we load JavaScript files at the very end of the document body so that they won&amp;#8217;t even begin downloading until the page has rendered. This provides noticeable performance for script-heavy pages.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Progressively load expensive data&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;There are types of data that are just too expensive to load along with the rest of the page. For a long time, Review Board would parse and render fragments of a diff for display in the review request page, but that meant that before the page could load, Review Board would need to do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Query the list of all comments.&lt;/li&gt;
&lt;li&gt;Fetch every file commented on.&lt;/li&gt;
&lt;li&gt;Apply the stored patch to each file.&lt;/li&gt;
&lt;li&gt;Diff between the original and patched files.&lt;/li&gt;
&lt;li&gt;Render the portion of the diff commented on into the page.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This became very time-consuming, and if a server was down, the page wasn&amp;#8217;t available until everything timed out. The solution to this was to lazily load each of these diff fragments in order.&lt;/p&gt;
&lt;p&gt;We now display a placeholder table for each diff fragment in roughly the same size of the rendered fragment (to avoid excessive page scrolling on loads). The table contains a spinner showing that something is happening, and, one-by-one (to avoid dogpiling) we load each diff fragment.&lt;/p&gt;
&lt;p&gt;The code to render the diff fragment, by the way, takes advantage of the &lt;tt&gt;If-Modified-Since&lt;/tt&gt; header and is also cached for a year. We use an &lt;tt&gt;AJAX_SERIAL&lt;/tt&gt; (same principal as the &lt;tt&gt;MEDIA_SERIAL&lt;/tt&gt; above) to allow for changes in new deployments.&lt;/p&gt;
&lt;p&gt;With these caching mechanisms in place, the review request page now loads in roughly a second in many cases (or less once cached), with diff fragments coming in lazily (and then almost immediately on future loads).&lt;/p&gt;
&lt;p&gt;&lt;b&gt;More to come&amp;#8230;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;This was a great first step, but there&amp;#8217;s more we can do. Before we hit our 1.0 release, we&amp;#8217;re going to batch together all our CSS files and JavaScript files into a couple of combined files and then &amp;#8220;minify&amp;#8221; them (basically compressing them in such a way to allow for smaller files and faster load times of the interpreted data).&lt;/p&gt;
&lt;p&gt;Again, these are techniques we&amp;#8217;re now making use of in Review Board, but they&amp;#8217;re not in any way specific to Review Board. Anyone out there developing websites or web applications should seriously look into ways to improve performance. I hope this was a good starting point, but seriously, do read Yahoo!&amp;#8217;s article as well.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=jXQMBtcQ"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=qP6AaYra"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=qP6AaYra" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=XM9Q8Wck"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=XM9Q8Wck" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=cuPnkDWl"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=cuPnkDWl" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><author>chipx86@chipx86.com (chipx86)</author><pubDate>Tue, 27 Jan 2009 12:14:29 -0700</pubDate><guid>http://www.chipx86.com/blog/2009/01/27/improving-browser-performance-in-review-board/</guid></item><item><title>Infect your application with Parasite!
</title><link>http://feedproxy.google.com/%7Er/chipx86/chiplog/%7E3/E2ntREFWw8k/</link><description>&lt;p&gt;&lt;img alt="Parasite" class="alignright size-full wp-image-294" height="137" src="http://www.chipx86.com/blog/wp-content/uploads/2009/01/parasite.png" title="Parasite" width="131" /&gt;&lt;/p&gt;
&lt;p&gt;Ever find yourself stuck debugging an application because the UI is just doing something weird that you can&amp;#8217;t track down? Maybe a widget isn&amp;#8217;t appearing correctly, or you just need more information about the overall structure and logging statements aren&amp;#8217;t doing you much good. Debugging complex UIs can be a pain.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;ve had some real challenges at &lt;a href="http://www.vmware.com/"&gt;VMware&lt;/a&gt;, due to the complexity of our applications. It was enough to drive me mad one day, so rather than write more logging statements, I wrote &lt;a href="http://chipx86.github.com/gtkparasite"&gt;Parasite&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Parasite is a debugging tool that David Trowbridge and I have been working on to give developers an interactive view of their entire application&amp;#8217;s UI. It provides a number of really useful features, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;See the entire widget hierarchy of your UI.&lt;/li&gt;
&lt;li&gt;Watch properties update live.&lt;/li&gt;
&lt;li&gt;Modify existing properties on a widget.&lt;/li&gt;
&lt;li&gt;View all registered GtkActions.&lt;/li&gt;
&lt;li&gt;Toggle GTK+&amp;#8217;s debugging of graphic updates.&lt;/li&gt;
&lt;li&gt;Inject custom code while the application is running.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Yes, you can inject new code into an application. With Python. Parasite runs in-process as a GTK+ module, so it has access to some internals of your application. We provide a Python shell equipped with PyGTK support for creating and modifying your UI on-the-fly, regardless of the language it was written in. Handy when you want to test out new concepts for a UI without writing new C code.&lt;/p&gt;
&lt;p&gt;David has a nice &lt;a href="http://chipx86.github.com/gtkparasite/video/parasite-intro.avi"&gt;screencast&lt;/a&gt; available showing some of what Parasite can do.&lt;/p&gt;
&lt;p&gt;For more information on Parasite, including screenshots, a mailing list, and where to get the source code, see the &lt;a href="http://chipx86.github.com/gtkparasite"&gt;Parasite homepage&lt;/a&gt;.&lt;/p&gt;
&lt;img height="1" src="http://feeds2.feedburner.com/~r/chipx86/chiplog/~4/E2ntREFWw8k" width="1" /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=UlC5-cbhGpQ:ODyunSRcbFI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=UlC5-cbhGpQ:ODyunSRcbFI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=UlC5-cbhGpQ:ODyunSRcbFI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=UlC5-cbhGpQ:ODyunSRcbFI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=UlC5-cbhGpQ:ODyunSRcbFI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=UlC5-cbhGpQ:ODyunSRcbFI:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=UlC5-cbhGpQ:ODyunSRcbFI:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><author>chipx86@chipx86.com (chipx86)</author><pubDate>Tue, 20 Jan 2009 02:52:47 -0700</pubDate><guid>http://feedproxy.google.com/~r/chipx86/chiplog/~3/E2ntREFWw8k/</guid></item><item><title>Review Board 1.0 alpha 1 released
</title><link>http://www.chipx86.com/blog/2009/01/19/review-board-10-alpha-1-released/</link><description>&lt;p&gt;Roughly two years ago, David Trowbridge and I began development of &lt;a href="http://www.review-board.org/"&gt;Review Board&lt;/a&gt; for use in our open source projects and our team at &lt;a href="http://www.vmware.com/"&gt;VMware&lt;/a&gt;. During that time, we&amp;#8217;ve turned Review Board into a powerful code review tool that works with a variety of version control systems. Most of VMware has moved over to it, as have an estimated 50-100 companies world-wide. We&amp;#8217;ve had over 100 contributors to the project, people providing volunteer support on the mailing list, and people have developed third party tools for integrating with Review Board.&lt;/p&gt;
&lt;p&gt;After all this time in development, with this many people contributing, we decided it&amp;#8217;s probably time to get a release out there. Sure, we could have done this a long time ago, but there&amp;#8217;s a number of large things we were hoping to get in (a recently-committed UI rewrite, for instance). Now that we have most of the major features we want for our 1.0 release, we decided it was time for an alpha.&lt;/p&gt;
&lt;p&gt;Over the coming months, we&amp;#8217;ll be working on stabilizing the codebase, fixing a few large remaining usability quirks, enhancing performance, and writing some proper documentation (which is coming along nicely).&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re eager to get a quality product out there and to begin development on the next release. There&amp;#8217;s a lot of neat things planned:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Support for writing extensions to Review Board.&lt;/li&gt;
&lt;li&gt;A fully-featured API covering every operation you&amp;#8217;ll need to perform.&lt;/li&gt;
&lt;li&gt;Some degree of policy support (specifying which users/groups can see which parts of a repository, for instance).&lt;/li&gt;
&lt;li&gt;Reviews with statuses other than &amp;#8220;Ship It&amp;#8221;. This will probably be customizable to some degree.&lt;/li&gt;
&lt;li&gt;Possibly some theme customization to allow Review Board to blend in better with corporate sites, Trac installs, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Along with this, I plan to roll out a new website for the project that will have a browseable list of third party extensions, apps, Greasemonkey scripts, and more.&lt;/p&gt;
&lt;p&gt;We have more information on our release on our &lt;a href="http://www.review-board.org/news/2009/01/19/review-board-10-alpha-1-released/"&gt;release announcement&lt;/a&gt;.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=JIs796ro"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=UB5Sl4wk"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=UB5Sl4wk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=QZWaOFbk"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=QZWaOFbk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=HqRNYLFS"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=HqRNYLFS" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><author>chipx86@chipx86.com (chipx86)</author><pubDate>Mon, 19 Jan 2009 23:20:13 -0700</pubDate><guid>http://www.chipx86.com/blog/2009/01/19/review-board-10-alpha-1-released/</guid></item><item><title>Armed robbery in progress
</title><link>http://feedproxy.google.com/%7Er/chipx86/chiplog/%7E3/EhLFIEPn0qI/</link><description>&lt;p&gt;Our Christmas this year was very nice, with lots of good presents, time spent with family, delicious food, and an opportunity to foil an armed robbery. Yes, an armed robbery. How do I continually get myself into these situations?&lt;/p&gt;
&lt;p&gt;While heading back home from my stepdad&amp;#8217;s parents&amp;#8217; house, I spotted a guy standing in a small field at a street corner near my parents&amp;#8217; house, holding what looked to be a gun. The guy was probably late teens/early adult, Caucasian, and dressed in all black. His actions looked instantly suspicious. He was pointing the gun to the ground and made some motion as if he was checking the ammo or something. He seemed pretty lost in his own world, apparently not even realizing he seemed very suspicious.&lt;/p&gt;
&lt;p&gt;My Mom was driving, and decided to slowly drive away from home instead of toward it, and then turn around, giving us time to watch and see what was happening. We knew there was a gas station across the street and wanted to see if he was going to head in there. If so, there was a good chance we&amp;#8217;d be witnessing a robbery.&lt;/p&gt;
&lt;p&gt;Sure enough, he started walking across the street to the TowerMart, a gas station/convenience store. We parked the car and my Mom grabbed my phone and called 911 while my brothers and I carefully watched from behind a building, making sure we weren&amp;#8217;t noticed. We saw the guy walking back and forth at the side of the building, looking &lt;i&gt;very&lt;/i&gt; nervous. He was wearing long sleeves with his left hand exposed and his right hand (which was holding the gun) completely covered. As my Mom talked to the police, we continued to watch, and the guy eventually psyched himself into going into the store. He put the gun in his pocket and went in.&lt;/p&gt;
&lt;p&gt;The store was pretty crowded, and we weren&amp;#8217;t sure what to expect. Would people be running out screaming? Would people be locked in? Would we hear gun fire? Or would he just leave?&lt;/p&gt;
&lt;p&gt;We never saw him actually leave, but we could only see the one side of the building. A couple minutes later, six police cars drove up, two right beside us. Two cop cars pulled up alongside us. One of them hopped out, grabbed a big ol&amp;#8217; semi-automatic, and approached the building, pointing the gun, ready to fire. Three other cops did the same, surrounding the building. A couple other cops went in and got people out of there, with another couple cops asking those people if they had seen anyone matching the description we gave, or saw other suspicious activity.&lt;/p&gt;
&lt;p&gt;They spent some time going through the TowerMart and eventually came back out once they were sure he wasn&amp;#8217;t hiding in there. It seems at some point, he had left the building. We weren&amp;#8217;t able to see when. However, he was definitely in there. Practically everyone they talked to noticed him, as he was nervously walking in circles around the building, completely covered. He had either grown nervous with the number of people in there, or heard the sirens come. Either way, he got out of there before doing anything.&lt;/p&gt;
&lt;p&gt;As most of the cops started to exit the building, the one who had pulled up closest to us walked up and asked what we saw. Then he said, &amp;#8220;Oh, I talked to you before.&amp;#8221; We all thought that was strange, since he hadn&amp;#8217;t actually talked to us, but then he pointed out that he remembered us from &lt;a href="http://www.chipx86.com/blog/?p=257"&gt;the assault&lt;/a&gt; back in May. Good memory.&lt;/p&gt;
&lt;p&gt;We walked with him to the field and pointed out roughly where we saw him standing. He found the footprints and was calling out the detectives to take pictures or whatever. We chit-chatted briefly before returning home. He told us we very well may have saved the store and a lot of people from experiencing a robbery on Christmas Day. I just hope the guy didn&amp;#8217;t make another attempt elsewhere.&lt;/p&gt;
&lt;p&gt;We found out that an hour or two later, the police were still all over that place. About an hour ago, they apparently had arrested someone not too far from here. Whether related or not, I don&amp;#8217;t know. Given that they had video footage of the guy, testimonies and descriptions from a bunch of people in the store, and his footprints, it&amp;#8217;s probably only a matter of time.&lt;/p&gt;
&lt;p&gt;The rest of Christmas proceeded without police intervention. Merry Christmas!&lt;/p&gt;
&lt;img height="1" src="http://feeds2.feedburner.com/~r/chipx86/chiplog/~4/EhLFIEPn0qI" width="1" /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=xPwgkZxjcYM:AcpNBEwpNfE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=xPwgkZxjcYM:AcpNBEwpNfE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=xPwgkZxjcYM:AcpNBEwpNfE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=xPwgkZxjcYM:AcpNBEwpNfE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=xPwgkZxjcYM:AcpNBEwpNfE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=xPwgkZxjcYM:AcpNBEwpNfE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=xPwgkZxjcYM:AcpNBEwpNfE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><author>chipx86@chipx86.com (chipx86)</author><pubDate>Fri, 26 Dec 2008 06:04:46 -0700</pubDate><guid>http://feedproxy.google.com/~r/chipx86/chiplog/~3/EhLFIEPn0qI/</guid></item><item><title>Ubuntu and Desktop Notifications
</title><link>http://feedproxy.google.com/%7Er/chipx86/chiplog/%7E3/bijFJKrT-cs/</link><description>&lt;p&gt;This past Monday, Mark Shuttleworth &lt;a href="http://www.markshuttleworth.com/archives/253"&gt;wrote about&lt;/a&gt; their plans for an overhaul of desktop notifications (the little popup bubbles telling you someone IM&amp;#8217;d you or there&amp;#8217;s updates available). Many people have asked me about this, some concerned, and wanted to know what I thought. Being the maintainer of libnotify, notification-daemon and the &lt;a href="http://www.galago-project.org/specs/notification/"&gt;Desktop Notifications specification&lt;/a&gt;, some people were concerned that this work would supersede my own.&lt;/p&gt;
&lt;p&gt;The reality is, this isn&amp;#8217;t a replacement of my project. This is a new joint effort between Ubuntu, KDE, and myself. What&amp;#8217;s been written in Mark&amp;#8217;s post may not end up being the end result. We&amp;#8217;re still deciding how this will progress, and Ubuntu wants to experiment a bit. &lt;a href="http://aseigo.blogspot.com/2008/12/notifications.html"&gt;Aaron Seigo&amp;#8217;s post&lt;/a&gt; on the subject sums up a lot of my thoughts on this, and I recommend reading it, though I&amp;#8217;ll go further and discuss where this all started and how it&amp;#8217;ll affect the project.&lt;/p&gt;
&lt;p&gt;First of all, libnotify/notification-daemon isn&amp;#8217;t going anywhere. It&amp;#8217;s not being replaced, nor is an alternate spec being drafted. Ubuntu&amp;#8217;s User Experience team has some new things they want to try, and that&amp;#8217;s fine. The plan is to see how this stuff goes in their codebase, with the intention of migrating code back upstream.&lt;/p&gt;
&lt;p&gt;A couple of weeks ago, during the Ubuntu Summit, I was invited to speak with some of the developers and User Experience guys from Ubuntu about their plans. They showed me the mockup that&amp;#8217;s on Mark&amp;#8217;s blog and told me about their plans. They have things they want to do that could definitely improve the experience. Some things are pretty controversial, such as the removal of actions on notifications. We sat down, discussed and debated various aspects of the proposals for a while, and I believe reached a general course of action for the project. The highlights include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Actions will be removed for applications packaged in Ubuntu. The developers will try to replace them with something that they feel makes more sense, with the hope of pushing these changes upstream.&lt;/li&gt;
&lt;li&gt;The released notification-daemon will, I believe, support actions, since many non-packaged applications do use them. They will, however, appear as old-style notifications and not appear in the new window stack demoed in Mark&amp;#8217;s blog post.&lt;/li&gt;
&lt;li&gt;We&amp;#8217;ll be drafting new additions to the notification spec in order to address the needs of KDE and Mozilla.&lt;/li&gt;
&lt;li&gt;The work will be done by their developers in either a fork or a whole new notification-daemon implementation, allowing them a greater ability to experiment. These changes (or parts of them) will make their way upstream. It will be spec-compatible so users won&amp;#8217;t have to worry too much about losing features (aside from actions, perhaps).&lt;/li&gt;
&lt;li&gt;In the end, it&amp;#8217;ll likely be that the Ubuntu theme specifically works this new way, and that other themes will work differently (they may support actions more directly, for example).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now I should point out that I don&amp;#8217;t believe actions are a bad thing. There&amp;#8217;s many use cases where actions are very much warranted, and it seems Aaron agrees. While the Ubuntu team has discussed the possibility of deprecating this in the spec, I believe the end result will be that actions will live on. I&amp;#8217;m also pretty adamant that upstream notification-daemon will still support actions and some other features. Ubuntu can choose what experience to give their packaged applications, but that may differ a bit from what we decide upstream.&lt;/p&gt;
&lt;p&gt;Time will tell how this all turns out. I personally think it&amp;#8217;s great that there&amp;#8217;s some momentum on this project. I know I haven&amp;#8217;t had much time to work on it as of late, between &lt;a href="http://www.vmware.com/"&gt;VMware&lt;/a&gt; and &lt;a href="http://www.review-board.org/"&gt;Review Board&lt;/a&gt;, which is why getting some new people on board with fresh thoughts will probably be a good thing.&lt;/p&gt;
&lt;p&gt;On a related note, I&amp;#8217;d like to welcome Andrew Walton to the project. He&amp;#8217;s going to be working as a co-maintainer and helping out when I&amp;#8217;m busy (which will be a lot of the time for a while).&lt;/p&gt;
&lt;p&gt;Over the next month or two, the project should start to pick up. We&amp;#8217;re beginning to look at ways to improve the spec and at what work needs to be done in the near future for the project. These discussions will take place on &lt;a href="http://lists.freedesktop.org/mailman/listinfo/xdg"&gt;xdg-list&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And with that, I wish everyone a Merry Christmas (or just a very good December 25th for those who don&amp;#8217;t celebrate Christmas)!&lt;/p&gt;
&lt;img height="1" src="http://feeds2.feedburner.com/~r/chipx86/chiplog/~4/bijFJKrT-cs" width="1" /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=6bTp7yHB9RM:t_MvAwQZWSg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=6bTp7yHB9RM:t_MvAwQZWSg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=6bTp7yHB9RM:t_MvAwQZWSg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=6bTp7yHB9RM:t_MvAwQZWSg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=6bTp7yHB9RM:t_MvAwQZWSg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=6bTp7yHB9RM:t_MvAwQZWSg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=6bTp7yHB9RM:t_MvAwQZWSg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><author>chipx86@chipx86.com (chipx86)</author><pubDate>Thu, 25 Dec 2008 07:09:12 -0700</pubDate><guid>http://feedproxy.google.com/~r/chipx86/chiplog/~3/bijFJKrT-cs/</guid></item><item><title>Fixing broken key codes in VMware on Ubuntu 8.10
</title><link>http://feedproxy.google.com/%7Er/chipx86/chiplog/%7E3/yIICswcMQG4/</link><description>&lt;p&gt;I recently upgraded a system to both Ubuntu 8.10 and VMware Workstation 6.5, and while using it, I realized a number of keys were broken. The down arrow invoked the Windows Start Menu, for instance. Pressing Alt caused the key to be stuck. I knew this stuff worked in 8.04, but it certainly wasn&amp;#8217;t in 8.10.&lt;/p&gt;
&lt;p&gt;After some digging around, I found a forum post (lost the link, sorry) that fixed this. It&amp;#8217;s worked pretty well for me, and so I thought I&amp;#8217;d share for all those who have hit this issue.&lt;/p&gt;
&lt;p&gt;Edit your &lt;tt&gt;$HOME/.vmware/preferences&lt;/tt&gt; file and add:&lt;/p&gt;
&lt;pre&gt;
xkeymap.keycode.108 = 0x138 # Alt_R
xkeymap.keycode.106 = 0x135 # KP_Divide
xkeymap.keycode.104 = 0x11c # KP_Enter
xkeymap.keycode.111 = 0x148 # Up
xkeymap.keycode.116 = 0x150 # Down
xkeymap.keycode.113 = 0x14b # Left
xkeymap.keycode.114 = 0x14d # Right
xkeymap.keycode.105 = 0x11d # Control_R
xkeymap.keycode.118 = 0x152 # Insert
xkeymap.keycode.119 = 0x153 # Delete
xkeymap.keycode.110 = 0x147 # Home
xkeymap.keycode.115 = 0x14f # End
xkeymap.keycode.112 = 0x149 # Prior
xkeymap.keycode.117 = 0x151 # Next
xkeymap.keycode.78  = 0x46  # Scroll_Lock
xkeymap.keycode.127 = 0x100 # Pause
xkeymap.keycode.133 = 0x15b # Meta_L
xkeymap.keycode.134 = 0x15c # Meta_R
xkeymap.keycode.135 = 0x15d # Menu
&lt;/pre&gt;
&lt;p&gt;That should do it!&lt;/p&gt;
&lt;img height="1" src="http://feeds2.feedburner.com/~r/chipx86/chiplog/~4/yIICswcMQG4" width="1" /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=miFvcco0puc:Ccljfg6y4dg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=miFvcco0puc:Ccljfg6y4dg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=miFvcco0puc:Ccljfg6y4dg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=miFvcco0puc:Ccljfg6y4dg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=miFvcco0puc:Ccljfg6y4dg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=miFvcco0puc:Ccljfg6y4dg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=miFvcco0puc:Ccljfg6y4dg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><author>chipx86@chipx86.com (chipx86)</author><pubDate>Tue, 23 Dec 2008 09:43:22 -0700</pubDate><guid>http://feedproxy.google.com/~r/chipx86/chiplog/~3/yIICswcMQG4/</guid></item><item><title>Twittering as Review Board Approaches 1.0
</title><link>http://www.chipx86.com/blog/2008/12/06/twittering-as-review-board-approaches-10/</link><description>&lt;p&gt;&lt;b&gt;On the road to 1.0&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re getting very close to feature freeze for &lt;a href="http://www.review-board.org/"&gt;Review Board&lt;/a&gt; 1.0. The last couple of major features are &lt;a href="http://reviews.review-board.org/"&gt;up for review&lt;/a&gt;. These consist largely of a UI rewrite that simplifies a lot of Review Board&amp;#8217;s operations and moves us over to using &lt;a href="http://www.jquery.com/"&gt;jQuery&lt;/a&gt;. This will go in once it&amp;#8217;s been reviewed and tested in Firefox 3, IE 6/7, Opera and Safari.&lt;/p&gt;
&lt;p&gt;There are some preliminary &lt;a href="http://reviews.review-board.org/r/659/s/53/"&gt;screenshots&lt;/a&gt; up of the UI rewrite. Some things will be changing before this goes in, but it should give a good idea as to the major changes (if you&amp;#8217;re already a Review Board user).&lt;/p&gt;
&lt;p&gt;In the meantime, we&amp;#8217;re working to get some other fixes and small features in, and I&amp;#8217;m beginning work on a user manual. I&amp;#8217;m not sure how much will get done for 1.0, but with any luck I&amp;#8217;ll have a decent chunk done.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Twittering the night away&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve just set up a &lt;a href="http://twitter.com/reviewboard"&gt;@reviewboard&lt;/a&gt; user on Twitter that I&amp;#8217;m going to try to keep up-to-date as progress is made. This should give people a decent way of passively keeping track of updates if they&amp;#8217;re Twitter users.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Barter system?&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://twitter.com/bs"&gt;Britt Selvitelle&lt;/a&gt; of Twitter fame just sent me a great &lt;a href="http://flickr.com/photos/bs/2959767600/"&gt;screenshot&lt;/a&gt; of a barter system for Review Board. Can&amp;#8217;t get someone to review your code? Offer them something in exchange!&lt;/p&gt;
&lt;p&gt;As some people know, we&amp;#8217;re planning to have extensions in the next major release (1.5 or 2.0). This would be a fun little extension to have :) Maybe I&amp;#8217;ll write it as part of a tutorial.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=Hu1PSeOK"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=pPJB5o88"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=pPJB5o88" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=dfyag8jk"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=dfyag8jk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=QiYJnzvx"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=QiYJnzvx" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><author>chipx86@chipx86.com (chipx86)</author><pubDate>Sun, 07 Dec 2008 06:58:23 -0700</pubDate><guid>http://www.chipx86.com/blog/2008/12/06/twittering-as-review-board-approaches-10/</guid></item><item><title>libnotify 0.4.5 and notification-daemon 0.4.0 released
</title><link>http://feedproxy.google.com/%7Er/chipx86/chiplog/%7E3/WXMYtFFKyjw/</link><description>&lt;p&gt;It&amp;#8217;s been a long time since I&amp;#8217;ve really put out a libnotify or notification-daemon release. &lt;a href="http://www.review-board.org/"&gt;Review Board&lt;/a&gt; and &lt;a href="http://www.vmware.com/"&gt;VMware&lt;/a&gt; have taken up a lot of time the past year, so development has been slow, but I think these releases are worth it.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;libnotify 0.4.5&lt;/b&gt; &lt;a href="http://galago-project.org/files/releases/source/libnotify/libnotify-0.4.5.NEWS"&gt;[Release Notes]&lt;/a&gt; &lt;a href="http://galago-project.org/files/releases/source/libnotify/"&gt;[Downloads]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is mostly a small bug fix release, but introduces support for associating a notification with a GtkStatusIcon. This allows for better position tracking when notification icons are jumping around.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;notification-daemon 0.4.0&lt;/b&gt; &lt;a href="http://galago-project.org/files/releases/source/notification-daemon/notification-daemon-0.4.0.NEWS"&gt;[Release Notes]&lt;/a&gt; &lt;a href="http://galago-project.org/files/releases/source/notification-daemon/"&gt;[Downloads]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is a large feature and bug fix release. The major two features are multi-head support and a new control panel applet for specifying the notification theme and corner origin.&lt;/p&gt;
&lt;p&gt;The multi-head support will show standard (non-positioned) notifications on the monitor the mouse is currently on. Previously, they would only appear on the primary head. This helps to notice new notifications, and fixes problems with some people who have a multi-head setup but only have one monitor on or in view. Also, notifications that appear on the edge of a monitor in a multi-head setup will no longer cross the monitor boundary, and will instead just stay on the correct monitor.&lt;/p&gt;
&lt;p&gt;The new control panel applet makes it easy to switch notification themes or to specify which corner notifications should appear from. This will be expanded in the future.&lt;/p&gt;
&lt;p&gt;As mentioned above with libnotify, notification-daemon can now track when status icons have moved so that the notifications are no longer in the wrong position during startup.&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s a bunch of other nice little bug fixes that are mentioned in the release notes.&lt;/p&gt;
&lt;p&gt;Thanks for the patience, everyone!&lt;/p&gt;
&lt;img height="1" src="http://feeds2.feedburner.com/~r/chipx86/chiplog/~4/WXMYtFFKyjw" width="1" /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=h8s9rnie2iU:OYQkjujU-aU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=h8s9rnie2iU:OYQkjujU-aU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=h8s9rnie2iU:OYQkjujU-aU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=h8s9rnie2iU:OYQkjujU-aU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=h8s9rnie2iU:OYQkjujU-aU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=h8s9rnie2iU:OYQkjujU-aU:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=h8s9rnie2iU:OYQkjujU-aU:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><author>chipx86@chipx86.com (chipx86)</author><pubDate>Thu, 20 Nov 2008 11:58:11 -0700</pubDate><guid>http://feedproxy.google.com/~r/chipx86/chiplog/~3/WXMYtFFKyjw/</guid></item><item><title>Racism, Sexism, and now Prop 8
</title><link>http://feedproxy.google.com/%7Er/chipx86/chiplog/%7E3/lcnJ_OexNRY/</link><description>&lt;p&gt;I found out this evening, to my dismay, that my site was littered with &amp;#8220;Yes On Prop 8&amp;#8243; banners. Now, for those who live outside California and haven&amp;#8217;t been following this, Prop 8 is a measure designed to introduce an amendment to the California constitution to ban gay marriage, basically ensuring that certain people would never have the same rights as others in this state.&lt;/p&gt;
&lt;p&gt;Now I normally try to stay away from politics on my blog, but I want to talk about two points.&lt;/p&gt;
&lt;p&gt;First, I don&amp;#8217;t mind banners on my site that are designed to sell a product. People generally understand that an ad for an online web service or a product of some sort is not necessarily endorsed by the site it&amp;#8217;s running on. Ads are everywhere and most people generally get that it&amp;#8217;s provided by an ad service, and just ignore them.&lt;/p&gt;
&lt;p&gt;What bothered me about the Yes On Prop 8 ads is that it felt as if I&amp;#8217;m endorsing Prop 8. Somehow, it feels wrong to me. I&amp;#8217;m not morally outraged about Sun Microsystems wanting to sell a server system or Microsoft wanting to sell an office suite. I am outraged about Prop 8. Products are fine to advertise on my site. Controversial freedom-limiting propositions I&amp;#8217;m completely against are not.&lt;/p&gt;
&lt;p&gt;I look back in our history and see that by and large, our generation is regretful of how we&amp;#8217;ve mistreated people in the past. Shooting Native Americans used to be fine. Stripping away their rights and making them unequal was socially accepted. It was completely understood that if you&amp;#8217;re black, you&amp;#8217;re property. If you&amp;#8217;re a women, you had no rights to vote and your opinion didn&amp;#8217;t matter.&lt;/p&gt;
&lt;p&gt;I like to think we&amp;#8217;ve come a long way from that. People pride themselves on how we&amp;#8217;re more mature now. Black, white, red, men, women. It doesn&amp;#8217;t matter. This is the land of the free, the land of equality. So why is it that it&amp;#8217;s still okay to discriminate against someone because their love of someone makes you feel uncomfortable?&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s okay to not feel comfortable with gay marriage. A lot of people don&amp;#8217;t. But do you feel more comfortable being part of a group of people that knowingly discriminated against another group, stripped them of certain rights that you yourself enjoy, simply because something you don&amp;#8217;t have to deal with on a daily basis makes you feel uncomfortable to think about? Are you going to be okay with the thought of your grandkids or your great-grandkids feeling embarrassed because of how you voted, like how you feel about your great-grandparents&amp;#8217; racism? How much is preventing marriage for two people who love each other, in order to feel less uncomfortable, worth to you?&lt;/p&gt;
&lt;p&gt;The Yes On Prop 8 advertisements often show the clip with the mayor of San Francisco saying &amp;#8220;It&amp;#8217;s going to happen, whether you like it or not!&amp;#8221; It&amp;#8217;s a good strategic clip for them to have chosen, as it can be interpreted as him saying &amp;#8220;you have no say, we&amp;#8217;re forcing gay marriage on all of you.&amp;#8221;&lt;/p&gt;
&lt;p&gt;I see it another way. I see gay marriage being inevitable not as an attack, but as the inevitable rise in tolerance that, over time, we&amp;#8217;ve come to develop in this country. As a country, we don&amp;#8217;t have the best track record of tolerance to new things, but we always mature in the end. This is not the last time we&amp;#8217;ll face such mass intolerance and the limiting of rights of a group of people, just as this will not be the first time that we as a people will overcome our fears and begin to see us all as being equal.&lt;/p&gt;
&lt;p&gt;So this is important. It&amp;#8217;s not just about your level of comfort with those who live a different lifestyle. It&amp;#8217;s about equality. It&amp;#8217;s about overcoming personal fears. It&amp;#8217;s about making an effort to keep this country on a path of freedom. Because if we start going back to our old ways of discrimination and fear, all we&amp;#8217;re doing is regressing and limiting the rights of others out of some fear of the world spiraling into chaos. We&amp;#8217;ve worked to abolish racism. We&amp;#8217;ve worked to abolish sexism. The world is still here. We can do this again.&lt;/p&gt;
&lt;p&gt;Vote no on Prop 8.&lt;/p&gt;
&lt;img height="1" src="http://feeds2.feedburner.com/~r/chipx86/chiplog/~4/lcnJ_OexNRY" width="1" /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=tnYELmLWCUk:qL3mJC4ZLgc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=tnYELmLWCUk:qL3mJC4ZLgc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=tnYELmLWCUk:qL3mJC4ZLgc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=tnYELmLWCUk:qL3mJC4ZLgc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=tnYELmLWCUk:qL3mJC4ZLgc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ReviewBoard?a=tnYELmLWCUk:qL3mJC4ZLgc:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ReviewBoard?i=tnYELmLWCUk:qL3mJC4ZLgc:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><author>chipx86@chipx86.com (chipx86)</author><pubDate>Tue, 04 Nov 2008 07:40:30 -0700</pubDate><guid>http://feedproxy.google.com/~r/chipx86/chiplog/~3/lcnJ_OexNRY/</guid></item><item><title>Djblets and Review Board moving to jQuery
</title><link>http://www.chipx86.com/blog/2008/09/18/djblets-and-review-board-moving-to-jquery/</link><description>&lt;p&gt;When we first began development of &lt;a href="http://www.review-board.org/"&gt;Review Board&lt;/a&gt; and its Django utility package Djblets almost two years ago, we needed to pick a JavaScript library to use. There were several good ones available at the time, and after evaluating several options we chose the &lt;a href="http://developer.yahoo.com/yui/"&gt;Yahoo! UI Library&lt;/a&gt; (YUI) and YUI-Ext, an extension library to YUI. Both were excellent and have served us well over the past two years.&lt;/p&gt;
&lt;p&gt;However, YUI-Ext itself is really no more, which means we needed to choose something new. We could have continued to bundle it and YUI with Review Board, but users of Djblets would have to hunt down a copy and load in all of YUI and YUI-Ext just to use such features as &lt;a href="http://www.chipx86.com/blog/?p=258"&gt;datagrids&lt;/a&gt;. This was, to say the least, inconvenient.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;YUI-Ext and the Licensing Situation&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Now I said YUI-Ext is no more, but really it&amp;#8217;s still around, just in a new form. It had been renamed to &lt;a href="http://www.extjs.com/"&gt;ExtJS&lt;/a&gt; and became its own independent library. While compatible with YUI, most of the functionality we needed was really provided by ExtJS, meaning we didn&amp;#8217;t really need both. Over time, YUI evolved as well, so we began looking into the differences and figuring out which to go with.&lt;/p&gt;
&lt;p&gt;ExtJS, it turns out, was a non-starter for us. Unlike YUI-Ext before it, the ExtJS &lt;a href="http://extjs.com/products/license.php"&gt;licensing terms&lt;/a&gt; were a bit restrictive and, frankly, confusing. Open source projects could use it under the GPL3, but commercial products required a special license per developer, which is $289 per developer. The GPL3 itself is unclear with regards to our situation. We&amp;#8217;re an open source project, but we&amp;#8217;re MIT-licensed. What if a company wants to modify something for their own use and not release it to the public? What if down the road someone wants to offer commercial extensions to Review Board? We&amp;#8217;d have to choose the commercial license to be safe, but then contributors would also need to pay $289 for a license, wouldn&amp;#8217;t they?&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Looking Again at YUI&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;We didn&amp;#8217;t want to step down a dangerous road with ExtJS, so we started to look again at YUI. It&amp;#8217;s definitely come a long way and I must recommend it for developers looking for a strong toolkit with good UI support. They provide good documentation, many examples, and base functionality for nearly everything.&lt;/p&gt;
&lt;p&gt;However, there&amp;#8217;s a lot we&amp;#8217;d have to rewrite to move to it, and if we had to rewrite the code anyway, I wanted to look around a bit at the current generation of JavaScript toolkits. Especially since our needs have changed over the years and we&amp;#8217;re looking for something with a lighter footprint. We&amp;#8217;re also moving away from the dialog-centered UI we have on some pages, which is where YUI shines.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;jQuery&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;We ended up deciding to go with &lt;a href="http://www.jquery.com/"&gt;jQuery&lt;/a&gt;, partially because of the footprint and partially the clean way in which scripts can be written. As an experiment, I converted our Djblets datagrid code to jQuery. The result is a smaller, much more readable, reusable, cross-browser script. I was impressed by what jQuery let me do, and by the size.&lt;/p&gt;
&lt;p&gt;I did some comparisons on the number of files downloaded and the size of the files, using the Review Board dashboard as a test.&lt;/p&gt;
&lt;p&gt;With YUI and YUI-Ext, we were loading 7 JavaScript files, excluding our own scripts, at a total size of 376KB (when minified).&lt;/p&gt;
&lt;p&gt;With jQuery, we loaded only 2 JavaScript files, at a total size of 128KB.&lt;/p&gt;
&lt;p&gt;Our datagrid.js file also went down from 13KB to 9KB largely due to some of the niceties of jQuery&amp;#8217;s API.&lt;/p&gt;
&lt;p&gt;This is a pretty significant savings, a whole 252KB, which could be a couple of seconds on an average DSL line. And it&amp;#8217;s not just the file size but the number of requests, which can make a big difference on a heavily accessed web server.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;What This Means for Djblets&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Developers using Djblets can now use datagrids without needing to do anything special. Djblets bundles jQuery, which it will use by default unless you choose to override which jQuery script is being used. This means all you need is an install of Djblets set up and you&amp;#8217;re ready to use it!&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Going Forward&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re working on migrating the rest of Review Board to jQuery. This will take place over the next few weeks, and is one of the last major things we hope to do for our 1.0 release.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=IL7f6DrV"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=esV1xTk1"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=esV1xTk1" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=R9DfiPuT"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=R9DfiPuT" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=aUl7GQVV"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=aUl7GQVV" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><author>chipx86@chipx86.com (chipx86)</author><pubDate>Thu, 18 Sep 2008 23:46:49 -0700</pubDate><guid>http://www.chipx86.com/blog/2008/09/18/djblets-and-review-board-moving-to-jquery/</guid></item><item><title>Review Board Roadmap and Donations
</title><link>http://www.chipx86.com/blog/2008/08/17/review-board-roadmap-and-donations/</link><description>&lt;p&gt;&lt;b&gt;Roadmap&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;With the upcoming release of &lt;a href="http://www.djangoproject.com/"&gt;Django&lt;/a&gt; 1.0 in the next few weeks, we decided it was time to formalize a &lt;a href="http://code.google.com/p/reviewboard/wiki/Roadmap"&gt;roadmap&lt;/a&gt; for Review Board 1.0. The roadmap provides a good overview of what users can expect for our release, and what it will take to get there.&lt;/p&gt;
&lt;p&gt;At this point we&amp;#8217;re asking for people to contribute wherever possible. The big thing is fixing &lt;a href="http://code.google.com/p/reviewboard/issues/list?can=2&amp;#038;q=milestone:Release1.0"&gt;bugs&lt;/a&gt; targeted for the 1.0 release. We&amp;#8217;d also like some help in finalizing unit tests.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Quality Control&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re doing what we can to improve quality control in Review Board. For a lot of people, Review Board works great, though setups often differ and some users hit issues that others never see. For this, we&amp;#8217;re trying to improve our unit tests to catch these various cases. When people submit patches, we&amp;#8217;d greatly appreciate unit tests to cover the new code, and in some cases will require them for the code submission. &lt;/p&gt;
&lt;p&gt;&lt;b&gt;Selenium&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;We will soon start using &lt;a href="http://selenium.openqa.org/"&gt;Selenium&lt;/a&gt; in our unit test process to simulate user action in various web browsers. Selenium allows for remote-controlling a web browser, simulating clicks, text input, and other user actions and checking the results. Over time, when our Selenium test suite is more complete, we should be able to catch browser-specific problems a lot more easily.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Buildbot Server&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Another issue users have hit lately is breakages due to changes in Django for the 1.0 release. As things calm down there, this will become less of an issue, but we&amp;#8217;ve put things in place to catch these problems before users do.&lt;/p&gt;
&lt;p&gt;We have just set up a &lt;a href="http://build.review-board.org/waterfall"&gt;buildbot server&lt;/a&gt; that will perform a full build and run the test suite whenever there&amp;#8217;s a code check-in to Review Board, Django, Djblets or Django-Evolution. It will then notify us when there&amp;#8217;s a new breakage. Users can check the build page before updating just to make sure they won&amp;#8217;t hit a major problem. Later on, our buildbot server will generate nightly builds and handle Selenium tests.&lt;/p&gt;
&lt;p&gt;We have a limited number of servers to test with. If you have server space and resources to donate and would like to run a BuildBot Slave server, let me know. We&amp;#8217;re looking to set up slaves to test various combinations of the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Python 2.5&lt;/li&gt;
&lt;li&gt;Python 2.4&lt;/li&gt;
&lt;li&gt;Django SVN trunk&lt;/li&gt;
&lt;li&gt;Django 1.0&lt;/li&gt;
&lt;li&gt;Windows 2000, XP and Vista&lt;/li&gt;
&lt;li&gt;Internet Explorer 6 and 7 (for Selenium tests)&lt;/li&gt;
&lt;li&gt;Opera (for Selenium tests)&lt;/li&gt;
&lt;li&gt;Firefox 2 and 3 (for Selenium tests)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Sandbox&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Our BuildBot server is also set up to allow us to test code changes before we submit the code. Running a sandbox build of our pending code will cause all build slaves to run the entire test suite. This ensures that we don&amp;#8217;t break things accidentally.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re a contributor working on large patches for Review Board and would like to have access to the sandbox, please post to the &lt;a href="http://groups.google.com/group/reviewboard"&gt;mailing list&lt;/a&gt; and we can work with you on getting an account set up.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Installation Improvements&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re working to make the installation experience much easier. I&amp;#8217;m in the process of creating Python easy_install packages for Review Board and Djblets. Soon, users will be able to simply &lt;tt&gt;easy_install ReviewBoard&lt;/tt&gt; to get going instead of checking out the development tree. I&amp;#8217;m hoping to create both nightly builds and release builds.&lt;/p&gt;
&lt;p&gt;Code will soon go in to move the entire project configuration into the administration interface. Modifying &lt;tt&gt;settings_local.py&lt;/tt&gt; and restarting the server will be a thing of the past. All that will be left there will be a few site-specific settings and the database settings. Expect this to go in real soon.&lt;/p&gt;
&lt;p&gt;A tool is in development for helping to generate the initial Review Board server tree based on an installed reviewboard Python module (using easy_install) and generating the web server configuration files. This will hopefully take care of a lot of problems people hit when trying to get their server configuration right the first time.&lt;/p&gt;
&lt;p&gt;And last but not least, before 1.0 we will have a first-time installation page that handles the creation of the initial &lt;tt&gt;settings_local.py&lt;/tt&gt; and the adding and checking of repositories.&lt;/p&gt;
&lt;p&gt;So in the end, the installation process will be something along the lines of:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;tt&gt;sudo easy_install ReviewBoard&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt&gt;sudo rb-install-site /var/www/reviews.mycompany.com&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Fill out the fields presented.&lt;/li&gt;
&lt;li&gt;Hand-tweak the configuration files if needed.&lt;/li&gt;
&lt;li&gt;Go to the page for the new Review Board server, fill out the fields and finish the install.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is the goal, anyway. We&amp;#8217;re going to try to get as close to this as possible for 1.0.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Donations&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Review Board has become a full-time project for us. Though it got its start at &lt;a href="http://www.vmware.com/"&gt;VMware&lt;/a&gt;, it&amp;#8217;s really a personal project developed in our spare time, not a project run by VMware. As the project grows, we&amp;#8217;ve been putting more time, energy and money into it.&lt;/p&gt;
&lt;p&gt;Hosting fees have started to become large, given that we&amp;#8217;re now hosting the main &lt;a href="http://www.review-board.org/"&gt;project website&lt;/a&gt;, the main &lt;a href="http://reviews.review-board.org/"&gt;Review Board&lt;/a&gt; server for our code reviews, the &lt;a href="http://demo.review-board.org/"&gt;demo server&lt;/a&gt;, the &lt;a href="http://gsoc.review-board.org/"&gt;Google Summer of Code review server&lt;/a&gt; and the &lt;a href="http://build.review-board.org/"&gt;BuildBot server&lt;/a&gt; and slaves. Down the road, we have many plans that will also require funding.&lt;/p&gt;
&lt;p&gt;To help cover our costs, we&amp;#8217;re now made it easy to &lt;a href="http://www.review-board.org/donate/"&gt;donate&lt;/a&gt; to the project. If Review Board has helped you, your company, team, or project and saved you money or time over alternative solutions, maybe you&amp;#8217;d like to help give back to keep our project going. Every bit helps.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=MH4cDW1y"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=5E2hO5Qe"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=5E2hO5Qe" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=GhXjWNB4"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=GhXjWNB4" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=gnLh7P5N"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=gnLh7P5N" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><author>chipx86@chipx86.com (chipx86)</author><pubDate>Sun, 17 Aug 2008 23:31:47 -0700</pubDate><guid>http://www.chipx86.com/blog/2008/08/17/review-board-roadmap-and-donations/</guid></item><item><title>Happy birthday Review Board!
</title><link>http://www.chipx86.com/blog/2008/05/18/happy-birthday-review-board/</link><description>&lt;p&gt;&lt;b&gt;One whole year&amp;#8230;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;While attending &lt;a href="http://superhappydevhouse.org/SuperHappyDevHouse25"&gt;SuperHappyDevHouse&lt;/a&gt;, &lt;a href="http://david.navi.cx/"&gt;David&lt;/a&gt; and I realized that it was the one year anniversary of &lt;a href="http://www.review-board.org/"&gt;Review Board&lt;/a&gt;&amp;#8217;s public announcement. (This was the evening of May 17th. I&amp;#8217;m just a few hours late in getting this post up.)&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s been a pretty awesome year for Review Board. What begun as a small project intended for use in our team at &lt;a href="http://www.vmware.com/"&gt;VMware&lt;/a&gt; and in our personal open source projects turned into a large project with a great community of developers and users. It&amp;#8217;s now being used by dozens of companies and projects (some of which have given us permission to &lt;a href="http://www.review-board.org/users.php"&gt;list them publicly&lt;/a&gt;) and has had code contributions from over 35 users. To everyone who has contributed to the project, we&amp;#8217;d like to give our thanks. Review Board wouldn&amp;#8217;t be the tool it is today without your help.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;d like to list some of the major things that have happened in the past year.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Review Board has been adopted by one or more teams at around 40 companies (including &lt;a href="http://search.yahoo.com/"&gt;Yahoo! Search&lt;/a&gt;, &lt;a href="http://www.vmware.com/"&gt;VMware&lt;/a&gt;, and &lt;a href="http://www.tripwire.com/"&gt;Tripwire&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Received contributions from over 35 users.&lt;/li&gt;
&lt;li&gt;Added support for CVS, Subversion, Perforce, Git, Mercurial, and Bazaar.&lt;/li&gt;
&lt;li&gt;Added support for useful features such as interdiffs, screenshot commenting, syntax highlighted diffs, customizable dashboard for keeping track of review requests, status reports, a full JSON API, and more.&lt;/li&gt;
&lt;li&gt;Several presentations were given at various companies and conferences on Review Board by third parties.&lt;/li&gt;
&lt;li&gt;One public presentation was given by us at LugRadio Live USA 2008 (&lt;a href="http://blip.tv/file/827320"&gt;view the presentation&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;We&amp;#8217;ve started hosting projects for this year&amp;#8217;s Google Summer of Code on our &lt;a href="http://gsoc.review-board.org/"&gt;Summer of Code server&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;#8217;s just a small sampling. There have been many changes made to stabilize the codebase, improve usability, and generally make the product more awesome.&lt;/p&gt;
&lt;p&gt;And of course there&amp;#8217;s a number of things happening in the near future:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.monotone.ca/"&gt;Monotone&lt;/a&gt; support.&lt;/li&gt;
&lt;li&gt;A new, improved administration UI.&lt;/li&gt;
&lt;li&gt;Extensions support, allowing Review Board to be extended in a variety of ways and integrated into other products.&lt;/li&gt;
&lt;li&gt;A new set of command-line tools and a Python library for working with Review Board servers.&lt;/li&gt;
&lt;li&gt;Support for P4V (for Windows Perforce users).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Database Migration and Parent Diffs&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Today, a change went in that improves Review Board in two fundamental ways.&lt;/p&gt;
&lt;p&gt;First, we now have a fast, powerful way of doing database migrations in-place, without dumping and loading the database. While this should make life easier for users and allow us to modify the database without fear of breaking people&amp;#8217;s installs as often, it will also save administrators of large Review Board servers a lot of time. Before this change, the VMware database (of over 25,000 review requests) took at least 30 minutes to do a full migration. Now it shouldn&amp;#8217;t take more than a minute.&lt;/p&gt;
&lt;p&gt;Second, we&amp;#8217;ve just landed the initial support for diffs based on parent diffs. If you&amp;#8217;re a user of a distributed version control system (such as Git or Mercurial) you&amp;#8217;ll appreciate this. Before, your change had to apply against revisions in the master repository, making it impossible to put up a review request for a change on a sub-branch of a branch when the parent branch didn&amp;#8217;t exist on the server. Now, a diff of the parent branch can be uploaded along with your sub-branch&amp;#8217;s diff.&lt;/p&gt;
&lt;p&gt;Confused? Maybe an example will help. Say you&amp;#8217;re working on a large restructuring change in your &amp;#8220;code-restructure&amp;#8221; branch in your local Git checkout. You have a topic branch off of your &amp;#8220;code-restructure&amp;#8221; branch with changes you want to put up for review. This used to be impossible without including the whole &amp;#8220;code-restructure&amp;#8221; branch&amp;#8217;s changes in your diff as well, but now, you can put up a diff of the topic branch along with a diff of the &amp;#8220;code-restructure&amp;#8221; branch, and the topic branch&amp;#8217;s diff will appear on Review Board, ready for review.&lt;/p&gt;
&lt;p&gt;The backend code for this is now in Subversion. We&amp;#8217;ll be adding support to the post-review tool shortly, making this accessible to anyone. Review Board will become fully usable for distributed version control systems.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Are you using Review Board?&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Review Board is gaining popularity, and more companies are beginning to use it. If you work for a company or an open source project that&amp;#8217;s using Review Board and can give us permission to list you on our &lt;a href="http://www.review-board.org/users.php"&gt;Happy Users&lt;/a&gt; page, please let us know!&lt;/p&gt;
&lt;p&gt;And here&amp;#8217;s to an even better year for Review Board.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=4NYm5ABv"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=I3DKHJo4"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=I3DKHJo4" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=rAR2sgfv"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=rAR2sgfv" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=u5uTdGk1"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=u5uTdGk1" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><author>chipx86@chipx86.com (chipx86)</author><pubDate>Sun, 18 May 2008 10:37:24 -0700</pubDate><guid>http://www.chipx86.com/blog/2008/05/18/happy-birthday-review-board/</guid></item><item><title>Free Review Board Hosting for Summer of Code
</title><link>http://www.chipx86.com/blog/2008/05/01/free-review-board-hosting-for-summer-of-code/</link><description>&lt;p&gt;Google Summer of Code 2008 is on, and soon students will begin coding, which means mentors will be reviewing code. While the Review Board project is not a participating project in this year&amp;#8217;s Summer of Code, we felt Review Board could help with the whole process, improving things for both the students and the mentors.&lt;/p&gt;
&lt;p&gt;Starting today, and for the duration of this year&amp;#8217;s Summer of Code, we at the Review Board project would like to supply up to 30 projects with free Review Board hosting at &lt;a href="http://gsoc.review-board.org/"&gt;gsoc.review-board.org&lt;/a&gt;. We&amp;#8217;ll handle maintenance of the server, support, and provide assistance to get students and mentors set up.&lt;/p&gt;
&lt;p&gt;Doing code reviews with Review Board is simple and saves time over reviewing standard raw diffs, with features such as a powerful diff viewer with syntax highlighting and inline commenting, interdiffs, status reports, and support for a wide variety of revision control systems. We believe it can be as effective a tool for open source development as Bugzilla and Trac have become.&lt;/p&gt;
&lt;p&gt;Th Summer of Code server is intended for Summer of Code-related changes only. While we&amp;#8217;d love to provide hosting for projects in general, we have limited resources. However, should your project decide to set up its own Review Board server in the future, we&amp;#8217;ll be able to assist in migrating your Review Board history to your new server.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re interested in trying out Review Board for your Summer of Code project, you can find out how to apply on our &lt;a href="http://code.google.com/p/reviewboard/wiki/Summer_Of_Code_Hosting"&gt;Summer of Code Hosting&lt;/a&gt; page.&lt;/p&gt;
&lt;p&gt;To learn more about Review Board and how it works, you can look at our &lt;a href="http://www.review-board.org/"&gt;project website&lt;/a&gt; or watch our &lt;a href="http://blip.tv/file/827320"&gt;presentation&lt;/a&gt; from this year&amp;#8217;s LugRadio Live USA.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=tSZsjmlq"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=CSDsjrXY"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=CSDsjrXY" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=2oRnV006"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=2oRnV006" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=P9DXv19Y"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=P9DXv19Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><author>chipx86@chipx86.com (chipx86)</author><pubDate>Thu, 01 May 2008 08:45:00 -0700</pubDate><guid>http://www.chipx86.com/blog/2008/05/01/free-review-board-hosting-for-summer-of-code/</guid></item><item><title>Review Board presentation at LugRadio Live 2008
</title><link>http://www.chipx86.com/blog/2008/04/14/review-board-presentation-at-lugradio-live-2008/</link><description>&lt;p&gt;This year&amp;#8217;s LugRadio Live USA conference was a blast. There were some great talks, interesting booths, and fun swag.&lt;/p&gt;
&lt;p&gt;The Review Board presentation went pretty well. I think in my next presentation I&amp;#8217;ll demo more often instead of just at the end, but all in all people seemed to find it interesting. The presentation focused on what Review Board is, how it works, and how it could benefit open source. With luck, it will encourage projects to begin using a real code review system, making life easier for all involved.&lt;/p&gt;
&lt;p&gt;For those that missed it, the &lt;a href="http://www.review-board.org/presentations/lugradio_usa_2008_reviewboard.pdf"&gt;slides&lt;/a&gt; and the &lt;a href="http://blip.tv/file/827320"&gt;presentation video&lt;/a&gt; are now available. Enjoy!&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=Ay5vq6ga"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=3RDpICAL"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=3RDpICAL" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=9baEqTg2"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=9baEqTg2" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=JsAO2wgQ"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=JsAO2wgQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><author>chipx86@chipx86.com (chipx86)</author><pubDate>Tue, 15 Apr 2008 03:19:32 -0700</pubDate><guid>http://www.chipx86.com/blog/2008/04/14/review-board-presentation-at-lugradio-live-2008/</guid></item><item><title>Django Development with Djblets: Unrooting your URLs
</title><link>http://www.chipx86.com/blog/2008/04/03/django-development-with-djblets-unrooting-your-urls/</link><description>&lt;div class="series_toc"&gt;&lt;h3&gt;Table of contents for Django Development with Djblets&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://www.chipx86.com/blog/2008/02/29/django-development-with-djblets/" title="Django Development with Djblets"&gt;Django Development with Djblets&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.chipx86.com/blog/2008/02/29/django-development-with-djblets-custom-tag-helpers/" title="Django Development with Djblets: Custom Tag Helpers"&gt;Django Development with Djblets: Custom Tag Helpers&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Django Development with Djblets: Unrooting your URLs&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.chipx86.com/blog/2008/07/25/django-development-with-djblets-data-grids/" title="Django Development with Djblets: Data Grids"&gt;Django Development with Djblets: Data Grids&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.chipx86.com/blog/2008/08/05/django-development-with-djblets-dynamic-site-configuration/" title="Django Development with Djblets: Dynamic Site Configuration"&gt;Django Development with Djblets: Dynamic Site Configuration&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt; &lt;p&gt;Typically, Django sites are designed with the assumption that they&amp;#8217;ll have a domain or subdomain to themselves. Often times this is fine, but if you&amp;#8217;re developing a web application designed for redistribution, sometimes you can&amp;#8217;t make that assumption.&lt;/p&gt;
&lt;p&gt;During development of &lt;a href="http://www.review-board.org/"&gt;Review Board&lt;/a&gt;, many of our users wanted the ability to install Review Board into a subdirectory of one of their domains, rather than a subdomain.&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s a few rules that are important when making your site relocatable:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Always use &lt;tt&gt;MEDIA_URL&lt;/tt&gt; when referring to your media directory, so that people can customize where they put their media files.&lt;/li&gt;
&lt;li&gt;Don&amp;#8217;t hard-code URLs in templates. Use the &lt;tt&gt;{% url %}&lt;/tt&gt; tag or &lt;tt&gt;get_absolute_url()&lt;/tt&gt; when possible.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These solve some of the issues, but doesn&amp;#8217;t address relocating a Django site to a subdirectory.&lt;/p&gt;
&lt;p&gt;Djblets fills in this gap by providing a special URL handler designed to act as a prefix for all your projects&amp;#8217; URLs. To make use of this, you need to modify your &lt;tt&gt;settings.py&lt;/tt&gt; file as follows:&lt;/p&gt;
&lt;p&gt;&lt;b&gt;settings.py&lt;/b&gt;&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="python python" style="font-family: monospace;"&gt;TEMPLATE_CONTEXT_PROCESSORS = &lt;span style="color: black;"&gt;&amp;#40;&lt;/span&gt;
    ...
    &lt;span style="color: #483d8b;"&gt;'djblets.util.context_processors.siteRoot'&lt;/span&gt;,
&lt;span style="color: black;"&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
SITE_ROOT_URLCONF = &lt;span style="color: #483d8b;"&gt;'yourproject.urls'&lt;/span&gt;
ROOT_URLCONF = &lt;span style="color: #483d8b;"&gt;'djblets.util.rooturl'&lt;/span&gt;
&amp;nbsp;
SITE_ROOT = &lt;span style="color: #483d8b;"&gt;'/'&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;tt&gt;SITE_ROOT&lt;/tt&gt; specifies where the site is located. By default, this should be &amp;#8220;/&amp;#8221;, but this can be changed to point to any path. For example, &amp;#8220;/myproject/&amp;#8221;. Note that it should always have a leading and a trailing slash.&lt;/p&gt;
&lt;p&gt;The custom template context processor (&lt;tt&gt;djblets.util.context_processors.siteRoot&lt;/tt&gt;) will make &lt;tt&gt;SITE_ROOT&lt;/tt&gt; accessible to templates.&lt;/p&gt;
&lt;p&gt;&lt;tt&gt;SITE_ROOT&lt;/tt&gt; should be used in templates when you need to refer to URLs that aren&amp;#8217;t designed to respect &lt;tt&gt;SITE_ROOT&lt;/tt&gt; (such as &lt;tt&gt;User.get_absolute_url&lt;/tt&gt;). Your own custom applications should always respect &lt;tt&gt;SITE_ROOT&lt;/tt&gt; whenever providing a URL.&lt;/p&gt;
&lt;p&gt;&lt;tt&gt;ROOT_URLCONF&lt;/tt&gt; is typically what you would set to point to your project&amp;#8217;s URL. However, in this case, you&amp;#8217;ll be pointing it to &lt;tt&gt;djblets.util.rooturl&lt;/tt&gt;. This in turn will forward all URLs to your project&amp;#8217;s handler, defined in &lt;tt&gt;SITE_ROOT_URLCONF&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;This is all you need to have a fully relocatable Django site!&lt;/p&gt;
&lt;p&gt;To sum up:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add &lt;tt&gt;djblets.util.context_processors.siteRoot&lt;/tt&gt; to your &lt;tt&gt;TEMPLATE_CONTEXT_PROCESSORS&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Set &lt;tt&gt;SITE_ROOT_URLCONF&lt;/tt&gt; to your project&amp;#8217;s URL handler.&lt;/li&gt;
&lt;li&gt;Set &lt;tt&gt;ROOT_URLCONF&lt;/tt&gt; to &amp;#8216;djblets.util.rooturl&amp;#8217;&lt;/li&gt;
&lt;li&gt;Prefix any URLs with &lt;tt&gt;SITE_ROOT&lt;/tt&gt; in your templates, unless the URL would already take &lt;tt&gt;SITE_ROOT&lt;/tt&gt; into account.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is functionality that will hopefully make its way into Django at some point. For now, you have an easy way of unrooting your Django project.&lt;/p&gt;
 &lt;div class="series_links"&gt;&lt;a href="http://www.chipx86.com/blog/2008/02/29/django-development-with-djblets-custom-tag-helpers/" title="Django Development with Djblets: Custom Tag Helpers"&gt;Previous in series&lt;/a&gt; &lt;a href="http://www.chipx86.com/blog/2008/07/25/django-development-with-djblets-data-grids/" title="Django Development with Djblets: Data Grids"&gt;Next in series&lt;/a&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=aJJxDmwU"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=SjAgVn4p"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=SjAgVn4p" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=vcFlWA3d"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=vcFlWA3d" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=06XvytEo"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=06XvytEo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><author>chipx86@chipx86.com (chipx86)</author><pubDate>Fri, 04 Apr 2008 06:35:11 -0700</pubDate><guid>http://www.chipx86.com/blog/2008/04/03/django-development-with-djblets-unrooting-your-urls/</guid></item><item><title>Django Development with Djblets: Custom Tag Helpers
</title><link>http://www.chipx86.com/blog/2008/02/29/django-development-with-djblets-custom-tag-helpers/</link><description>&lt;div class="series_toc"&gt;&lt;h3&gt;Table of contents for Django Development with Djblets&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://www.chipx86.com/blog/2008/02/29/django-development-with-djblets/" title="Django Development with Djblets"&gt;Django Development with Djblets&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Django Development with Djblets: Custom Tag Helpers&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.chipx86.com/blog/2008/04/03/django-development-with-djblets-unrooting-your-urls/" title="Django Development with Djblets: Unrooting your URLs"&gt;Django Development with Djblets: Unrooting your URLs&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.chipx86.com/blog/2008/07/25/django-development-with-djblets-data-grids/" title="Django Development with Djblets: Data Grids"&gt;Django Development with Djblets: Data Grids&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.chipx86.com/blog/2008/08/05/django-development-with-djblets-dynamic-site-configuration/" title="Django Development with Djblets: Dynamic Site Configuration"&gt;Django Development with Djblets: Dynamic Site Configuration&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt; &lt;p&gt;I&amp;#8217;m planning to cover all of what Django can do, but for now, let&amp;#8217;s start simple with something most Django developers spend way too much time creating: Custom tags.&lt;/p&gt;
&lt;p&gt;Django&amp;#8217;s nice enough to provide a &lt;tt&gt;@register.simple_tag&lt;/tt&gt; decorator for creating very basic tags that don&amp;#8217;t take a context but do take parameters. This is great, but what if you want more? Many Django applications use the same boilerplate time and time again to create their tags, but we make it much easier.&lt;/p&gt;
&lt;p&gt;Introducing &lt;tt&gt;@basictag&lt;/tt&gt; and &lt;tt&gt;@blocktag&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;tt&gt;@basictag&lt;/tt&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Ever wanted to use Django&amp;#8217;s &lt;tt&gt;@register.simple_tag&lt;/tt&gt; but needed access to the context? I&amp;#8217;ve found far too many cases where this would be useful, but Django doesn&amp;#8217;t make this easy. Your tag code would end up looking like this:&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="python python" style="font-family: monospace;"&gt;&lt;span style="color: #ff7700; font-weight: bold;"&gt;class&lt;/span&gt; MyTagNode&lt;span style="color: black;"&gt;&amp;#40;&lt;/span&gt;template.&lt;span style="color: black;"&gt;Node&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;#41;&lt;/span&gt;:
    &lt;span style="color: #ff7700; font-weight: bold;"&gt;def&lt;/span&gt; &lt;span style="color: #0000cd;"&gt;__init__&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #008000;"&gt;self&lt;/span&gt;, arg1, arg2&lt;span style="color: black;"&gt;&amp;#41;&lt;/span&gt;:
        &lt;span style="color: #008000;"&gt;self&lt;/span&gt;.&lt;span style="color: black;"&gt;arg1&lt;/span&gt; = arg1
        &lt;span style="color: #008000;"&gt;self&lt;/span&gt;.&lt;span style="color: black;"&gt;arg2&lt;/span&gt; = arg2
&amp;nbsp;
    &lt;span style="color: #ff7700; font-weight: bold;"&gt;def&lt;/span&gt; render&lt;span style="color: black;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #008000;"&gt;self&lt;/span&gt;, context&lt;span style="color: black;"&gt;&amp;#41;&lt;/span&gt;:
        arg1 = Variable&lt;span style="color: black;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #008000;"&gt;self&lt;/span&gt;.&lt;span style="color: black;"&gt;arg1&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;#41;&lt;/span&gt;.&lt;span style="color: black;"&gt;resolve&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;#40;&lt;/span&gt;context&lt;span style="color: black;"&gt;&amp;#41;&lt;/span&gt;
        arg2 = Variable&lt;span style="color: black;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #008000;"&gt;self&lt;/span&gt;.&lt;span style="color: black;"&gt;arg2&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;#41;&lt;/span&gt;.&lt;span style="color: black;"&gt;resolve&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;#40;&lt;/span&gt;context&lt;span style="color: black;"&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
        &lt;span style="color: #ff7700; font-weight: bold;"&gt;return&lt;/span&gt; context&lt;span style="color: black;"&gt;&amp;#91;&lt;/span&gt;&lt;span style="color: #483d8b;"&gt;'user'&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;#93;&lt;/span&gt;
&amp;nbsp;
@register.&lt;span style="color: black;"&gt;tag&lt;/span&gt;
&lt;span style="color: #ff7700; font-weight: bold;"&gt;def&lt;/span&gt; mytag&lt;span style="color: black;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: #dc143c;"&gt;parser&lt;/span&gt;, &lt;span style="color: #dc143c;"&gt;token&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;#41;&lt;/span&gt;:
    bits = &lt;span style="color: #dc143c;"&gt;token&lt;/span&gt;.&lt;span style="color: black;"&gt;split_contents&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;#40;&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;#41;&lt;/span&gt;
    &lt;span style="color: #ff7700; font-weight: bold;"&gt;return&lt;/span&gt; MyTagNode&lt;span style="color: black;"&gt;&amp;#40;&lt;/span&gt;bits&lt;span style="color: black;"&gt;&amp;#91;&lt;/span&gt;&lt;span style="color: #ff4500;"&gt;1&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;#93;&lt;/span&gt;, bits&lt;span style="color: black;"&gt;&amp;#91;&lt;/span&gt;&lt;span style="color: #ff4500;"&gt;2&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;#93;&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;#41;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Do this a few times and it&amp;#8217;s bound to drive you nuts. How about this instead?&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="python python" style="font-family: monospace;"&gt;&lt;span style="color: #ff7700; font-weight: bold;"&gt;from&lt;/span&gt; djblets.&lt;span style="color: black;"&gt;util&lt;/span&gt;.&lt;span style="color: black;"&gt;decorators&lt;/span&gt; &lt;span style="color: #ff7700; font-weight: bold;"&gt;import&lt;/span&gt; basictag
&amp;nbsp;
@register.&lt;span style="color: black;"&gt;tag&lt;/span&gt;
@basictag&lt;span style="color: black;"&gt;&amp;#40;&lt;/span&gt;takes_context=&lt;span style="color: #008000;"&gt;True&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;#41;&lt;/span&gt;
&lt;span style="color: #ff7700; font-weight: bold;"&gt;def&lt;/span&gt; mytag&lt;span style="color: black;"&gt;&amp;#40;&lt;/span&gt;context, arg1, arg2&lt;span style="color: black;"&gt;&amp;#41;&lt;/span&gt;:
    &lt;span style="color: #ff7700; font-weight: bold;"&gt;return&lt;/span&gt; context&lt;span style="color: black;"&gt;&amp;#91;&lt;/span&gt;&lt;span style="color: #483d8b;"&gt;'user'&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;#93;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Far less code and increased readability. Hooray!&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;tt&gt;@blocktag&lt;/tt&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;tt&gt;@blocktag&lt;/tt&gt; aims to do the same thing @basictag does but for block tags. A block tag is a tag that contains nested content, like &lt;tt&gt;@spaceless&lt;/tt&gt; or &lt;tt&gt;@for&lt;/tt&gt;. This usually requires even more boilerplate than the above code fragment, except with the added complexity of having to grab the contents of the block.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;ve condensed it down to this:&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;div class="code"&gt;&lt;pre class="python python" style="font-family: monospace;"&gt;&lt;span style="color: #ff7700; font-weight: bold;"&gt;from&lt;/span&gt; djblets.&lt;span style="color: black;"&gt;util&lt;/span&gt;.&lt;span style="color: black;"&gt;decorators&lt;/span&gt; &lt;span style="color: #ff7700; font-weight: bold;"&gt;import&lt;/span&gt; blocktag
&amp;nbsp;
@register.&lt;span style="color: black;"&gt;tag&lt;/span&gt;
@blocktag
&lt;span style="color: #ff7700; font-weight: bold;"&gt;def&lt;/span&gt; blinkblock&lt;span style="color: black;"&gt;&amp;#40;&lt;/span&gt;context, nodelist, arg1, arg2&lt;span style="color: black;"&gt;&amp;#41;&lt;/span&gt;:
    &lt;span style="color: #ff7700; font-weight: bold;"&gt;return&lt;/span&gt; &lt;span style="color: #483d8b;"&gt;&amp;quot;&amp;amp;lt;blink&amp;amp;gt;%s&amp;amp;lt;/blink&amp;amp;gt;&amp;quot;&lt;/span&gt; &lt;span style="color: #66cc66;"&gt;%&lt;/span&gt; nodelist.&lt;span style="color: black;"&gt;render&lt;/span&gt;&lt;span style="color: black;"&gt;&amp;#40;&lt;/span&gt;context&lt;span style="color: black;"&gt;&amp;#41;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you&amp;#8217;ve built block tags in the past, you&amp;#8217;ll appreciate how simple that was.&lt;/p&gt;
 &lt;div class="series_links"&gt;&lt;a href="http://www.chipx86.com/blog/2008/02/29/django-development-with-djblets/" title="Django Development with Djblets"&gt;Previous in series&lt;/a&gt; &lt;a href="http://www.chipx86.com/blog/2008/04/03/django-development-with-djblets-unrooting-your-urls/" title="Django Development with Djblets: Unrooting your URLs"&gt;Next in series&lt;/a&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=MXQRqdO9"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=KKDw4t9W"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=KKDw4t9W" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=ZdaSjHmm"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=ZdaSjHmm" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ReviewBoard?a=P6PEu7GE"&gt;&lt;img src="http://feeds.feedburner.com/~f/ReviewBoard?i=P6PEu7GE" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><author>chipx86@chipx86.com (chipx86)</author><pubDate>Fri, 29 Feb 2008 12:37:46 -0700</pubDate><guid>http://www.chipx86.com/blog/2008/02/29/django-development-with-djblets-custom-tag-helpers/</guid></item></channel></rss>
