<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
  <title>James Andres's Tips &amp; How-To's</title>
  
  <link href="http://jamesandres.com/post" rel="alternate" />
  <id>http://jamesandres.com/post</id>
  <updated>2008-09-17T16:14:38Z</updated>
  <author>
    <name>James Andres</name>
  </author>
  <link rel="self" href="http://feeds.feedburner.com/JamesAndressTipsHow-tos" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry>
    <title>Subversion Deployment: DGEDeploy v2 and DGEPush</title>
    <link href="http://feedproxy.google.com/~r/JamesAndressTipsHow-tos/~3/cqJ1RBCGB8I/Subversion-Deployment--Dge-Deploy-V2-And-Dge-Push-11" rel="alternate" />
    <id>http://jamesandres.com/post/show/11</id>
    <updated>2008-09-17T16:14:38Z</updated>
    <author>
      <name>James Andres</name>
    </author>
    <summary>Post summary</summary>
    <content type="html">
&lt;div class="post"&gt;
  

  &lt;h1&gt;Subversion Deployment: DGEDeploy v2 and DGEPush&lt;/h1&gt;

  &lt;div class="post-header"&gt;Wednesday, September 17, 2008&lt;/div&gt;
  &lt;!-- begin post body --&gt;
  &lt;div&gt;Back in February I released a Ruby script called &lt;a href="/post/show/Dge-Deploy-Is-A-Subversion-Merging-And-Release-Control-Script-5"&gt;DGEDeploy&lt;/a&gt; .
We use DGEDeploy internally at &lt;a href="http://www.donatgroup.com"&gt;Donat Group&lt;/a&gt; to
help manage several of our project deployments.

	&lt;p&gt;Besides being a misnomer, DGEDeploy had one major weak spot: actually pushing
code to servers.  That, and a few other bugs, are fixed now in this
latest release.  Heck, lets call it version 2.&lt;/p&gt;


	&lt;p&gt;The latest version adds a new script, DGEPush, that acts as a simple &lt;a href="http://en.wikipedia.org/wiki/Rsync"&gt;RSync&lt;/a&gt;
front-end.  When using &lt;span class="caps"&gt;SSH&lt;/span&gt; keys it&amp;#8217;s a breeze to merge a development branch
into staging and push to the server.&lt;/p&gt;


	&lt;p&gt;DGEPush features list:
 * Rsync&amp;#8217;s code using the -C option to skip &lt;code&gt;.svn&lt;/code&gt; and &lt;code&gt;CVS&lt;/code&gt;
   directories.  This saves server space, and is a better security practice.
 * Can use &lt;span class="caps"&gt;SSH&lt;/span&gt; keys for better security and ease of use.
 * Can deploy to multiple servers in one shot.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s how you get it running:&lt;/p&gt;


	&lt;h3&gt;Create a &lt;em&gt;dgepush&lt;/em&gt; user, on your remote server&lt;/h3&gt;


On Ubuntu / Debian this is as simple as:
&lt;pre&gt;
# Log into your remote server
ssh remote-server.com

# Create an account called 'dgepush'
sudo adduser dgepush
&lt;/pre&gt;

If you like, set up key based password-less logins for the remote user:
&lt;pre&gt;
# On 'local' machine, ie: your laptop
sudo adduser dgepush
sudo su dgepush
cd ~

# Create the SSH keys
mkdir -m 700 .ssh
cd .ssh
ssh-keygen -t rsa -f dgepush-key
# !! Don't enter a passphrase, just hit Enter and Enter.

# Copy the key to the remote machine, this syntax only works on Linux.
# Possibly only on Debian / Ubuntu Linux.
ssh-copy-id -i ~/.ssh/dgepush-key.pub dgepush@remote-server.com
&lt;/pre&gt;

	&lt;p&gt;Test your &lt;span class="caps"&gt;SSH&lt;/span&gt; keys &lt;code&gt;ssh -i /home/dgepush/.ssh/dgepush-key dgepush@remote-server.com&lt;/code&gt;
should log right in without a password.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s some other tutorials on the subject:
 * &lt;a href="http://www.debian-administration.org/articles/152"&gt;Password-less logins with OpenSSH&lt;/a&gt;
 * &lt;a href="http://rcsg-gsir.imsb-dsgi.nrc-cnrc.gc.ca/documents/internet/node31.html"&gt;ssh-keygen: password-less &lt;span class="caps"&gt;SSH&lt;/span&gt; login&lt;/a&gt;&lt;/p&gt;


	&lt;h3&gt;Update your dgedeploy-projects.conf&lt;/h3&gt;


	&lt;p&gt;Adding a &amp;#8216;servers&amp;#8217; section to any workflow enables you to get started with
DGEPush.&lt;/p&gt;


	&lt;p&gt;&lt;small&gt;/etc/dgedeploy/dgedeploy-projects.conf&lt;/small&gt;
&lt;pre class='yaml'&gt;&lt;span class='comment'&gt;# YAML 1.1&lt;/span&gt;
&lt;span class='comment'&gt;# Settings for example-project deployment&lt;/span&gt;
&lt;span class='key'&gt;example-project&lt;/span&gt;&lt;span class='punct'&gt;:&lt;/span&gt;
  &lt;span class='comment'&gt;# The workflow field is required, the order of the parameters specify which&lt;/span&gt;
  &lt;span class='comment'&gt;# branch merges with which branch.  eg:&lt;/span&gt;
  &lt;span class='comment'&gt;#     development --&amp;gt; staging --&amp;gt; live&lt;/span&gt;
  &lt;span class='key'&gt;workflow&lt;/span&gt;&lt;span class='punct'&gt;:&lt;/span&gt;
    &lt;span class='punct'&gt;-&lt;/span&gt; development
    &lt;span class='punct'&gt;-&lt;/span&gt; staging
    &lt;span class='punct'&gt;-&lt;/span&gt; live
  &lt;span class='key'&gt;development&lt;/span&gt;&lt;span class='punct'&gt;:&lt;/span&gt;
    &lt;span class='comment'&gt;# The order of the urls parameter is important.  The first in the list will&lt;/span&gt;
    &lt;span class='comment'&gt;# be used as the default choice whenever necessary.  Each url should be,&lt;/span&gt;
    &lt;span class='comment'&gt;# a directory inside a Subversion repository, of course.  All urls should&lt;/span&gt;
    &lt;span class='comment'&gt;# be in the SAME Subversion repository.&lt;/span&gt;
    &lt;span class='key'&gt;urls&lt;/span&gt;&lt;span class='punct'&gt;:&lt;/span&gt;
      &lt;span class='punct'&gt;-&lt;/span&gt; http://example.com/svn/example-project/trunk
  &lt;span class='key'&gt;staging&lt;/span&gt;&lt;span class='punct'&gt;:&lt;/span&gt;
    &lt;span class='key'&gt;urls&lt;/span&gt;&lt;span class='punct'&gt;:&lt;/span&gt;
      &lt;span class='punct'&gt;-&lt;/span&gt; http://example.com/svn/example-project/tags/staging
    &lt;span class='key'&gt;servers&lt;/span&gt;&lt;span class='punct'&gt;:&lt;/span&gt;
      &lt;span class='comment'&gt;# This server uses key based password-less logins.&lt;/span&gt;
      &lt;span class='punct'&gt;-&lt;/span&gt; &lt;span class='punct'&gt;&amp;quot;&lt;/span&gt;&lt;span class='string'&gt;-e 'ssh -i /home/dgepush/.ssh/dgepush-key' dgepush@stage.com:/var/www/stage.com/&lt;/span&gt;&lt;span class='punct'&gt;&amp;quot;&lt;/span&gt;
      &lt;span class='comment'&gt;# You can push to multiple servers by adding more lines!&lt;/span&gt;
      &lt;span class='punct'&gt;-&lt;/span&gt; &lt;span class='punct'&gt;&amp;quot;&lt;/span&gt;&lt;span class='string'&gt;dgepush@mirror-stage.com:/var/www/mirror-stage.com/&lt;/span&gt;&lt;span class='punct'&gt;&amp;quot;&lt;/span&gt;
  &lt;span class='key'&gt;live&lt;/span&gt;&lt;span class='punct'&gt;:&lt;/span&gt;
    &lt;span class='key'&gt;urls&lt;/span&gt;&lt;span class='punct'&gt;:&lt;/span&gt;
      &lt;span class='punct'&gt;-&lt;/span&gt; http://example.com/svn/example-project/tags/live
    &lt;span class='key'&gt;servers&lt;/span&gt;&lt;span class='punct'&gt;:&lt;/span&gt;
    &lt;span class='comment'&gt;# This server will require a password every time DGEPush is run.&lt;/span&gt;
    &lt;span class='punct'&gt;-&lt;/span&gt; &lt;span class='punct'&gt;&amp;quot;&lt;/span&gt;&lt;span class='string'&gt;dgepush@live.com:/var/www/live.com/&lt;/span&gt;&lt;span class='punct'&gt;&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;


	&lt;h3&gt;DGEPush in action&lt;/h3&gt;


	&lt;p&gt;If you have already got DGEDeploy up and running using DGEPush is one more step.
Here&amp;#8217;s a basic example:&lt;/p&gt;


&lt;pre&gt;
# First merge trunk into staging branch
sudo dgedeploy example-project http://example.com/svn/example-project/trunk
# Next push the staging branch to the server
sudo -u dgepush  dgepush example-project staging
&lt;/pre&gt;

	&lt;p&gt;Important points:
 * &lt;code&gt;sudo -u dgepush&lt;/code&gt; runs the command as the dgepush user
 * &lt;code&gt;dgepush example-project staging&lt;/code&gt; copies the contents of the
   dgedeploy cace for &amp;#8216;example-project/staging&amp;#8217; to remote server.  In other
   words, DGEPush won&amp;#8217;t work unless you have initialized your project with
   DGEDeploy at least once.&lt;/p&gt;


	&lt;p&gt;&lt;img title='DGEDeploy-v2.0.tar.gz' src='/images/tango-attachment-24.png' alt='file attachment' style='vertical-align: middle;'/&gt;
   Download &lt;a href="/downloads/DGEDeploy-v2.0.tar.gz"&gt;DGEDeploy-v2.0.tar.gz&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
  &lt;!-- end post body --&gt;

  &lt;div class="links"&gt;
    
      &lt;span&gt;&lt;a href="/comment/new/11"&gt;new comment&lt;/a&gt;&lt;/span&gt;
    
  &lt;/div&gt;

  
&lt;/div&gt;    </content>
  <feedburner:origLink>http://jamesandres.com/post/show/Subversion-Deployment--Dge-Deploy-V2-And-Dge-Push-11</feedburner:origLink></entry>
  <entry>
    <title>Back on the blogging train</title>
    <link href="http://feedproxy.google.com/~r/JamesAndressTipsHow-tos/~3/JbhIJH8XLDI/Back-On-The-Blogging-Train-10" rel="alternate" />
    <id>http://jamesandres.com/post/show/10</id>
    <updated>2008-09-17T05:51:32Z</updated>
    <author>
      <name>James Andres</name>
    </author>
    <summary>Post summary</summary>
    <content type="html">
&lt;div class="post"&gt;
  

  &lt;h1&gt;Back on the blogging train&lt;/h1&gt;

  &lt;div class="post-header"&gt;Wednesday, September 17, 2008&lt;/div&gt;
  &lt;!-- begin post body --&gt;
  &lt;div&gt;Wheew, it&amp;#8217;s been a crazy summer.  Excuses for my absence include:

	&lt;p&gt;&lt;a href="http://jameselaine.blogspot.com/"&gt;I got married!&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;img src='http://farm4.static.flickr.com/3220/2851768753_e5af8cf590.jpg?v=0' alt='James and Elaine by Plaza of Nations'/&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.flickr.com/photos/jamesandres/2472408541"&gt;I moved!&lt;/a&gt;&lt;/p&gt;


&lt;object data='http://www.flickr.com/apps/video/stewart.swf?v=60247' type='application/x-shockwave-flash' height='300' classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' width='400'&gt; &lt;param name='flashvars' value='intl_lang=en-us&amp;amp;photo_secret=3a44a83477&amp;amp;photo_id=2472408541'/&gt; &lt;param name='movie' value='http://www.flickr.com/apps/video/stewart.swf?v=60247'/&gt; &lt;param name='bgcolor' value='#000000'/&gt; &lt;param name='allowFullScreen' value='true'/&gt;&lt;embed src='http://www.flickr.com/apps/video/stewart.swf?v=60247' allowfullscreen='true' type='application/x-shockwave-flash' height='300' flashvars='intl_lang=en-us&amp;amp;photo_secret=3a44a83477&amp;amp;photo_id=2472408541' bgcolor='#000000' width='400'/&gt;&lt;/object&gt;

	&lt;p&gt;Ahhh glad to be back.&lt;/div&gt;&lt;/p&gt;
  &lt;!-- end post body --&gt;

  &lt;div class="links"&gt;
    
      &lt;span&gt;&lt;a href="/comment/new/10"&gt;new comment&lt;/a&gt;&lt;/span&gt;
    
  &lt;/div&gt;

  
&lt;/div&gt;    </content>
  <feedburner:origLink>http://jamesandres.com/post/show/Back-On-The-Blogging-Train-10</feedburner:origLink></entry>
  <entry>
    <title>HOWTO Compile MPD With AAC/M4A Support on Ubuntu</title>
    <link href="http://feedproxy.google.com/~r/JamesAndressTipsHow-tos/~3/d9MfkPi0pcY/Howto-Compile-Mpd-With-Aac-M4-A-Support-On-Ubuntu-6" rel="alternate" />
    <id>http://jamesandres.com/post/show/6</id>
    <updated>2008-11-12T20:00:21Z</updated>
    <author>
      <name>James Andres</name>
    </author>
    <summary>Post summary</summary>
    <content type="html">
&lt;div class="post"&gt;
  

  &lt;h1&gt;HOWTO Compile MPD With AAC/M4A Support on Ubuntu&lt;/h1&gt;

  &lt;div class="post-header"&gt;Monday, March 24, 2008&lt;/div&gt;
  &lt;!-- begin post body --&gt;
  &lt;div&gt;Linux&amp;#8217;s Music Player Daemon, &lt;span class="caps"&gt;MPD&lt;/span&gt;, is an interface-less jukebox.  It&amp;#8217;s like
iTunes, Winamp, or Rhythm Box, except there is no built in &lt;span class="caps"&gt;GUI&lt;/span&gt;.  Think of it
as the Apache or MySQL of the music player world.

	&lt;p&gt;&lt;span class="caps"&gt;MPD&lt;/span&gt; is great for remotely controlling your Linux powered entertainment system
or, as in my office&amp;#8217;s case, to allow 15 staff to each act as work-day DJs.&lt;/p&gt;


	&lt;p&gt;Our office music server runs Ubuntu 7.10, but the default mpd package for
Ubuntu doesn&amp;#8217;t have &lt;span class="caps"&gt;M4A&lt;/span&gt; (AAC) support for &lt;span class="caps"&gt;MPD&lt;/span&gt;.  Here&amp;#8217;s what we did to
re-compile &lt;span class="caps"&gt;MPD&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;This tutorial will set you up with a new &lt;span class="caps"&gt;MPD&lt;/span&gt; with support for &lt;span class="caps"&gt;OSS&lt;/span&gt;/ALSA that
will play the following formats:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;span class="caps"&gt;MP3&lt;/span&gt;&lt;/li&gt;
		&lt;li&gt;&lt;span class="caps"&gt;AAC&lt;/span&gt;&lt;/li&gt;
		&lt;li&gt;&lt;span class="caps"&gt;OGG&lt;/span&gt; Vorbis&lt;/li&gt;
		&lt;li&gt;&lt;span class="caps"&gt;FLAC&lt;/span&gt;&lt;/li&gt;
		&lt;li&gt;&lt;span class="caps"&gt;WAV&lt;/span&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;First, &lt;span class="caps"&gt;MPD&lt;/span&gt; requires libfaad2-dev and libmp4v2-dev to compile with &lt;span class="caps"&gt;AAC&lt;/span&gt;
support.  I&amp;#8217;m using the debian-multimedia repositories to get these packages
and they don&amp;#8217;t have versions of libfaad2-dev and libmp4v2-dev suitable for
Ubuntu 8.10.&lt;/p&gt;


	&lt;p&gt;No worries, this is a good excuse to learn how to build packages &amp;#8220;gentoo
style&amp;#8221; using apt to build packages from source.&lt;/p&gt;


	&lt;p&gt;You&amp;#8217;ll need the appropriate repositories enabled.  Check your
&lt;strong&gt;/etc/apt/sources.list&lt;/strong&gt; file to ensure you have at least universe and
multiverse enabled.  Then add the debian-multimedia repositories.  Append the
below lines to your &lt;strong&gt;/etc/apt/sources.list&lt;/strong&gt;.&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class='comment'&gt;## Debian Multimedia&lt;/span&gt;
&lt;span class='ident'&gt;deb&lt;/span&gt; &lt;span class='ident'&gt;http&lt;/span&gt;&lt;span class='punct'&gt;:/&lt;/span&gt;&lt;span class='regex'/&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;www&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='ident'&gt;debian&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;multimedia&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='ident'&gt;org&lt;/span&gt; &lt;span class='ident'&gt;stable&lt;/span&gt; &lt;span class='ident'&gt;main&lt;/span&gt;
&lt;span class='ident'&gt;deb&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;src&lt;/span&gt; &lt;span class='ident'&gt;http&lt;/span&gt;&lt;span class='punct'&gt;:/&lt;/span&gt;&lt;span class='regex'/&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;www&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='ident'&gt;debian&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;multimedia&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='ident'&gt;org&lt;/span&gt; &lt;span class='ident'&gt;stable&lt;/span&gt; &lt;span class='ident'&gt;main&lt;/span&gt;
&lt;span class='ident'&gt;deb&lt;/span&gt; &lt;span class='ident'&gt;http&lt;/span&gt;&lt;span class='punct'&gt;:/&lt;/span&gt;&lt;span class='regex'/&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;www&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='ident'&gt;debian&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;multimedia&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='ident'&gt;org&lt;/span&gt; &lt;span class='ident'&gt;testing&lt;/span&gt; &lt;span class='ident'&gt;main&lt;/span&gt;
&lt;span class='ident'&gt;deb&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;src&lt;/span&gt; &lt;span class='ident'&gt;http&lt;/span&gt;&lt;span class='punct'&gt;:/&lt;/span&gt;&lt;span class='regex'/&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;www&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='ident'&gt;debian&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;multimedia&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='ident'&gt;org&lt;/span&gt; &lt;span class='ident'&gt;testing&lt;/span&gt; &lt;span class='ident'&gt;main&lt;/span&gt;
&lt;span class='ident'&gt;deb&lt;/span&gt; &lt;span class='ident'&gt;http&lt;/span&gt;&lt;span class='punct'&gt;:/&lt;/span&gt;&lt;span class='regex'/&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;www&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='ident'&gt;debian&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;multimedia&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='ident'&gt;org&lt;/span&gt; &lt;span class='ident'&gt;unstable&lt;/span&gt; &lt;span class='ident'&gt;main&lt;/span&gt;
&lt;span class='ident'&gt;deb&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;src&lt;/span&gt; &lt;span class='ident'&gt;http&lt;/span&gt;&lt;span class='punct'&gt;:/&lt;/span&gt;&lt;span class='regex'/&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;www&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='ident'&gt;debian&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;multimedia&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='ident'&gt;org&lt;/span&gt; &lt;span class='ident'&gt;unstable&lt;/span&gt; &lt;span class='ident'&gt;main&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;Update your apt package database with an &lt;code&gt;apt-get update&lt;/code&gt;.  Next,
we need to install the basic dependencies that will allow you to compile the
software.&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class='ident'&gt;sudo&lt;/span&gt; &lt;span class='ident'&gt;apt&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;get&lt;/span&gt; &lt;span class='ident'&gt;install&lt;/span&gt; &lt;span class='ident'&gt;build&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;essential&lt;/span&gt; &lt;span class='ident'&gt;dpkg&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; \
     &lt;span class='ident'&gt;debhelper&lt;/span&gt; &lt;span class='ident'&gt;libasound2&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; &lt;span class='ident'&gt;libid3tag0&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; \
     &lt;span class='ident'&gt;ccache&lt;/span&gt; &lt;span class='ident'&gt;libxvidcore4&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; &lt;span class='ident'&gt;libid3&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='number'&gt;3.8&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='number'&gt;3&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; \
     &lt;span class='ident'&gt;libgtk2&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='number'&gt;0&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; &lt;span class='ident'&gt;libesd0&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; &lt;span class='ident'&gt;libsdl1&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='number'&gt;2&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; \
     &lt;span class='ident'&gt;liba52&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; &lt;span class='ident'&gt;liblame&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; &lt;span class='ident'&gt;libxt&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; \
     &lt;span class='ident'&gt;nasm&lt;/span&gt; &lt;span class='ident'&gt;libx264&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; &lt;span class='ident'&gt;dpatch&lt;/span&gt; \
     &lt;span class='ident'&gt;autotools&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; &lt;span class='ident'&gt;libfaad&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; &lt;span class='ident'&gt;libvorbis&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; \
     &lt;span class='ident'&gt;libimlib2&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; &lt;span class='ident'&gt;libfaac&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; &lt;span class='ident'&gt;texi2html&lt;/span&gt; \
     &lt;span class='ident'&gt;libtheora&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; &lt;span class='ident'&gt;libgsm1&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; &lt;span class='ident'&gt;libxvmc&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; \
     &lt;span class='ident'&gt;libamrnb&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; &lt;span class='ident'&gt;libamrwb&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; &lt;span class='ident'&gt;libsamplerate0&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; \
     &lt;span class='ident'&gt;libflac&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; &lt;span class='ident'&gt;fakeroot&lt;/span&gt; &lt;span class='ident'&gt;checkinstall&lt;/span&gt; \
     &lt;span class='ident'&gt;libmp3lame&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; &lt;span class='ident'&gt;quilt&lt;/span&gt; &lt;span class='ident'&gt;libdc1394&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='number'&gt;22&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; \
     &lt;span class='ident'&gt;libdirac&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; &lt;span class='ident'&gt;libschroedinger&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;Once that has finished coming down the wire we&amp;#8217;re almost ready to start
compiling.  Let&amp;#8217;s get the &lt;span class="caps"&gt;MPD&lt;/span&gt; source code, and some initial dependencies.&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class='ident'&gt;sudo&lt;/span&gt; &lt;span class='ident'&gt;mkdir&lt;/span&gt; &lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;p&lt;/span&gt; &lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;usr&lt;/span&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;local&lt;/span&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;src&lt;/span&gt;
&lt;span class='ident'&gt;cd&lt;/span&gt; &lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;usr&lt;/span&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;local&lt;/span&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;src&lt;/span&gt;
&lt;span class='ident'&gt;sudo&lt;/span&gt; &lt;span class='ident'&gt;wget&lt;/span&gt; &lt;span class='ident'&gt;http&lt;/span&gt;&lt;span class='punct'&gt;:/&lt;/span&gt;&lt;span class='regex'/&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;www&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='ident'&gt;musicpd&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='ident'&gt;org&lt;/span&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;uploads&lt;/span&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;files&lt;/span&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;mpd&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='number'&gt;0.13&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='number'&gt;2&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='ident'&gt;tar&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='ident'&gt;gz&lt;/span&gt;
&lt;span class='ident'&gt;sudo&lt;/span&gt; &lt;span class='ident'&gt;tar&lt;/span&gt; &lt;span class='ident'&gt;zxvf&lt;/span&gt; &lt;span class='ident'&gt;mpd&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='number'&gt;0.13&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='number'&gt;2&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='ident'&gt;tar&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='ident'&gt;gz&lt;/span&gt;
&lt;span class='ident'&gt;sudo&lt;/span&gt; &lt;span class='ident'&gt;chown&lt;/span&gt; &lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='constant'&gt;R&lt;/span&gt; &lt;span class='punct'&gt;&amp;quot;&lt;/span&gt;&lt;span class='string'&gt;$USER&lt;/span&gt;&lt;span class='punct'&gt;&amp;quot;&lt;/span&gt;&lt;span class='symbol'&gt;:admin&lt;/span&gt; &lt;span class='ident'&gt;mpd&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='number'&gt;0.13&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='number'&gt;2&lt;/span&gt;&lt;span class='punct'&gt;*&lt;/span&gt;
&lt;/pre&gt;
&lt;small&gt;&lt;span class="caps"&gt;NOTE&lt;/span&gt;: The above snippet download&amp;#8217;s mpd version 0.13.2.  This is up to
date as of November 12, 2008.&lt;/small&gt;

	&lt;p&gt;Time to compile!  We&amp;#8217;re using &lt;code&gt;apt-get -b source PACKAGE-NAME&lt;/code&gt; to
download and compile the source packages.  This is a good way to do things
since it will create &lt;span class="caps"&gt;DEB&lt;/span&gt; packages automatically, plus it&amp;#8217;s good Debian form.
I recommend learning how to use this feature of apt.&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class='ident'&gt;sudo&lt;/span&gt; &lt;span class='ident'&gt;apt&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;get&lt;/span&gt; &lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;b&lt;/span&gt; &lt;span class='ident'&gt;source&lt;/span&gt; &lt;span class='ident'&gt;libavcodec&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt; &lt;span class='ident'&gt;libavutil&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;dev&lt;/span&gt;
&lt;span class='ident'&gt;sudo&lt;/span&gt; &lt;span class='ident'&gt;dpkg&lt;/span&gt; &lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;i&lt;/span&gt; &lt;span class='punct'&gt;*.&lt;/span&gt;&lt;span class='ident'&gt;deb&lt;/span&gt;
&lt;span class='ident'&gt;sudo&lt;/span&gt; &lt;span class='ident'&gt;apt&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;get&lt;/span&gt; &lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;b&lt;/span&gt; &lt;span class='ident'&gt;source&lt;/span&gt; &lt;span class='ident'&gt;libmp4v2&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='number'&gt;0&lt;/span&gt;
&lt;span class='ident'&gt;sudo&lt;/span&gt; &lt;span class='ident'&gt;dpkg&lt;/span&gt; &lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='ident'&gt;i&lt;/span&gt; &lt;span class='punct'&gt;*.&lt;/span&gt;&lt;span class='ident'&gt;deb&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;Lastly we compile and install mpd.  Run the following commands.&lt;/p&gt;


&lt;pre class='ruby'&gt;
&lt;span class='ident'&gt;cd&lt;/span&gt; &lt;span class='ident'&gt;mpd&lt;/span&gt;&lt;span class='punct'&gt;-&lt;/span&gt;&lt;span class='number'&gt;0.13&lt;/span&gt;&lt;span class='punct'&gt;.&lt;/span&gt;&lt;span class='number'&gt;2&lt;/span&gt;
&lt;span class='ident'&gt;make&lt;/span&gt; &lt;span class='ident'&gt;clean&lt;/span&gt;
&lt;span class='punct'&gt;./&lt;/span&gt;&lt;span class='regex'&gt;configure
make
sudo checkinstall -D make install
sudo ln -s &lt;/span&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;usr&lt;/span&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;local&lt;/span&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;bin&lt;/span&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;mpd&lt;/span&gt; &lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;usr&lt;/span&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;bin&lt;/span&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='ident'&gt;mpd&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;If you haven&amp;#8217;t received any errors, then you&amp;#8217;re good to go!&lt;/p&gt;


	&lt;p&gt;The &lt;a href="http://mpd.wikia.com/wiki/Configuration"&gt;&lt;span class="caps"&gt;MPD&lt;/span&gt; Wiki&lt;/a&gt; is a good resource for
help with the rest of the set up and configuration.&lt;/div&gt;&lt;/p&gt;
  &lt;!-- end post body --&gt;

  &lt;div class="links"&gt;
    
      &lt;span&gt;&lt;a href="/comment/new/6"&gt;new comment&lt;/a&gt;&lt;/span&gt;
    
  &lt;/div&gt;

  
&lt;/div&gt;    </content>
  <feedburner:origLink>http://jamesandres.com/post/show/Howto-Compile-Mpd-With-Aac-M4-A-Support-On-Ubuntu-6</feedburner:origLink></entry>
  <entry>
    <title>DGEDeploy Is A Subversion Merging And Release Control Script</title>
    <link href="http://feedproxy.google.com/~r/JamesAndressTipsHow-tos/~3/hKK91VwSoPA/Dge-Deploy-Is-A-Subversion-Merging-And-Release-Control-Script-5" rel="alternate" />
    <id>http://jamesandres.com/post/show/5</id>
    <updated>2008-02-24T07:37:29Z</updated>
    <author>
      <name>James Andres</name>
    </author>
    <summary>Post summary</summary>
    <content type="html">
&lt;div class="post"&gt;
  

  &lt;h1&gt;DGEDeploy Is A Subversion Merging And Release Control Script&lt;/h1&gt;

  &lt;div class="post-header"&gt;Sunday, February 24, 2008&lt;/div&gt;
  &lt;!-- begin post body --&gt;
  &lt;div&gt;DGEDeploy is a Ruby script that helps make subversion merges a little
easier.  I wrote it at &lt;a href="http://donatgroup.com"&gt;Donat Group Enterprises&lt;/a&gt; for use
as a light weight tagging and release control solution.

	&lt;h3&gt;Why?&lt;/h3&gt;


	&lt;p&gt;I wrote DGEDeploy to:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Make tedious &amp;#8216;svn merge&amp;#8217; commands easier to use.&lt;/li&gt;
		&lt;li&gt;Reduce the number of typos when running &amp;#8216;svn merge&amp;#8217; commands.&lt;/li&gt;
		&lt;li&gt;Be extremely simple, its not meant to replace Capistrano, CruiseControl, ...&lt;/li&gt;
		&lt;li&gt;To improve my Ruby scripting skills&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;There are a lot of similar scripts out there, but if you find this one useful
please let me know :-).&lt;/p&gt;


	&lt;h3&gt;How does it work?&lt;/h3&gt;


	&lt;p&gt;The script uses two configuration files to keep track of vital settings.  The
first, &amp;#8216;dgedeploy.conf&amp;#8217;, stores settings for the script itself (ie: subversion
credentials).  The second, &amp;#8216;dgedeploy-projects.conf&amp;#8217; stores information about
your codebase and projects.&lt;/p&gt;


	&lt;p&gt;All settings are stored in the &lt;a href="http://www.yaml.org/"&gt;&lt;span class="caps"&gt;YAML&lt;/span&gt;&lt;/a&gt; format.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Example: /etc/dgedeploy/dgedeploy-projects.conf&lt;/strong&gt;&lt;/p&gt;


&lt;pre class='yaml'&gt;&lt;span class='comment'&gt;# YAML 1.1&lt;/span&gt;
&lt;span class='comment'&gt;# Settings for example-project deployment&lt;/span&gt;
&lt;span class='key'&gt;example-project&lt;/span&gt;&lt;span class='punct'&gt;:&lt;/span&gt;
  &lt;span class='comment'&gt;# The workflow field is required, the order of the parameters specify which&lt;/span&gt;
  &lt;span class='comment'&gt;# branch merges with which branch.  eg:&lt;/span&gt;
  &lt;span class='comment'&gt;#     development --&amp;gt; staging --&amp;gt; live&lt;/span&gt;
  &lt;span class='key'&gt;workflow&lt;/span&gt;&lt;span class='punct'&gt;:&lt;/span&gt;
    &lt;span class='punct'&gt;-&lt;/span&gt; development
    &lt;span class='punct'&gt;-&lt;/span&gt; staging
    &lt;span class='punct'&gt;-&lt;/span&gt; live
  &lt;span class='key'&gt;development&lt;/span&gt;&lt;span class='punct'&gt;:&lt;/span&gt;
    &lt;span class='comment'&gt;# The order of the urls parameter is important.  The first in the list will&lt;/span&gt;
    &lt;span class='comment'&gt;# be used as the default choice whenever necessary.  Each url should be,&lt;/span&gt;
    &lt;span class='comment'&gt;# a directory inside a Subversion repository, of course.  All urls should&lt;/span&gt;
    &lt;span class='comment'&gt;# be in the SAME Subversion repository.&lt;/span&gt;
    &lt;span class='key'&gt;urls&lt;/span&gt;&lt;span class='punct'&gt;:&lt;/span&gt;
      &lt;span class='punct'&gt;-&lt;/span&gt; http://example.com/svn/example-project/trunk
  &lt;span class='key'&gt;staging&lt;/span&gt;&lt;span class='punct'&gt;:&lt;/span&gt;
    &lt;span class='key'&gt;urls&lt;/span&gt;&lt;span class='punct'&gt;:&lt;/span&gt;
      &lt;span class='punct'&gt;-&lt;/span&gt; http://example.com/svn/example-project/tags/staging
  &lt;span class='key'&gt;live&lt;/span&gt;&lt;span class='punct'&gt;:&lt;/span&gt;
    &lt;span class='key'&gt;urls&lt;/span&gt;&lt;span class='punct'&gt;:&lt;/span&gt;
      &lt;span class='punct'&gt;-&lt;/span&gt; http://example.com/svn/example-project/tags/live&lt;/pre&gt;

	&lt;p&gt;So, as shown in the configuration example above, the script is based on
workflows.  Merges always happen forward and must hit every level in the chain.
This ensures your development code doesn&amp;#8217;t go straight to live without being
merged into staging first.&lt;/p&gt;


	&lt;h3&gt;Make a merge&lt;/h3&gt;


	&lt;p&gt;The syntax for the script is fairly straightforward.  Once you have everything
installed (see &lt;span class="caps"&gt;README&lt;/span&gt;.txt for details) you initialize your working copies
like so &amp;#8230;&lt;/p&gt;


&lt;pre&gt;dgedeploy example-project initialize&lt;/pre&gt;

	&lt;p&gt;After the working copy caches are setup a merge can be performed using the same
script.  This example merges all of trunk into staging.&lt;/p&gt;


&lt;pre&gt;dgedeploy example-project \
  http://example.com/svn/example-project/trunk

#
# Translates to ...
#   svn merge \
#   http://example.com/svn/example-project/tags/staging \
#   http://example.com/svn/example-project/trunk \
#   /var/cache/dgedeploy/example-project/tags/staging
#&lt;/pre&gt;

	&lt;p&gt;DGEDeploy will also merge just specific subdirectories.  To send
only a certain subdirectory from staging to live run a command like this &amp;#8230;&lt;/p&gt;


&lt;pre&gt;dgedeploy example-project \
  http://example.com/svn/example-project/tags/staging/sub-dir

#
# Translates to ...
#   svn merge \
#   http://example.com/svn/example-project/tags/live/sub-dir \
#   http://example.com/svn/example-project/tags/staging/sub-dir \
#   /var/cache/dgedeploy/example-project/tags/live/sub-dir
#&lt;/pre&gt;

	&lt;p&gt;Enjoy!&lt;/p&gt;


	&lt;p&gt;James.&lt;/p&gt;


	&lt;p&gt;&lt;img title='DGEDeploy.tar.gz' src='/images/tango-attachment-24.png' alt='file attachment' style='vertical-align: middle;'/&gt;
Download &lt;a href="/downloads/DGEDeploy.tar.gz"&gt;DGEDeploy.tar.gz&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
  &lt;!-- end post body --&gt;

  &lt;div class="links"&gt;
    
      &lt;span&gt;&lt;a href="/comment/new/5"&gt;new comment&lt;/a&gt;&lt;/span&gt;
    
  &lt;/div&gt;

  
&lt;/div&gt;    </content>
  <feedburner:origLink>http://jamesandres.com/post/show/Dge-Deploy-Is-A-Subversion-Merging-And-Release-Control-Script-5</feedburner:origLink></entry>
  <entry>
    <title>Hook ordering in Drupal</title>
    <link href="http://feedproxy.google.com/~r/JamesAndressTipsHow-tos/~3/qaJ4ly3DE_Q/Hook-Ordering-In-Drupal-4" rel="alternate" />
    <id>http://jamesandres.com/post/show/4</id>
    <updated>2008-01-30T04:49:36Z</updated>
    <author>
      <name>James Andres</name>
    </author>
    <summary>Post summary</summary>
    <content type="html">
&lt;div class="post"&gt;
  

  &lt;h1&gt;Hook ordering in Drupal&lt;/h1&gt;

  &lt;div class="post-header"&gt;Wednesday, January 30, 2008&lt;/div&gt;
  &lt;!-- begin post body --&gt;
  &lt;div&gt;I use Drupal &lt;i&gt;a lot&lt;/i&gt;.  This has caused me to become atuned to some of it&amp;#8217;s foibles.
Hook ordering, the order in which hooks/callbacks are called, is a one issue that
agrevates me quite often.  There just doesn&amp;#8217;t seem to be a &lt;i&gt;Right Way&lt;/i&gt; &lt;sup&gt;TM&lt;/sup&gt;
to get out of a hook ordering jam.

	&lt;p&gt;The community has taken a few stabs at the hook ordering problem.  Sometimes the
concept of a &amp;#8220;hook registry&amp;#8221; has been used.  Here&amp;#8217;s two threads I found on the issue
(if anyone knows of some newer ones please let me know!):&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://lists.drupal.org/pipermail/development/2007-January/021604.html"&gt;Hook ordering&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://lists.drupal.org/pipermail/development/2007-January/022081.html"&gt;Eliminate hooks entirely in Drupal 6&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;I haven&amp;#8217;t seen any commited code relating to hook orderig or a hook registry in
Drupal 6, though I think it may have found new life in the updated menu system.&lt;/p&gt;


	&lt;p&gt;Alas, I was really hoping hook ordering of some form would make it into Drupal 6.  So
over the next few paragrahs I&amp;#8217;ll lay out my grand vision for hook ordering.&lt;/p&gt;


	&lt;h3&gt;Here lies James&amp;#8217; receipe for hook ordering in Drupal&lt;/h3&gt;


	&lt;p&gt;First, the links above contain some fairly drastic ideas on how to implement a
hook ordering system.  I propose something a little simpler.&lt;/p&gt;


	&lt;p&gt;Reasons why, I think, my solution is simpler:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;It requires the addition of only one hook&lt;/li&gt;
		&lt;li&gt;It requires only a few lines of extra, unobtrusive, code to the core&lt;/li&gt;
		&lt;li&gt;It won&amp;#8217;t affect any existing contrib or core modules&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Also, please feel free to steal my ideas for something else if you like, I got the
idea from the Compiz project anyway&amp;#8212;namely their plugin dependancy system.&lt;/p&gt;


	&lt;h3&gt;Addition of the hook_depends()&lt;/h3&gt;


	&lt;p&gt;Sure, it sounds like reeling in a pair of adult diapers instead of trout.  The &lt;span class="caps"&gt;API&lt;/span&gt;
needs more humor anyway.&lt;/p&gt;


Ex:
&lt;pre class='ruby'&gt;
&lt;span class='ident'&gt;function&lt;/span&gt; &lt;span class='ident'&gt;mymodule_depends&lt;/span&gt;&lt;span class='punct'&gt;()&lt;/span&gt; &lt;span class='punct'&gt;{&lt;/span&gt;
  &lt;span class='keyword'&gt;return&lt;/span&gt; &lt;span class='ident'&gt;array&lt;/span&gt;&lt;span class='punct'&gt;(&lt;/span&gt;
    &lt;span class='punct'&gt;'&lt;/span&gt;&lt;span class='string'&gt;hook_nodeapi&lt;/span&gt;&lt;span class='punct'&gt;'&lt;/span&gt; &lt;span class='punct'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ident'&gt;array&lt;/span&gt;&lt;span class='punct'&gt;(&lt;/span&gt;
      &lt;span class='punct'&gt;'&lt;/span&gt;&lt;span class='string'&gt;before&lt;/span&gt;&lt;span class='punct'&gt;'&lt;/span&gt; &lt;span class='punct'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ident'&gt;array&lt;/span&gt;&lt;span class='punct'&gt;(&lt;/span&gt;
        &lt;span class='punct'&gt;'&lt;/span&gt;&lt;span class='string'&gt;taxonomy_nodeapi&lt;/span&gt;&lt;span class='punct'&gt;',&lt;/span&gt;
        &lt;span class='punct'&gt;'&lt;/span&gt;&lt;span class='string'&gt;audio_nodeapi&lt;/span&gt;&lt;span class='punct'&gt;'&lt;/span&gt;
      &lt;span class='punct'&gt;),&lt;/span&gt;
      &lt;span class='punct'&gt;'&lt;/span&gt;&lt;span class='string'&gt;after&lt;/span&gt;&lt;span class='punct'&gt;'&lt;/span&gt; &lt;span class='punct'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ident'&gt;array&lt;/span&gt;&lt;span class='punct'&gt;(&lt;/span&gt;
        &lt;span class='punct'&gt;'&lt;/span&gt;&lt;span class='string'&gt;image_nodeapi&lt;/span&gt;&lt;span class='punct'&gt;'&lt;/span&gt;
      &lt;span class='punct'&gt;),&lt;/span&gt;
    &lt;span class='punct'&gt;),&lt;/span&gt;
    &lt;span class='punct'&gt;'&lt;/span&gt;&lt;span class='string'&gt;hook_form_alter&lt;/span&gt;&lt;span class='punct'&gt;'&lt;/span&gt; &lt;span class='punct'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ident'&gt;array&lt;/span&gt;&lt;span class='punct'&gt;(&lt;/span&gt;
      &lt;span class='punct'&gt;'&lt;/span&gt;&lt;span class='string'&gt;before&lt;/span&gt;&lt;span class='punct'&gt;'&lt;/span&gt; &lt;span class='punct'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ident'&gt;array&lt;/span&gt;&lt;span class='punct'&gt;(&lt;/span&gt;
        &lt;span class='punct'&gt;'&lt;/span&gt;&lt;span class='string'&gt;taxonomy_form_alter&lt;/span&gt;&lt;span class='punct'&gt;'&lt;/span&gt;
      &lt;span class='punct'&gt;),&lt;/span&gt;
    &lt;span class='punct'&gt;),&lt;/span&gt;
  &lt;span class='punct'&gt;);&lt;/span&gt;
&lt;span class='punct'&gt;}&lt;/span&gt;
&lt;/pre&gt;

	&lt;p&gt;The hook_depends is implemented by any module that cares about what order it&amp;#8217;s
hook(s) get called in.  It should only be used when there is an issue with the
standard hook ordering (more on that later).  The idea should be quite
straightforward from the example: the &amp;#8220;mymodule&amp;#8221; module needs its hook_nodeapi()
run before a few other modules and after one, it also needs its hook_form_alter()
run before one module.&lt;/p&gt;


	&lt;h3&gt;How the core orders the hooks based on hook_depends()&lt;/h3&gt;


	&lt;p&gt;When a new Drupal module is installed the core invokes all instances of
hook_depends().  These should, in a perfect world, only exist in contrib modules
because the core should take care of it&amp;#8217;s own issues in a cleaner manner.&lt;/p&gt;


	&lt;p&gt;So, once a list of modules and their requested dependancies has been gathered
the system can pour over them to figure out which order each hook should be run.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m sure someone else has a better algorithm than me, but here&amp;#8217;s a shot.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Find all implementations of the hook in question (from all modules, including ones that implement hook_depends().&lt;/li&gt;
		&lt;li&gt;Split the list of hooks into two groups: (1) Hooks that don&amp;#8217;t care when they are run, (2) hooks that care when they are run.&lt;/li&gt;
		&lt;li&gt;Keep making consecutive passes over the hooks in group (2) trying to fit them into group (1) as they desire to be placed.&lt;/li&gt;
		&lt;li&gt;If a cyclic relationship occurs then throw a nasty error (more on this later).&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Once the ordered lists have been made for each hook cache the list to the database.
I&amp;#8217;m unsure if this should be done using cache_set or by keeping track of it in a
seperate table entirely.  Either way the result is the same.&lt;/p&gt;


	&lt;h3&gt;Modifications to module_implements&lt;/h3&gt;


	&lt;p&gt;Since Drupal is quite good at keeping it&amp;#8217;s core code squeaky clean, adding hook
ordering is a simple matter.  Just modify module_implements() to grab the cached list
of ordered hooks and everything should cascade from there.&lt;/p&gt;


	&lt;h3&gt;What to do if there is a collision or cycle?&lt;/h3&gt;


	&lt;p&gt;Nothing.  Well throw an error, I guess.  The real point is that while cyclic
dependancies are easy to create it&amp;#8217;s up to contrib module developers to avoid them. As
long as the hook_depends() is used sparingly and only when there is a bonified reason
cyclic dependancies shouldn&amp;#8217;t happen.&lt;/p&gt;


	&lt;p&gt;Reasons to use hook_depends(), aka common reasons hook ordering is needed:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Some module up the food-chain from my module is messing up my data, and I want it to stop.&lt;/li&gt;
		&lt;li&gt;I want to mess with the data being supplied to some module down the food-chain.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h3&gt;Why not have &amp;#8216;after all&amp;#8217; or &amp;#8216;before all&amp;#8217; ordering classes?&lt;/h3&gt;


	&lt;p&gt;Because somebody has to go first, and two hooks can&amp;#8217;t both be first.  It&amp;#8217;s better to
encourage developers to place their hooks directly before the module they intend to
superceed.  Also, wasn&amp;#8217;t this what hook_init() an hook_exit() were created for?&lt;/p&gt;


	&lt;p&gt;All thoughts and feedback are welcome!&lt;/p&gt;


James.
&lt;/div&gt;
  &lt;!-- end post body --&gt;

  &lt;div class="links"&gt;
    
      &lt;span&gt;&lt;a href="/comment/new/4"&gt;new comment&lt;/a&gt;&lt;/span&gt;
    
  &lt;/div&gt;

  
&lt;/div&gt;    </content>
  <feedburner:origLink>http://jamesandres.com/post/show/Hook-Ordering-In-Drupal-4</feedburner:origLink></entry>
  <entry>
    <title>Welcome!</title>
    <link href="http://feedproxy.google.com/~r/JamesAndressTipsHow-tos/~3/22mI8ZFqSNU/Welcome%21-3" rel="alternate" />
    <id>http://jamesandres.com/post/show/3</id>
    <updated>2008-01-25T06:35:48Z</updated>
    <author>
      <name>James Andres</name>
    </author>
    <summary>Post summary</summary>
    <content type="html">
&lt;div class="post"&gt;
  

  &lt;h1&gt;Welcome!&lt;/h1&gt;

  &lt;div class="post-header"&gt;Friday, January 25, 2008&lt;/div&gt;
  &lt;!-- begin post body --&gt;
  &lt;div&gt;Hello Web-travlers and welcome to my new site.  I&amp;#8217;ll have some fresh content shortly, once I sand smooth all the rough edges on the site.

	&lt;p&gt;Until then, I&amp;#8217;ve posted a few of the better posts from my blog on projectopus.com.&lt;/p&gt;


	&lt;p&gt;While you wait, why not check out the site in &lt;pre class='ruby'&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;span class='regex'&gt;[e]?l(i|y)nks&lt;/span&gt;&lt;span class='punct'&gt;/&lt;/span&gt;&lt;/pre&gt;?&lt;/p&gt;


	&lt;p&gt;&lt;a href="/images/jamesandres.com-in-elinks.png"&gt;&lt;img src="/images/jamesandres.com-in-elinks-150.png" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;James.&lt;/div&gt;&lt;/p&gt;
  &lt;!-- end post body --&gt;

  &lt;div class="links"&gt;
    
      &lt;span&gt;&lt;a href="/comment/new/3"&gt;new comment&lt;/a&gt;&lt;/span&gt;
    
  &lt;/div&gt;

  
&lt;/div&gt;    </content>
  <feedburner:origLink>http://jamesandres.com/post/show/Welcome%21-3</feedburner:origLink></entry>
  <entry>
    <title>Lesson learned: Apache2 MaxClients Variable</title>
    <link href="http://feedproxy.google.com/~r/JamesAndressTipsHow-tos/~3/Q6jt8M3I9Js/Lesson-Learned--Apache2-Max-Clients-Variable-2" rel="alternate" />
    <id>http://jamesandres.com/post/show/2</id>
    <updated>2008-01-19T18:42:50Z</updated>
    <author>
      <name>James Andres</name>
    </author>
    <summary>Post summary</summary>
    <content type="html">
&lt;div class="post"&gt;
  

  &lt;h1&gt;Lesson learned: Apache2 MaxClients Variable&lt;/h1&gt;

  &lt;div class="post-header"&gt;Thursday, November 30, 2006&lt;/div&gt;
  &lt;!-- begin post body --&gt;
  &lt;div&gt;&lt;strong&gt;This is an old post originally taken from my blog on &lt;a href="http://www.projectopus.com/node/10463"&gt;Project Opus&lt;/a&gt;&lt;/strong&gt;

	&lt;p&gt;Yea, I finally got around to reading about what the &lt;i&gt;MaxClients&lt;/i&gt; variable in the apache2.conf is for.  Please keep your laughter to yourself, but i thought what MaxClients meant was &amp;#8220;how many clients can connect at one time.&amp;#8221;  So logically, I set it at 255.  Well, I&amp;#8217;m not sure if MaxClients is a cryptic name, or maybe I just missed the boat, but actually this variable controls how many server processes will run simultaneously!&lt;/p&gt;


	&lt;p&gt;Visually stated: MaxClients == MaximumNumberOfApacheInstancesRunningAtTheSameTime&lt;/p&gt;


	&lt;p&gt;So what?  Well, when load got high, apache would start spawing &amp;#8220;hefty&amp;#8221; Drupal processes @ between 20MB and 80MB each.&lt;/p&gt;


	&lt;p&gt;Simple math: 255&amp;#215;60MB = 15,300 &lt;span class="caps"&gt;MB RAM&lt;/span&gt; usage &lt;strong&gt;(hint: we don&amp;#8217;t have 15 GB of &lt;span class="caps"&gt;RAM&lt;/span&gt;)&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;As you can see this is a bad situation.&lt;/p&gt;


	&lt;p&gt;I changed the nubmer to 40 this morning and systems haven&amp;#8217;t been happier :-)&lt;/p&gt;


	&lt;p&gt;Lessons learned &amp;#8230; lessons learned&lt;/p&gt;


	&lt;p&gt;James.&lt;/div&gt;&lt;/p&gt;
  &lt;!-- end post body --&gt;

  &lt;div class="links"&gt;
    
      &lt;span&gt;&lt;a href="/comment/new/2"&gt;new comment&lt;/a&gt;&lt;/span&gt;
    
  &lt;/div&gt;

  
&lt;/div&gt;    </content>
  <feedburner:origLink>http://jamesandres.com/post/show/Lesson-Learned--Apache2-Max-Clients-Variable-2</feedburner:origLink></entry>
  <entry>
    <title>PHP opcode caching and SMP (multiple processors)</title>
    <link href="http://feedproxy.google.com/~r/JamesAndressTipsHow-tos/~3/1eo2BKgS5nQ/Php-Opcode-Caching-And-Smp--Multiple-Processors--1" rel="alternate" />
    <id>http://jamesandres.com/post/show/1</id>
    <updated>2008-01-19T18:43:48Z</updated>
    <author>
      <name>James Andres</name>
    </author>
    <summary>Post summary</summary>
    <content type="html">
&lt;div class="post"&gt;
  

  &lt;h1&gt;PHP opcode caching and SMP (multiple processors)&lt;/h1&gt;

  &lt;div class="post-header"&gt;Thursday, November 23, 2006&lt;/div&gt;
  &lt;!-- begin post body --&gt;
  &lt;div&gt;&lt;strong&gt;This is an old post originally taken from my blog on &lt;a href="http://www.projectopus.com/node/10250"&gt;Project Opus&lt;/a&gt;&lt;/strong&gt;

	&lt;p&gt;Hello all,&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Off-Topic Note&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;ve decided to start blogging on a bit more of a regular basis.  I&amp;#8217;m not much of a blogger, but who knows &amp;#8230; it might just stick this time.  I have a hunch problem was subject matter.  So from now on I plan to stick to what I know best.  Geek stuff!&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Main Feature&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;Just learned an interesting thing about &lt;span class="caps"&gt;APC&lt;/span&gt; (the popular &lt;span class="caps"&gt;PHP&lt;/span&gt; opcode cache) today: &lt;span class="caps"&gt;APC&lt;/span&gt; &lt;i&gt;hates&lt;/i&gt; SMP.  I&amp;#8217;ve been trying for nearly a month to get &lt;span class="caps"&gt;APC&lt;/span&gt; to run stably on our multi-CPU system.  Invariably the extension will start seg. faulting within a few minutes or hours of starting up.&lt;/p&gt;


	&lt;p&gt;After many headaches, I gave up on &lt;span class="caps"&gt;APC&lt;/span&gt;.  Running &lt;span class="caps"&gt;PHP&lt;/span&gt; without an opcode cache is a fairly crazy thing to do, so for the last month I&amp;#8217;ve been looking high and low for a replacement.  Recently I just stumbled across &lt;a href="http://trac.lighttpd.net/xcache/"&gt;XCache&lt;/a&gt; and immediately loved what I saw.  XCache is very similar to &lt;span class="caps"&gt;APC&lt;/span&gt;, the installation was nearly identical, but it has a few added options (I haven&amp;#8217;t explored them all yet).&lt;/p&gt;


	&lt;p&gt;Best of all, it works great with &lt;span class="caps"&gt;SMP&lt;/span&gt;!!!&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&lt;a href="http://trac.lighttpd.net/xcache/wiki/Introduction"&gt;XCache Introcution Page&lt;/a&gt; ... before then I had used &lt;span class="caps"&gt;APC&lt;/span&gt;. Although it was quite stable for a php4 with flock() configuration it had become unstable once I upgraded my server to a dual cpu (4 threaded cpu) because it flock()ed badly so XCache was used instead and seems to have solved the problem.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;I couldn&amp;#8217;t have said it better my self.&lt;/p&gt;


	&lt;p&gt;James.&lt;/div&gt;&lt;/p&gt;
  &lt;!-- end post body --&gt;

  &lt;div class="links"&gt;
    
      &lt;span&gt;&lt;a href="/comment/new/1"&gt;new comment&lt;/a&gt;&lt;/span&gt;
    
  &lt;/div&gt;

  
&lt;/div&gt;    </content>
  <feedburner:origLink>http://jamesandres.com/post/show/Php-Opcode-Caching-And-Smp--Multiple-Processors--1</feedburner:origLink></entry>
</feed>
