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

<channel>
	<title>Everything In Between &#187; HOWTO</title>
	<atom:link href="http://maymay.net/blog/category/howto/feed/" rel="self" type="application/rss+xml" />
	<link>http://maymay.net/blog</link>
	<description>The brutally honest, first-person account of Meitar Moscovitz&#039;s life.</description>
	<lastBuildDate>Thu, 19 Jan 2012 08:54:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>HowTo: Use Rules to Automatically Manage Email in Apple Mail</title>
		<link>http://maymay.net/blog/2009/07/27/howto-use-rules-to-automatically-manage-email-in-apple-mail/</link>
		<comments>http://maymay.net/blog/2009/07/27/howto-use-rules-to-automatically-manage-email-in-apple-mail/#comments</comments>
		<pubDate>Mon, 27 Jul 2009 21:07:47 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[Crosspost]]></category>
		<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Information & Communication]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Email]]></category>
		<category><![CDATA[LinkedIn]]></category>
		<category><![CDATA[Mail.app]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=935</guid>
		<description><![CDATA[After recently moving to San Francisco, I joined the San Francisco Freecyclers&#8217; Network. Freecycle is a really cool set of local groups who prefer to give away items to people who want them instead of throwing them away into the trash. The group uses email to connect people who offer items and those who want [...]]]></description>
			<content:encoded><![CDATA[<p>After recently moving to San Francisco, I joined the <a href="http://www.freecycle.org/group/US/California/San%20Francisco">San Francisco Freecyclers&#8217; Network</a>. Freecycle is a really cool set of local groups who prefer to give away items to people who want them instead of throwing them away into the trash. The group uses email to connect people who offer items and those who want them. In order to stay sane, a simple, <a href="http://www.freecycle.org/faq/faq/faq_guidelines" title="Read more about Freecycle guidelines.">conventional format for writing an email&#8217;s subject line</a> lets you quickly figure out what&#8217;s on offer and where.</p>
<p>Thanks to this simple text convention in subject lines, I could trivially automate the process of sorting through the approximately 100 emails a day that the email list generates in order to single out only the emails that interest me. Here&#8217;s how I did it.</p>
<h2>Define Your Goals</h2>
<p>Before setting out on any task, it behooves you to take a moment and think about what it is you&#8217;re trying to accomplish. For me, with the San Francisco Freecycling Network (SFFN) email list, I wanted to achieve the following goals:</p>
<ul>
<li>Keep my inbox clear of email from the SFFN list unless a message was particularly interesting.</li>
<li>Browse the SFFN messages when I wanted to look at them without having to go to the web site.</li>
<li>Highlight particularly interesting messages in my inbox visually and play a special sound to alert me that such email has been found in case Mail was running in the background (since free stuff gets taken fast!).</li>
</ul>
<p>I defined &#8220;particularly interesting&#8221; messages as ones that offered items of need for my recent move. With this in mind, I set out to create email rules that accomplished each goal in turn.</p>
<h2>Step 1: Create a mailbox to store the appropriate messages</h2>
<p>I began by creating a new mailbox to store all the SFFN messages I was getting. This alternate mailbox would be the mailbox I would shunt all SFFN email to so as to keep my inbox clear of it. I called the mailbox simply &#8220;SFFN&#8221;.</p>
<p><strong>Do this:</strong></p>
<ol>
<li>From the <em>Mailbox</em> menu, select <em>New Mailbox…</em>. The New Mailbox sheet appears.</li>
<li>Select any location (&#8220;On My Mac&#8221; is fine, as is the account that receives the mailing list messages), and give it a name.</li>
<li>Click OK.</li>
</ol>
<h2>Step 2: Create an email rule to move all appropriate messages to the new mailbox</h2>
<p>With the new mailbox created, I now needed to get all the appropriate messages in there and out of my inbox.</p>
<p>Apple Mail&#8217;s email rules work by looking at each incoming message and matching it against a set of conditions that you provide. If the message being evaluated matches the conditions you specify, such as &#8220;from the San Francisco Freecycler&#8217;s Network mailing list&#8221;, then an associated action is automatically performed. Every email you get is evaluated against every rule you have unless a rule moves the message to another mailbox or until you trigger the &#8220;stop evaluating rules&#8221; action.</p>
<p>Since moving an email message to a new mailbox ends the process of evaluating rules and moving messages to the SFFN mailbox I just created is the goal of the rule I&#8217;m creating, I decided to name the rule &#8220;END &#8211; SFFN&#8221;.</p>
<p><strong>Do this:</strong></p>
<ol>
<li>From the Mail menu, select <em>Preferences…</em>. The Mail Preferences window opens.</li>
<li>Click the <em>Rules</em> button. The Rules pane appears.</li>
<li>Click the <em>Add Rule</em> button. The Add Rule sheet appears:
<ol>
<li>Enter a meaningful description (I chose &#8220;END &#8211; SFFN&#8221;) in the <em>Description:</em> field.</li>
<li>Provide the conditions you want to match. Since all SFFN emails must be addressed to the mailing list, I simply provided the email address of the mailing list (<kbd>sffn@yahoogroups.com</kbd>) as the condition for the <em>To</em> header.</li>
<li>Provide the actions you want Mail to perform. I simply wanted to move the matched messages to the SFFN mailbox.</li>
</ol>
<li>Click OK.</li>
</ol>
<p>For me, the above configuration looked like this:</p>
<p><a href="http://maymay.net/blog/wp-content/uploads/2009/07/end-sffn-mail-rule.gif"><img src="http://maymay.net/blog/wp-content/uploads/2009/07/end-sffn-mail-rule.gif" alt="end-sffn-mail-rule" title="end-sffn-mail-rule" class="alignnone wp-image-936" /></a></p>
<h2>Step 3: Create an email rule to highlight a message of particular interest</h2>
<p>At this point, any and all email I receive from the San Francisco Freecyclers&#8217; Network is being moved to the SFFN mailbox I created for it. This is nice because it keeps my inbox clear, but it&#8217;s still not very helpful since I still have to go trudging through the SFFN mailbox in order to find anything that might be interesting to me. The whole point of this exercise is to reduce the amount of time I spend actively looking for interesting things and let my computer do that work for me. So the next step is to tell Mail what I&#8217;m looking for so it can show the interesting messages to me.</p>
<p>Now, as it happens I&#8217;m in need of a wireless router. Since &#8220;router&#8221; is an appropriately unique word, I&#8217;m going to tell Mail to look for that word in a subject line. However, since I only want Mail to tell me when a router is available and not when other people like me are looking for routers, I&#8217;ll also tell Mail to look for the keyword &#8220;OFFER&#8221; in the subject line. (And this is why the <a href="http://www.freecycle.org/faq/faq/faq_guidelines">Freecycle guidelines</a> tell users to format their subject lines in a conventional way.)</p>
<p>Finally, since I don&#8217;t want to have to go digging for the interesting email message and since my inbox is already going to be kept clear by the previous rule, I&#8217;ll simply have Mail highlight the message in a bright green color and leave the message in my inbox <em>without</em> moving it to the SFFN mailbox I created earlier.</p>
<p><strong>Do this:</strong></p>
<ol>
<li>From the Rules pane in Mail&#8217;s preferences, click <em>Add Rule</em>.</li>
<li>Enter a meaningful description in the <em>Description:</em> field. (Since I&#8217;m looking for a router, I called it &#8220;SFFN &#8211; Search for OFFERed &#8216;router&#8217;&#8221;.)</li>
<li>Provide the conditions you wish to match. For me, this meant email sent to the Freecycler&#8217;s mailing list with the two words &#8220;OFFER&#8221; and &#8220;router&#8221; in the subject line.</li>
<li>Specify the actions you wish Mail to perform. I wanted Mail simply to color the message green and to leave the email go to the inbox (where it was originally destined for), so I chose &#8220;Stop evaluating rules&#8221;. (I also decided I&#8217;d want Mail to play a special sound to alert me that it had found something interesting. This is optional, of course.)</li>
<li>Click OK.</li>
</ol>
<p>When I was done creating my rule, the above configuration looked like this:</p>
<p><a href="http://maymay.net/blog/wp-content/uploads/2009/07/highlight-router-sffn-mail-rule.gif"><img src="http://maymay.net/blog/wp-content/uploads/2009/07/highlight-router-sffn-mail-rule.gif" alt="Screenshot of Mail.app rule to highlight incoming Freecycling emails offering a router." title="highlight-router-sffn-mail-rule" width="556" height="330" class="alignnone size-full wp-image-945" /></a></p>
<p>I can now repeat this step as many times as desired to tell Mail to highlight other messages that may be of particular interest for some other reason. For instance, say instead of looking for a wireless router, I wanted to look for a toaster. I would simply need to click on &#8220;Duplicate Rule&#8221; and replace all instances of &#8220;router&#8221; with &#8220;toaster&#8221;.</p>
<h2>Step 4: Place email rules in appropriate order</h2>
<p>Since Mail will repeatedly check incoming email against all the active rules, we need to be sure to place the rules in the correct order. You can think of each email rule as part of large Rube Goldberg machine, each message getting funneled through some piece of the logic at each successive rule. That&#8217;s why I began the name of the first rule I created with &#8220;END,&#8221; so that I&#8217;d know it should be placed <em>after</em> the rest of the SFFN-related email rules.</p>
<p>I decided that I wanted Mail to look for anything related to cameras and, of course, to toasters. This gave me a total of 4 rules (three to search for items of interest, and one to keep my inbox clear). Since the three highlighting rules all perform the same action, it doesn&#8217;t really matter which order they go in, but it is important that all of them appear before the rule to move messages to the SFFN mailbox.</p>
<p>To order rules, simply click-and-drag them into the order you wish Mail to evaluate them in. When I was done, my Rules pane looked like this:</p>
<p><a href="http://maymay.net/blog/wp-content/uploads/2009/07/mailapp-rules-pane.gif"><img src="http://maymay.net/blog/wp-content/uploads/2009/07/mailapp-rules-pane.gif" alt="Screenshot of the Mail.app Rules pane with sorted rules." title="mailapp-rules-pane" width="550" height="309" class="alignnone size-full wp-image-946" /></a></p>
<h2>Conclusion</h2>
<p>Mail rules are an extremely powerful feature that most email clients have, but that too few people use. They can save you enormous amounts of time and increase your productivity by automating simple yet time-consuming tasks.</p>
<p>The conventional, standardized subject lines that the Freecycle mailing list uses simplifies the logic required to have your computer automatically process your messages for you. This is a useful observation because it can be applied to other areas of your life where using simple conventions can help to organize otherwise overwhelming information tasks into manageable batches. Although this particular example uses stock, simple commands, you can get as fancy as you like by having an action trigger an <a href="/blog/category/applescript/">AppleScript</a>.</p>
<p>Now, hopefully, finding some additional housewares and a wireless router for my new San Francisco apartment will be as easy as checking (but not manually sorting!) my own email!</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2009/07/27/howto-use-rules-to-automatically-manage-email-in-apple-mail/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>How To Use Git-SVN as the Only Subversion Client You&#8217;ll Need</title>
		<link>http://maymay.net/blog/2009/02/24/how-to-use-git-svn-as-the-only-subversion-client-youll-need/</link>
		<comments>http://maymay.net/blog/2009/02/24/how-to-use-git-svn-as-the-only-subversion-client-youll-need/#comments</comments>
		<pubDate>Tue, 24 Feb 2009 18:17:37 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[Subversion]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=891</guid>
		<description><![CDATA[I&#8217;ve been using git as my favorite version control tool for quite a while now. One of its numerous distinguishing features is an optional component called git-svn, which serves as a bi-directional &#8220;bridge&#8221; that enables native git repositories to interact with a Subversion repository, performing all the normal operations you would need to use svn [...]]]></description>
			<content:encoded><![CDATA[<p><a href="/blog/tag/git/">I&#8217;ve been using git</a> as my favorite version control tool for quite a while now. One of its  numerous distinguishing features is an optional component called git-svn, which serves as a bi-directional &#8220;bridge&#8221; that enables native git repositories to interact with a Subversion repository, performing all the normal operations you would need to use <code>svn</code> for. In other words, since you can checkout, commit to, and query the logs of Subversion repositories (among other things) using git-svn, <strong>git can serve as your all-in-one Subversion client</strong>.</p>
<p>One reason why you might use git-svn because your project <em>actually</em> resides in a Subversion repository and other people need to access it using Subversion-only tools. Another might be because you have multiple projects, some that use git and others that use Subversion, and you&#8217;re tired of switching between <code>svn</code> and <code>git</code> commands—like me. For us, it&#8217;s far easier to simply use git as a Subversion client and never have to call <code>svn</code> directly.</p>
<p>As an important aside, please note that I would strongly discourage people who are new to git from learning about it by using git-svn. Although you may think that moving to git from Subversion would be eased by using the git-svn bridge, I really don&#8217;t think that&#8217;s the case. You&#8217;re much, much better off simply using git by itself right off the bat, and you can <a href="/blog/2008/03/26/howto-use-git-for-personal-development-when-everyone-else-is-using-subversion-part-1/">do this even if your fellow committers are using subversion</a>.</p>
<p>Also, I&#8217;m going to assume you&#8217;ve already got a Subversion repository set up somewhere.</p>
<p>First, checkout the subversion repository. In Subversion you would do this:</p>
<pre><code class="shell">svn checkout <var>http://example.com/path/to/svn/repo</var></code></pre>
<p>With git-svn, you do this:</p>
<pre><code class="shell">git svn clone <var>http://example.com/path/to/svn/repo</var></code></pre>
<p>This will cause git-svn to create a new directory called <code>repo</code>, switch to it, initialize a new git repository, configure the Subversion repository at <var>http://example.com/path/to/svn/repo</var> as a remote git branch (confusingly called <code>git-svn</code> by default, although you can specify your name by passing a <code>-R<var>remote_name</var></code> or <code>--svn-remote=<var>remote_name</var></code> option), and then does a checkout.</p>
<p>The output of this command will be a little awkward. Here&#8217;s a sample from one my repositories:</p>
<pre><samp>r14 = dbd7266f328ef2ad061ea4532f39ce7cebaba0c5 (git-svn)
	M	trunk/Chapter 6/Chapter 6.doc
	M	trunk/Chapter 6/code examples/6.1.html
	A	trunk/Chapter 6/code examples/6.2.html
r15 = 4cca08341ab0600069cece77ce67afc449caca68 (git-svn)
	M	trunk/Chapter 6/Chapter 6.doc
	A	trunk/Chapter 6/code examples/print.css
	A	trunk/Chapter 6/code examples/screen.css
	M	trunk/Chapter 6/code examples/6.1.html
	M	trunk/Chapter 6/code examples/6.2.html
r16 = 7b2f3e0ccfd79be61b527b6ba325f8689475dc01 (git-svn)
	M	trunk/Chapter 5/Chapter 5.doc
r17 = a319764855361d92bb6e006cfd18a51319046cae (git-svn)
	M	trunk/Chapter 5/Chapter 5.doc
r18 = 4cd5cb43d33b2dd45bd39b9a2b7ea9416f9e3d8f (git-svn)
	M	trunk/Chapter 6/Chapter 6.doc
	M	trunk/Chapter 6/code examples/screen.css
	M	trunk/Chapter 6/code examples/6.1.html
</samp></pre>
<p>As you can see, git-svn is associating specific Subversion revisions with particular git commit objects. Due to this required mapping, the initial cloning process of a Subversion repository may take some time. This is a good opportunity for your morning coffee break.</p>
<p>When this process is done, you&#8217;ll have a typical git repository with a local master branch and one remote branch for the Subversion repository:</p>
<pre><code class="shell">Perseus:repo maymay$ git branch
* master
Perseus:repo maymay$ git branch -r
  git-svn
</code></pre>
<p>You can now treat the Subversion repository as though it were a remote branch of sorts. Say you&#8217;ve done a bunch of work and, as you typically do with git, you commit this work to your topic branch.</p>
<pre><code class="shell">Perseus:repo maymay$ git checkout -b awesome-feature
<samp>Switched to a new branch "awesome-feature"</samp>
Perseus:repo maymay$ vim awesome-feature-stylesheet.css
Perseus:repo maymay$ git add awesome-feature-stylesheet.css
Perseus:repo maymay$ git commit -m "Now I'm perty."
<samp>Created commit 07ee832: Now I'm perty.
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 awesome-feature-stylesheet.css</samp>
</code></pre>
<p>Right now your changes are still in the topic branch (called <code>awesome-feature</code> in the above example). To get them to Subversion, you merely need to say <code>git svn dcommit</code>:</p>
<pre><code class="shell">Perseus:repo maymay$ git svn dcommit
<samp>Committing to <var>http://example.com/path/to/svn/repo</var> ...</samp>
</code></pre>
<p>Note that pesky extra &#8220;d&#8221; in the command. This is the equivalent of Subversion&#8217;s <code>svn commit</code>, but the commit message used is the one from the previous command, which in this case was <code>git commit -m "Now I'm perty."</code>. Also interesting to note here is that because Subversion doesn&#8217;t understand git branches, any change on any branch can be &#8220;pushed&#8221; to Subversion at any time using <code>git svn dcommit</code>—the git commits don&#8217;t have to be on any specific branch, since all git-svn does is map a git commit object to a Subversion revision and vice versa.</p>
<p>Similarly, you can at any time run the equivalent of <code>svn update</code> to get the latest changes from the Subversion repository into your Subversion branch.</p>
<ul>
<li>To do this, <em>without</em> affecting your working tree—that is, to only fetch the latest changes but not write them to the filesystem, just to the git-svn metadata area and the remote git branch—use <code>git svn fetch</code>. To apply these changes to your local branch, you simply merge: <code>git checkout master; git merge git-svn</code>.</li>
<li>If you do want to write out the changes to the filesystem (as <code>svn update</code> would do), use <code>git svn rebase</code>, which automatically linearizes your local git commit history after the commit history of the incoming Subversion changesets. Very slick.</li>
</ul>
<p>If your fetching/rebasing causes a conflict, you&#8217;ll be notified and will have to resolve it as per usual. If your &#8220;pushes&#8221; to the svn repo causes a Subversion conflict, you&#8217;ll be notified and you should again edit the appropriate files to resolve it, but this time make sure you run a <code>git svn rebase</code> before you try <code>dcommit</code>-ing again (since, remember, Subversion can only handle linear commit history).</p>
<p>As always, saying <code>man git-svn</code> or <code>git help svn</code> to your shell will give you all the other details. Among these, the most likely you&#8217;ll probably want to learn about is <a href="http://www.jukie.net/~bart/blog/svn-branches-in-git">how to track multiple Subversion branches as normal git branches</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2009/02/24/how-to-use-git-svn-as-the-only-subversion-client-youll-need/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>How To Start Contributing To Open Source Projects</title>
		<link>http://maymay.net/blog/2009/02/11/how-to-start-contributing-to-open-source-projects/</link>
		<comments>http://maymay.net/blog/2009/02/11/how-to-start-contributing-to-open-source-projects/#comments</comments>
		<pubDate>Wed, 11 Feb 2009 08:06:20 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[HOWTO]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=880</guid>
		<description><![CDATA[If you&#8217;re anything like me, then you&#8217;ve been using open source projects for years. You love them, you know them, and you want to help them. But you aren&#8217;t the fastest programmer, or the smartest, and you&#8217;ve finally gotten to a point in your life where you&#8217;re okay that someone, somewhere, is going to be [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re anything like me, then you&#8217;ve been using open source projects for years. You love them, you know them, and you want to help them. But you aren&#8217;t the fastest programmer, or the smartest, and you&#8217;ve finally gotten to a point in your life where you&#8217;re okay that someone, somewhere, is going to be better than you at everything you do.</p>
<p>To this I say <em>congratulations</em>, because now—at last—you&#8217;re ready to start contributing to open source projects. To help you out, here are a few of the things that I&#8217;ve noticed that have been immensely helpful for me as I&#8217;ve started to make the transition from power user to contributor.</p>
<h2>Start with the bugs</h2>
<p>Contributors to open source projects are like Tom Hanks in the movie Cast Away. No matter how much help you get from the mailing list or the chat room, you&#8217;re still ultimately going to have to figure stuff out for yourself. This is a challenge, to be sure, but the good news is that you don&#8217;t have to work it <em>all</em> out on your own—it is an open source and collaborative project, after all, right?</p>
<p>So, very often, the best ways to start contributing is by sending bug fixes in as patches, the smaller the better. I think my first bug fix to an open source project was like 3 lines, and all my first contributions to subsequent projects have been that size or smaller. Surf to the issue tracker and cruise over to all the bugs in your down time, read them and work through the process of reproduce, fix, and test. Lather, rinse, and repeat until you have a patch to contribute.</p>
<p>Atomicity helps here, which is to say you should be certain to contribute <em>one patch per bug fix</em>. (Don&#8217;t send a single patch that fixes 10 unrelated bugs. That can be extremely difficult for a project maintainer to review.) Sure, bug fixing isn&#8217;t a glamorous contribution, but you&#8217;d be <em>amazed</em> how appreciated it is. Seriously, nobody likes bugs, so you can easily become an unsung hero for one of the core developers if all you do is ruthlessly cull the bug list.</p>
<h2>Speak with results, not with possibilities</h2>
<p>There are lots of times when it pays to discuss things on a mailing list before you go and lay down code for them. However, if you&#8217;re just getting started contributing to a project and your changes are relatively small and simple, you&#8217;re much better off just implementing them and sending in a patch. Once you have code to explain what you mean to do, <em>then</em> discussing it with the project at large can get you places.</p>
<p>There are a few reasons for this, but the primary one that&#8217;s impacted me is <em>easier communication</em>: many people use the same words to mean different things, and this makes communication about code in a human language (typically over a mailing list with hundreds of people living in countries all over the world) <em>really hard</em>. In comparison, (most) computers will treat your code in the same exact way. This means it&#8217;s much easier to talk to the community using the project&#8217;s own code than it is likely to be for you to get all the terminology correct in a mailing list message or a chat room.</p>
<h2>Do things their way, not your way</h2>
<p>This should be obvious, but I often see other people making this mistake so I&#8217;ll mention it anyway. When you contribute to a project, you really, <em>really</em>, <strong>really</strong> should pay attention not just to what the project is doing, but also how they&#8217;re doing it. This does actually require a bit more observation on your part than you might think at first, but it&#8217;s still not that hard.</p>
<p>If the open source project were a planet, then when you start contributing, you&#8217;re still an insect in its world. (That&#8217;s why you&#8217;re starting with the bugs, remember?) Quite simply, match the coding style of the project. Figure out what the preferred way to report bugs and to send patches are. For goodness sake, <em>RTFM</em> (no, really, read it—twice if you have to).</p>
<p>In many cases the project&#8217;s developers will have already spent hours trying to make all of this information available to you somehow, so it can be really demoralizing for them (and ultimately for you, too) if you don&#8217;t take advantage of it. Now admittedly, many projects don&#8217;t do this <em>very well</em>, but they have tried. In fact, if you think you can make the information more easily available, perhaps by fixing the grammar, correcting typos, reorganizing a wiki page, or whatever, then <em>contribute</em>!</p>
<h2>Leave your ego on your side of the screen</h2>
<p>Y&#8217;know office politics? Well, sometimes, open source politics can make office politics look like child&#8217;s play. It&#8217;s kind of a tragedy, actually, but it&#8217;s true. And <a href="http://www.youtube.com/watch?v=ZSFDm3UYkeE" title="Watch and learn how open source projects can protect themselves from poisonous people.">all the poison stems from people&#8217;s egos</a>. The maintainers of all the best-run projects remove negative emotion and ego from their mailing list messages, and are quick to defuse ego-filled situations.</p>
<p>As a contributor, this means you should do your best to do the same. Do not—<em>do not</em>—lobby for the inclusion of a particular piece of code, bug fix, feature, extensions, plugin, whatever, just because <em>you</em> wrote it. Seriously. Do not do this. In open source projects, your only currency is your reputation, and you&#8217;ll be doing yourself a lot more harm with your ego than you&#8217;ll do good with your code.</p>
<p>If you feel really strongly about something, you can always just fork the code base and do your own thing anyway. However, even better than that, try to avoid fragmenting the community and just maintain your own branch locally, and then freely share your patches amongst the people who care about it. (And if you&#8217;re not yet using a distributed version control tool, this is a major reason to <a href="/blog/2008/03/26/howto-use-git-for-personal-development-when-everyone-else-is-using-subversion-part-1/" title="Learn how to use git for personal development when everyone else is using Subversion.">learn one, like git</a>.)</p>
<h2>Acknowledge your strengths <em>and</em> your weaknesses</h2>
<p>For a long time I completely shied away from areas in a project where I knew my skill was subpar. This was actually really stupid because it cut off one of the best opportunities I had to improve said subpar skill. I stopped doing this when I started looking at bugs in areas of code bases I was unfamiliar with and, guess what, I got better!</p>
<p>When you&#8217;re working in areas in which you are not an expert, it&#8217;s easy to become defensive about your lack of skill when you <em>know</em> you&#8217;re going to be reviewed by people who know more than you. It&#8217;s intimidating, and stressful, yes, but it&#8217;s also an amazing learning opportunity. That being said, you can&#8217;t just expect to jump into open source projects as a way to lazily get an education. If anything, I contend that learning with this method is way, way more reliant on your own initiative and effort than formal schooling is because, again, no one&#8217;s going to (nor should they) hold your hand.</p>
<p>It&#8217;s also exceptionally difficult because, since it&#8217;s open source, you&#8217;re essentially making your lack of expertise public knowledge. It&#8217;s not easy to admit having flaws in some areas, and it&#8217;s naturally even harder to do so in public. But again, when you can do this well, then you&#8217;ll also be able to garner the immense benefits that come with coding (and screwing up) in public, including greater creativity, better experimental branches, and a faster learning curve. (Once again, I think <a href="/blog/tag/git/">Git</a> is a <em>fantastic</em> tool for this.)</p>
<h2>Conclusion: treat others the way you would like to be treated</h2>
<p>As I look over much of what I&#8217;ve written here, what strikes me more than anything else is that nothing here is specific to open source software development, except the terminology. All of this is, in fact, much more relevant to the every day living of one&#8217;s life. So, as you should do in code, do in your life: identify the problems, focus on results, hone your communication, and make bettering your own process an integral part of your process.</p>
<p>After all this, well, I guess I should should get back to work now. :)</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2009/02/11/how-to-start-contributing-to-open-source-projects/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>One Minute Mac Tip: Create an encrypted disk image to store confidential files</title>
		<link>http://maymay.net/blog/2008/10/13/one-minute-mac-tip-create-an-encrypted-disk-image-to-store-confidential-files/</link>
		<comments>http://maymay.net/blog/2008/10/13/one-minute-mac-tip-create-an-encrypted-disk-image-to-store-confidential-files/#comments</comments>
		<pubDate>Mon, 13 Oct 2008 06:33:17 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[Crosspost]]></category>
		<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Security & Privacy]]></category>
		<category><![CDATA[Tech/Computing]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=548</guid>
		<description><![CDATA[Nary a day goes by when I don&#8217;t use my computer for some extremely personal stuff. I would consider it a Very Bad Thing if some of this information (my bank account details or private SSH keys, for instance) fell out of my control. Everyone has sensitive files that they keep on their computer and, [...]]]></description>
			<content:encoded><![CDATA[<p>Nary a day goes by when I don&#8217;t use my computer for some <em>extremely</em> personal stuff. I would consider it a <a href="http://www.catb.org/jargon/html/B/Bad-Thing.html">Very Bad Thing</a> if some of this information (my bank account details or private <acronym title="Secure SHell">SSH</acronym> keys, for instance) fell out of my control.</p>
<p>Everyone has sensitive files that they keep on their computer and, fortunately for Mac <acronym title="Operating System">OS</acronym> X Users, Apple has made it ridiculously easy to create a cryptographically secure containers for such files. You can think of a container like this, which is just a standard Mac <acronym title="Operating System">OS</acronym> X disk image (<code>.dmg</code>) file, like a vault that you open, put stuff you want to keep safe inside, and then close again.</p>
<p>Here&#8217;s how you go about making and using one.</p>
<h3>Create the container, an encrypted disk image</h3>
<ol>
<li>First, open up your copy of Disk Utility.app, which is located in your computer&#8217;s <code>/Applications/Utilities</code> folder. (As an aside, this program is a bit like a swiss army knife for handling disk operations in Mac <acronym title="Operating System">OS</acronym> X. You should definitely <a href="http://en.wikipedia.org/wiki/Disk_Utility">find out what else it can do</a>).</li>
<li>Next, select the <em>File &rarr; New &rarr; Blank Disk Image&hellip;</em> option. This will cause the New Blank Image window to appear.</li>
<li>Fill in the typical details such as the disk image file&#8217;s name and where you want to save it to. In addition, you&#8217;ll be presented with a number of options such as Volume Name, Volume Size, and Image Format. The defaults are usually adequate except for Volume Name, which you should customize so that when you mount the disk image the disk label is meaningful for you, and the Image Format, which I recommend you switch to &#8220;<a href="http://en.wikipedia.org/wiki/Sparse_disk_image">sparse disk image</a>.&#8221;
<p>Sparse disk images can start small and grow automatically as you write more files into them. If what you want to keep secure in this manner are very large files, say gigantic high resolution PhotoShop documents, then you might <a href="http://macosx.com/article/live-filevaultsparse-bundle-backups-in-leopard.html">consider the sparse <em>bundle</em> disk image format</a> instead.</p>
<p>Also, obviously, set the Encryption to a value other than &#8220;None.&#8221;</p>
<p>Here&#8217;s an example screenshot from my Mac:<div id="attachment_691" class="wp-caption aligncenter" style="width: 510px"><a href="http://maymay.net/blog/wp-content/uploads/2008/10/new-blank-image-screenshot.png"><img src="http://maymay.net/blog/wp-content/uploads/2008/10/new-blank-image-screenshot.png" alt="Screenshot of the New Blank Image window showing meaningful values entered, Encryption field set to 128-bit, and Image Format field set to sparse disk image." title="new-blank-image-screenshot" width="500" height="470" class="size-full wp-image-691" /></a><p class="wp-caption-text">Screenshot of the New Blank Image window showing meaningful values entered, Encryption field set to 128-bit, and Image Format field set to sparse disk image.</p></div></li>
<li>Press the &#8220;Create&#8221; button and you&#8217;ll be presented with a standard password selection dialogue. This is the password you&#8217;ll use to mount the disk image and is analogous to the idea of setting the combination on your vault&#8217;s lock. <a href="http://support.apple.com/kb/HT1506" title="Learn how to choose good passwords in Mac OS X.">It&#8217;s critical that the password you choose is a good one</a>. Ideally, your password is a totally random string that may include any printable character. Since that&#8217;s hard to remember, you can <a href="http://maymay.net/blog/2008/05/06/one-minute-mac-tip-use-mac-os-xs-keychain-to-store-recover-and-sync-all-your-passwords-from-one-place/">have the Mac <acronym title="Operating System">OS</acronym> X keychain manage your passwords for you</a>.</li>
</ol>
<h3>Encrypt some files by writing them to the disk image</h3>
<p>Now that you have an encrypted disk image, a secure container for your sensitive data, you can make use of it just as you might any other disk image on Mac <acronym title="Operating System">OS</acronym> X. For instance, say I have a top secret file called &#8220;My Killer Business Plan.pages&#8221; and I don&#8217;t want anyone to get at it. All I need to do is copy the file into my encrypted disk image, as the following screenshot shows:</p>
<a href="http://maymay.net/blog/wp-content/uploads/2008/10/encrypting-files-via-copy-to-image.jpg"><img src="http://maymay.net/blog/wp-content/uploads/2008/10/encrypting-files-via-copy-to-image-300x138.jpg" alt="Copying &quot;My Killer Business Plan.pages&quot; to the encrypted disk image encrypts the file, too." title="encrypting-files-via-copy-to-image" width="300" height="138" class="size-medium wp-image-693" /></a>
<p>It should go without saying that you want to delete the original, unencrypted copy of the file you&#8217;re copying into the encrypted disk image, but I&#8217;ll say that anyway. Don&#8217;t leave unprotected copies of your files lying around. Also, be certain to unmount (eject) the disk image when you&#8217;re done using it because the only thing the password protects is opening the disk image, not the files contained within it.</p>
<h3>External references</h3>
<p>Here are some additional places where this technique is discussed. Check out these additional articles about this topic elsewhere for more information and other perspectives:</p>
<ul>
<li><a href="http://support.apple.com/kb/HT1578">Mac <acronym title="Operating System">OS</acronym> X: How to create a password-protected (encrypted) disk image</a></li>
<li><a href="http://docs.info.apple.com/article.html?artnum=107332">Mac <acronym title="Operating System">OS</acronym> X: About Encrypted Disk Images</a></li>
<li><a href="http://www.macosxhints.com/article.php?story=20030212055706937">MacOSXHints.com: Create an encrypted disk image that grows as required</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/10/13/one-minute-mac-tip-create-an-encrypted-disk-image-to-store-confidential-files/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to use mod_rewrite rules to easily enable web site &#8220;maintenance&#8221; modes</title>
		<link>http://maymay.net/blog/2008/08/10/how-to-use-mod_rewrite-rules-to-easily-enable-web-site-maintenance-modes/</link>
		<comments>http://maymay.net/blog/2008/08/10/how-to-use-mod_rewrite-rules-to-easily-enable-web-site-maintenance-modes/#comments</comments>
		<pubDate>Sun, 10 Aug 2008 09:24:07 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[Crosspost]]></category>
		<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Web Design]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[regex]]></category>
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=574</guid>
		<description><![CDATA[When you&#8217;re administering a web site, sometimes you need to make changes that for whatever reasons require that the web site be temporarily unavailable for normal visitors. One obvious example is database maintenance. Unless you have the resources to do full-blown load balancing across a server cluster, you probably have to accept that your site [...]]]></description>
			<content:encoded><![CDATA[<p>When you&#8217;re administering a web site, sometimes you need to make changes that for whatever reasons require that the web site be temporarily unavailable for normal visitors. One obvious example is database maintenance. Unless you have the resources to do full-blown load balancing across a server cluster, you probably have to accept that your site is going to be down for a short period of time.</p>
<p>When this happens, it&#8217;s generally a good idea to show your visitors a web page that briefly explains the situation. This is typically a page that politely explains that the &#8220;site is temporarily down for maintenance&#8221; and so on. I&#8217;ve taken to calling such a page a &#8220;curtain&#8221; because it&#8217;s a little like putting a curtain up in front of construction work.</p>
<p>You put the curtain up, do whatever you need to do to fix or upgrade or maintain your web site in the background, then take the curtain down. For delicate servers, this has the added benefit of dramatically reducing server load while you do your maintenance tasks. You can even allow access to specific visitors, such as QA testers or remote admins while this curtain is up, while still redirecting normal users to the &#8220;down for maintenance&#8221; page.</p>
<p>Obviously, the first thing you need is the page that explains your site is down for maintenance reasons. This can be anything you like, but it&#8217;s simplest to make it a static <acronym title="HyperText Markup Language">HTML</acronym> page and place any and all resources you need for this page (like images) into the same folder. I often use a directory named <code>down-for-maintenance</code> and I place an <code>index.html</code> file in that folder to use as my &#8220;curtain&#8221; page. Images go straight into the <code>down-for-maintenance</code> directory, too.</p>
<p>Once you have that, you can then use the following Apache configurations to create an &#8220;on/off switch&#8221; for putting your curtain up and taking it down.</p>
<pre class="apache-config">
# To take the web site into a maintenance mode, create a file named
# maintenance-mode-on at the document (website) root, such as this:
#
#     touch maintenance-mode-on
#
# To bring the web site back, remove or rename the file, such as this:
#
#    mv maintenance-mode-on maintenance-mode-off
#
# To enable the site for your <acronym title="Internet Protocol">IP</acronym> address only but nobody else's
# uncomment the second RewriteCond directive.
&lt;IfModule mod_rewrite.c&gt;
    RewriteEngine On
    RewriteCond %{DOCUMENT_ROOT}/maintenance-mode-on -f
    #RewriteCond %{REMOTE_ADDR} !^<var>your.IP.address.here</var>$
    RewriteRule !^down-for-maintenance/.*$ /down-for-maintenance/ [R,L]
&lt;/IfModule&gt;
</pre>
<p>What this does, step by step, is:</p>
<ol>
<li>Determines whether or not you have <code>mod_rewrite</code> enabled. If you don&#8217;t, then nothing happens.</li>
<li>Enables the <code>mod_rewrite</code> rewriting engine.</li>
<li>Checks for the existence of a file called <code>maintenance-mode-on</code> at your site&#8217;s root. If such a file does not exist, nothing happens.</li>
<li>With the second <code>RewriteCond</code> directive uncommented, it also checks the visitor&#8217;s <acronym title="Internet Protocol">IP</acronym> address and if it does match the one listed nothing special happens. If it does <em>not</em> match the one listed, the next line, which is the redirect, is executed.</li>
<li>Checks the requested <acronym title="Uniform Resource Identifier">URI</acronym> and if it does not begin with <code>down-for-maintenance</code>, a temporary redirect (<acronym title="HyperText Transfer Protocol">HTTP</acronym> status code 302) is issued that points browsers to the <code>down-for-maintenance</code> directory you created earlier. Obviously, if you named this directory something else, you should change this <code>RewriteRule</code>.</li>
</ol>
<p>This isn&#8217;t perfect. For example, if a visitor is filling out a multi-page form then they might get interrupted half way through when you enable the curtain since the curtain takes effect starting at the next <acronym title="HyperText Transfer Protocol">HTTP</acronym> request after you enable it. That said, the only way to do truly graceful maintenance with zero downtime is load balancing, and that is beyond the capability of most simple sites, but this curtain is extremely simple and extremely effective.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/08/10/how-to-use-mod_rewrite-rules-to-easily-enable-web-site-maintenance-modes/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>One minute Mac tip: Schedule off-hours downloads by enabling `at`, `batch` UNIX job scheduling commands</title>
		<link>http://maymay.net/blog/2008/07/14/one-minute-mac-tip-schedule-off-hours-downloads-by-enabling-at-batch-unix-job-scheduling-commands/</link>
		<comments>http://maymay.net/blog/2008/07/14/one-minute-mac-tip-schedule-off-hours-downloads-by-enabling-at-batch-unix-job-scheduling-commands/#comments</comments>
		<pubDate>Mon, 14 Jul 2008 08:48:56 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[Crosspost]]></category>
		<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=508</guid>
		<description><![CDATA[In a lot of places in the world, many people still have to pay for bandwidth costs. I&#8217;m one of those people who just can&#8217;t afford to download lots of stuff during peak hours when my bandwidth might quickly get shaped or, worse, I&#8217;ll get charged. Nevertheless, there are often plenty of legit reasons to [...]]]></description>
			<content:encoded><![CDATA[<p>In a lot of places in the world, many people still have to pay for bandwidth costs. I&#8217;m one of those people who just can&#8217;t afford to download lots of stuff during peak hours when my bandwidth might quickly get shaped or, worse, I&#8217;ll get charged. Nevertheless, there are often plenty of legit reasons to initiate huge downloads.</p>
<p>In these cases, it makes sense to be smart about <em>when</em> I initiate these downloads. Being something of a UNIX-head myself, I wanted to use the age-old <code>at</code> command to download a Linux ISO during off-peak hours, which my <acronym title="Internet Service Provider">ISP</acronym> says starts at 2 AM. Much to my chagrin, I found that <code>at</code> doesn&#8217;t work by default on Mac <acronym title="Operating System">OS</acronym> X and, worse, the Leopard man page leads to a dead end (though it didn&#8217;t back in Tiger…).</p>
<p>Turns out that the system daemon that is responsible for checking up on <code>at</code> jobs has been wrapped with a <code>launchd</code> job. This makes enabling <code>at</code> on your system really easy:</p>
<pre>sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.atrun.plist</pre>
<p>Once you&#8217;ve done this, you can now use <code>at</code> as you normally have done. For instance, I could now schedule my downloads to happen during the off-peak hours:</p>
<pre><samp>Perseus:Fedora maymay$ </samp>at 2:15am tomorrow # now press <kbd>return</kbd>
curl -LO http://download.fedoraproject.org/pub/fedora/linux/releases/9/Fedora/x86_64/iso/Fedora-9-x86_64-<acronym title="Digital Video Disc">DVD</acronym>.iso
# now press <kbd>CTRL-D</kbd>.
<samp>job 1 at Tue Jul 15 02:15:00 2008
Perseus:Fedora maymay$ </samp>atq
<samp>1	Tue Jul 15 02:15:00 2008</samp>
</pre>
<p>This is also incredibly handy for scheduling just about any resource-intensive task that you don&#8217;t have to do <em>right now</em>. To take it one step further, you can even let the computer itself choose when to run these resource-heavy tasks by using the <code>batch</code> command, which will execute commands much like <code>at</code> but will check the system load average instead of the system clock to determine if it should start the job.</p>
<p>Note that with the <code>com.apple.atrun</code> job loaded <code>/usr/libexec/atrun</code> is started every 30 seconds (unless you change the <code>StartInterval</code> key in the <code>plist</code> file). Since the <code>atrun</code> command checks a file on disk (that it places in the <code>/usr/lib/cron/jobs</code> directory) to see if there is any work to do, this will probably prevent your disks from ever sleeping, which could be a major concern for battery life on portables. Also, obviously, your computer needs to be turned on and awake for the job to actually launch.</p>
<p>For more information, check out the result of typing <code>man at</code> and <code>man launchctl</code> at a Terminal prompt. There&#8217;s also a really good <a href="http://video.google.com/videoplay?docid=1781045834610400422">Google Tech Talk about Launchd</a> that will teach you a lot more about job scheduling on Mac <acronym title="Operating System">OS</acronym> X.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/07/14/one-minute-mac-tip-schedule-off-hours-downloads-by-enabling-at-batch-unix-job-scheduling-commands/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>One minute Mac tip: Auto-complete, spellcheck, and search for definitions in Cocoa text fields</title>
		<link>http://maymay.net/blog/2008/06/28/one-minute-mac-tip-auto-complete-spellcheck-and-search-for-definitions-in-cocoa-text-fields/</link>
		<comments>http://maymay.net/blog/2008/06/28/one-minute-mac-tip-auto-complete-spellcheck-and-search-for-definitions-in-cocoa-text-fields/#comments</comments>
		<pubDate>Sat, 28 Jun 2008 10:19:49 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[Crosspost]]></category>
		<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Writing and blogging]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=487</guid>
		<description><![CDATA[Without doubt, the most common use of computers today is to create written content of some kind. Blogs are an obvious example, but written content can take a number of forms. Writing manuscripts for publication is another example. No matter what kind of writing you&#8217;re doing, using good tools to make your writing technically better [...]]]></description>
			<content:encoded><![CDATA[<p>Without doubt, the most common use of computers today is to create written content of some kind. Blogs are an obvious example, but written content can take a number of forms. Writing manuscripts for publication is another example.</p>
<p>No matter what kind of writing you&#8217;re doing, using good tools to make your writing technically better is an incredibly handy thing. Letting the computers do the technical stuff&mdash;the stuff they&#8217;re good at&mdash;let&#8217;s you focus on the creative stuff: writing great content. Which is why, if you use a Mac, you&#8217;ll be happy to hear that any application&#8217;s text field let&#8217;s you do a number of really cool things (as long as it&#8217;s a <a href="//developer.apple.com/cocoa/">Cocoa</a> application, of course).</p>
<h2>1. Auto-complete unfinished words</h2>
<p>Try this out:</p>
<ol>
<li>Open TextEdit, from your <code>/Applications</code> directory. A new blank document will open.</li>
<li>Type <kbd>Hel</kbd> and then press the <kbd>ESC</kbd> key. A drop-down menu will suddenly appear with an alphabetically sorted auto-complete list of suggestions, sourced from your computer&#8217;s current language dictionary. It looks like this: <a href='http://maymay.net/blog/wp-content/uploads/2008/06/cocoa-text-auto-complete.png'><img src="http://maymay.net/blog/wp-content/uploads/2008/06/cocoa-text-auto-complete.png" alt="Mac OS X\&#039;s native Cocoa framework allows for many applications to get \&quot;auto-complete\&quot; functionality for free." title="cocoa-text-auto-complete" width="255" height="383" class="alignnone size-full wp-image-488" /></a></li>
</ol>
<p>This feature works with both <a href="//www.apple.com/iwork/pages/">Pages</a> and, for those of you still using it for some reason (I know you&#8217;re out there), TextEdit, too. Also, if you&#8217;re a developer <em>and</em> a writer as well (like I am), you&#8217;ll be happy to hear that this feature also works with <a href="http://developer.apple.com/tools/xcode/index.html">Xcode</a>&#8216;s Code Sense feature, and suggests completions for variable, function, class, and method names in your code.</p>
<h2>2. Spellcheck as you type</h2>
<p>A Cocoa text input field also has a number of other tricks up its sleeve. For instance, in many applications you can elect to turn on the &#8220;Check spelling as you type&#8221; feature, which will cause words you misspell (words not in the computer&#8217;s dictionary) to appear with a dotted red underline. If you right-click on these words, the contextual menu that appears will offer spelling corrections.</p>
<p>However, sometimes we use words like those in slang or colloquial language that isn&#8217;t in a proper dictionary. These words will still appear to be &#8220;misspelled&#8221; when you type, so in these cases, we can tell Mac <acronym title="Operating System">OS</acronym> X to &#8220;Learn Spelling&#8221; (also from the contextual menu). When you select this option, you append that spelling to your personal dictionary. (This is really just a plain-text file located at <code>~/Library/Spelling/<var>lang</var></code> file, where <var>lang</var> is the language code you&#8217;re typing in. For Enlgish, this file is <code>~/Library/Spelling/en</code>.)</p>
<h2>3. Look up word definitions and search for text in Google or Spotlight</h2>
<p>Last, but certainly not least, another neat thing you can do with text on your Mac is look them up with Dictionary.app. Simply highlight some selectable text on screen, right-click and select &#8220;Look up in Dictionary&#8221;. This will cause Dictionary.app to open and display the definition of the selected word.</p>
<p><a href='http://maymay.net/blog/wp-content/uploads/2008/06/cocoa-text-contextual-menu.png'><img src="http://maymay.net/blog/wp-content/uploads/2008/06/cocoa-text-contextual-menu.png" alt="" title="cocoa-text-contextual-menu" width="264" height="287" class="alignnone size-full wp-image-489" /></a></p>
<p>Since <a href="//www.apple.com/pro/tips/wiki.html">Dictionary.app can also look up articles in Wikipedia</a>, this is also a very quick way to go to a Wikipedia article without ever having to open up a Web browser.</p>
<p>Also, from the very same menu, you <em>can</em> open a Web browser. Simply select &#8220;Search in Google&#8221; to cause your default Web browser to launch a Google search for the highlighted text.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/06/28/one-minute-mac-tip-auto-complete-spellcheck-and-search-for-definitions-in-cocoa-text-fields/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>One minute Mac tip: Create the illusion that Bonjour works over a VPN</title>
		<link>http://maymay.net/blog/2008/06/26/one-minute-mac-tip-create-the-illusion-that-bonjour-works-over-a-vpn/</link>
		<comments>http://maymay.net/blog/2008/06/26/one-minute-mac-tip-create-the-illusion-that-bonjour-works-over-a-vpn/#comments</comments>
		<pubDate>Thu, 26 Jun 2008 10:25:46 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=483</guid>
		<description><![CDATA[If you&#8217;re a Mac user who often uses VPN connections, you&#8217;ll notice one very disappointing thing about connecting to your corporate or personal network over such tunneled connections: typically, Bonjour-style addresses (such as &#8220;computer-name.local&#8221;) don&#8217;t work. This is because multicast DNS (or mDNS) doesn&#8217;t work over a tunnel. Though there are ways to get it [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re a Mac user who often uses VPN connections, you&#8217;ll notice one very disappointing thing about connecting to your corporate or personal network over such tunneled connections: typically, Bonjour-style addresses (such as &#8220;computer-name.local&#8221;) don&#8217;t work. This is because multicast <acronym title="Domain Name System or Domain Name Server">DNS</acronym> (or mDNS) doesn&#8217;t work over a tunnel. Though there are ways to get it functional, they are pretty complicated and require that you have a lot of esoteric networking knowledge.</p>
<p>However, if the services you typically access via Bonjour use static <acronym title="Internet Protocol">IP</acronym> addresses, then there is one age-old networking technique you can use to simulate Bonjour-style naming conventions without actually using Bonjour. This, of course, is the <code>/etc/hosts</code> file.</p>
<p>The <code>/etc/hosts</code> is a simple, static, text-based mapping of computer names to <acronym title="Internet Protocol">IP</acronym> addresses. It does exactly what Bonjour does except it doesn&#8217;t keep itself up to date when things change. Of course, if you&#8217;re using static IPs for the services you want access to, you can pretty safely assume that things aren&#8217;t going to be changing frequently anyway. Long-time sysadmins will laugh at this, but I say let them laugh. This is remarkably useful and very easy to implement.</p>
<p>Let&#8217;s assume I&#8217;m running a personal web server on my home network, and I can access my home network via a VPN. On my home network, my web server&#8217;s <acronym title="Internet Protocol">IP</acronym> address is, say, <code>192.168.2.100</code>, and I usually access it as <code>http://server.local/</code>. All I need to do is open a Terminal prompt and run the following commands as an administrative user:</p>
<pre>
sudo echo "192.168.2.100	server.local" >> /etc/hosts
</pre>
<p>That&#8217;s it. What this does is hard-wire the name <code>server.local</code> so that it always resolves to the <acronym title="Internet Protocol">IP</acronym> address <code>192.168.2.100</code>. Now, anytime anything on my computer tries to access <code>server.local</code>, it&#8217;ll always access <code>192.168.2.100</code> directly instead of ever needing to make an mDNS query on the network. The net effect is that we can trick our computer into thinking that Bonjour is working, even when it&#8217;s not—such as over a VPN connection.</p>
<p>Note that in default cases, hard-wiring an <acronym title="Internet Protocol">IP</acronym> address like this <em>completely prevents your computer from ever asking other computers (such as <acronym title="Domain Name System or Domain Name Server">DNS</acronym> servers) what the current <acronym title="Internet Protocol">IP</acronym> address for this name is</em>. That means if the <acronym title="Internet Protocol">IP</acronym> address of the remote server changes, you won&#8217;t be notified, and things will just not work. So be mindful that you&#8217;ve made this change, and revert it as a first step in troubleshooting procedures.</p>
<p>By the way, Windows users can do the very same thing simply by editing their <code>etc/hosts</code>. They can find this file at <code>C:\WINDOWS\system32\drivers\etc\hosts</code> and can edit it with Notepad. They will also need to <a href="//www.apple.com/support/downloads/bonjourforwindows.html">install Bonjour for Windows</a> to get Bonjour working in the first place, of course.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/06/26/one-minute-mac-tip-create-the-illusion-that-bonjour-works-over-a-vpn/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Fix Subversion &#8220;checksum mismatch&#8221; error by editing .svn/entries file</title>
		<link>http://maymay.net/blog/2008/06/17/fix-subversion-checksum-mismatch-error-by-editing-svnentries-file/</link>
		<comments>http://maymay.net/blog/2008/06/17/fix-subversion-checksum-mismatch-error-by-editing-svnentries-file/#comments</comments>
		<pubDate>Tue, 17 Jun 2008 14:07:21 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[md5]]></category>
		<category><![CDATA[Subversion]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=471</guid>
		<description><![CDATA[I can&#8217;t explain why this happened because in my several-year-long history with Subversion, I&#8217;ve never experienced this issue once. However, today, I fell into the (arguably) unfortunate circumstance of running into a most disturbing error from SVN. When trying to commit my changes, SVN barfed at me and complained of a &#8220;checksum mismatch&#8221;. It looked [...]]]></description>
			<content:encoded><![CDATA[<p>I can&#8217;t explain why this happened because in my several-year-long history with Subversion, I&#8217;ve never experienced this issue once. However, today, I fell into the (arguably) unfortunate circumstance of running into a most disturbing error from SVN. When trying to commit my changes, SVN barfed at me and complained of a &#8220;checksum mismatch&#8221;. It looked something like this:</p>
<pre><samp>Transmitting file data ..svn: Commit failed (details follow):
svn: Checksum mismatch for '/Users/maymay/Sites/path/to/subversion/working/copy/.svn/text-base/working-file.php.svn-base'; expected 'cde4d8fbd5c623da3a8b1a343aa7b3f4', actual: '270b2f20804a5fcdbd15eec5910f6e3f'
</samp></pre>
<p>Of course, the <code>path/to/subversion/working/copy</code> bit was the path to my working copy file&#8217;s parent directory and the <code>working-file.php</code> was an actual file in my working directory.</p>
<p>I think what Subversion was trying to tell me is that its hashed copy of the <code>working-file.php</code> file and the copy I was asking it to commit weren&#8217;t the same. It would be nice if it would actually tell me why that happened, but it&#8217;s clearly more temperamental than that.</p>
<p>Anyway, to fix this issue (at least for now…?) I simply checked out a new working copy of this directory, examined the <code>.svn/entries</code> file from it and sure enough, found the actual checksums in there, just as Subversion reported expecting. I simply copied those expected checksums into the <code>.svn/entries</code> overwriting the old <em>actual</em> checksums and, voila, Subversion has been fooled. After that, I could commit my changes.</p>
<p>Step by step (because I&#8217;m sure someone, somewhere, somehow, will run into this again—if it&#8217;s not me that is!), this procedure looked like this:</p>
<ol>
<li>Copy the &#8220;expected&#8221; and &#8220;actual&#8221; checksums Subversion reports to you to a new text file so you can refer to them later. Note which one is the expected and which is the actual checksum.</li>
<li>Go to where the problem is (that is, <code>cd <var>path/to/broken-files-parent-dir/.svn</var></code>)</li>
<li>Open the <code>entries</code> for editing (for example, <code>vim entries</code>)</li>
<li>Search the file for the actual checksum.</li>
<li>Replace it with the expected checksum. Be careful not to change any other part of the file.</li>
<li>Save the file.</li>
<li>Try to <code>svn commit</code> again.</li>
<li>Lather, rinse, and repeat for any other files Subversion barfs at you about.</li>
</ol>
<p>I&#8217;m sure this is <em>not</em> an elegant or even the recommended solution to this problem. The truth is I never bothered to look up what the recommended solution is, because it seems to me that any code repository that can&#8217;t guarantee what I get out of it is the same as what I put into it isn&#8217;t a versioning system I really want to trust the &#8220;recommended&#8221; solution of, anyway.</p>
<p>Also known as: this is another reason why <a href="/blog/2008/03/26/howto-use-git-for-personal-development-when-everyone-else-is-using-subversion-part-1/">I like git</a> better now.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/06/17/fix-subversion-checksum-mismatch-error-by-editing-svnentries-file/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Arbitrarily exclude posts from displaying in WordPress</title>
		<link>http://maymay.net/blog/2008/06/06/arbitrarily-exclude-posts-from-displaying-in-wordpress/</link>
		<comments>http://maymay.net/blog/2008/06/06/arbitrarily-exclude-posts-from-displaying-in-wordpress/#comments</comments>
		<pubDate>Fri, 06 Jun 2008 18:11:08 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Design]]></category>
		<category><![CDATA[Writing and blogging]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=437</guid>
		<description><![CDATA[When hacking away at WordPress sites, often times you&#8217;ll find yourself in a situation where you need to filter out certain posts from displaying on some pages, such as the home page. There are a lot of ways to do this, but few are perfect. Recently, I had the need to do this and went [...]]]></description>
			<content:encoded><![CDATA[<p>When hacking away at WordPress sites, often times you&#8217;ll find yourself in a situation where you need to filter out certain posts from displaying on some pages, such as the home page. There are a lot of ways to do this, but few are perfect. Recently, I had the need to do this and went searching for pre-existing solutions.</p>
<p>I came across <a href="//blog.gadodia.net/excluding-certain-categories-from-your-blog-main-page/">Vaibhav&#8217;s post on the topic</a> and noted that his solution uses the <a href="//codex.wordpress.org/Template_Tags/query_posts" title="WordPress documentation for the query_posts() function.">query_posts()</a> function to alter WordPress&#8217;s query object before <a href="//codex.wordpress.org/The_Loop">The Loop</a> has run. While this is a great solution if your exclusion criteria is simple enough to be supported directly by the WordPress query object, other times the query_posts() function doesn&#8217;t provide you with the hook you need.</p>
<p>In these cases, you can run the original query, note any modifications you need to make, and then create a new, modified query and display the results you get from running <em>that</em> one instead. For instance, you might need to do this if you need to exclude posts based on category and, say, the beginning of their title, or their category and a certain piece of content in the post itself, or all three, or any other combination you can think of.</p>
<p>Another advantage of this technique over simpler ones is that this method maintains the same behavior you&#8217;d expect to see in every other way. Most notably, this means that if you&#8217;ve told WordPress to display the 10 most recent posts on the home page (in the WordPress settings), you&#8217;ll still see ten posts on that page even after you exclude some of them.</p>
<p>To do something like excluding posts if they are in the &#8220;Uncategorized&#8221; category (traditionally the category with an ID of 1 in WordPress) and their title begins with &#8220;Some title&#8221;, you can do this:</p>
<pre class="php">
// original query runs in The (real) Loop first
while ( have_posts() ) : the_post();
    // detect pots matching our exclusion criteria
    if (in_category(1) &#038;&#038; (0 === strpos(the_title('', '', false), 'Some title')) ) {
        $wp_query->post_count++; // increment the post counter
        continue;
    }
    endif;
endwhile;
// now make a new query and show the posts for real, with the adjusted post count and filtering
$my_new_query = new WP_Query($query_string.'&#038;showposts='.$wp_query->post_count);
// do another The Loop (and display the results this time)
while ( $my_new_query->have_posts() ) : $my_new_query->the_post();
    // detect and exclude these same posts
    if (in_category(1) &#038;&#038; (0 === strpos(the_title('', '', false), 'Some title')) ) { continue; }

// ...the rest of the WordPress template goes here...
</pre>
<p>This is neat because it gives you the capability to define arbitrarily complex exclusion patterns and directly modify your new query object however you like before you execute it. Once you know this works, you&#8217;ll probably want to extract the filtering code into a function. Using the above example, your new code might look like this:</p>
<pre class="php">
<strong>// define criteria for filtering
function matches_filtering_criteria () {
    if (in_category(1) &#038;&#038; (0 === strpos(the_title('', '', false), 'Some title')) ) {
        return true;
    } else {
        return false;
    }
}</strong>
// original query runs in The (real) Loop first
while ( have_posts() ) : the_post();
    // detect pots matching our exclusion criteria
    if (<strong>matches_filtering_criteria()</strong>) {
        $wp_query->post_count++; // increment the post counter
        continue;
    }
    endif;
endwhile;
// now make a new query and show the posts for real, with the adjusted post count and filtering
$my_new_query = new WP_Query($query_string.'&#038;showposts='.$wp_query->post_count);
// do another The Loop (and display the results this time)
while ( $my_new_query->have_posts() ) : $my_new_query->the_post();
    //
    // detect and exclude these same posts
    if (<strong>matches_filtering_criteria()</strong>) { continue; }

// ...the rest of the WordPress template goes here...
</pre>
<p>For more information on these functions, see:</p>
<ul>
<li><a href="//codex.wordpress.org/The_Loop">The Loop</a></li>
<li><a href="//codex.wordpress.org/Template_Tags/in_category">in_category()</a></li>
<li><a href="//codex.wordpress.org/Template_Tags/the_title">the_title()</a></li>
<li><a href="//codex.wordpress.org/Function_Reference/WP_Query">WP_Query()</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/06/06/arbitrarily-exclude-posts-from-displaying-in-wordpress/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>One Minute Mac Tip: Use the command line to edit the content of your clipboard</title>
		<link>http://maymay.net/blog/2008/05/09/one-minute-mac-tip-use-the-command-line-to-edit-the-content-of-your-clipboard/</link>
		<comments>http://maymay.net/blog/2008/05/09/one-minute-mac-tip-use-the-command-line-to-edit-the-content-of-your-clipboard/#comments</comments>
		<pubDate>Fri, 09 May 2008 05:08:21 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Tech/Computing]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=433</guid>
		<description><![CDATA[Using the pbpaste and pbcopy commands, you can manipulate the contents of the Mac OS X clipboard (or more formally known as the pasteboard) right from the command line. As a brief example, just select the text of this first paragraph, copy it to your clipboard (with -c), and then type pbpaste in a Terminal [...]]]></description>
			<content:encoded><![CDATA[<p>Using the <code>pbpaste</code> and <code>pbcopy</code> commands, you can manipulate the contents of the Mac <acronym title="Operating System">OS</acronym> X clipboard (or more formally known as the <em>pasteboard</em>) right from the command line. As a brief example, just select the text of this first paragraph, copy it to your clipboard (with <kbd>-c</kbd>), and then type <code>pbpaste</code> in a Terminal prompt. You should see output similar to the following:</p>
<pre><samp>Perseus:~ meitar$ </samp><kbd>pbpaste</kbd>
<samp>Using the pbpaste and pbcopy commands, you can manipulate the contents of the Mac <acronym title="Operating System">OS</acronym> X clipboard (or more formally known as the pasteboard) right from the command line. As a brief example, just select the text of this first paragraph, copy it to your clipboard (with ?-c), and then type pbpaste in a Terminal prompt. You should see output similar to the following:Perseus:~ meitar$ </samp></pre>
<p>Pretty straightforward, right? The only thing to be aware of is that the  symbol showed up in the output as a ? symbol. This is because the Terminal doesn&#8217;t support Unicode, but that&#8217;s a topic for another time.</p>
<p>Anyway, what&#8217;s happening here is nothing more magical than simply reading the clipboard and pasting it into a command&#8217;s standard output stream. As a result, you can construct pipelines that read  from or add content to the clipboard. Here&#8217;s an example in reverse, which takes a command&#8217;s standard output and replaces the contents of the clipboard with it:</p>
<pre><kbd>echo "Hello world! I came from the command line, but now I'm in the clipboard." | pbcopy</kbd></pre>
<p>This command produces no output, but if we examine the contents of the clipboard (by selecting <strong>Edit &rarr; Show Clipboard</strong> from the Finder&#8217;s menu bar) we can see that the text we echoed has indeed been copied there.</p>
<p><a href='/blog/wp-content/uploads/2008/05/finder-clipboard-contents.png'><img src="http://maymay.net/blog/wp-content/uploads/2008/05/finder-clipboard-contents.png" alt="The clipboard now contains the text we echoed from the command line." title="finder-clipboard-contents" width="386" height="186" class="aligncenter size-full wp-image-434" /></a></p>
<p>Another way we can verify that this worked as expected is to simply <code>pbpaste</code> again:</p>
<pre><samp>Perseus:~ meitar$ </samp><kbd>pbpaste</kbd>
<samp>Hello world! I came from the command line, but now I'm in the clipboard.
Perseus:~ meitar$ </samp></pre>
<p>Anyway, this is cool, but it isn&#8217;t very useful yet. For that, we need to add some more stages to our pipeline. Let&#8217;s take the simple case of trying to count how many words the selected text contains. We&#8217;ll use the clipboard contents shown above to do this:</p>
<pre><samp>Perseus:~ meitar$ </samp><kbd>pbpaste | wc -w</kbd>
<samp>      14</samp></pre>
<p>Using the word count (<code>wc</code>) utility, we can count words (<code>-w</code>) very easily. Indeed, our previous example does have exactly 14 words in it. We can also count characters (<code>-c</code>) or lines (<code>-l</code>) of text in the clipboard this way. This is like adding Microsoft Word&#8217;s &#8220;Word Count&#8221; feature to every single piece of text you can copy!</p>
<p>As another example take, for instance, the simple case of copying and pasting a snippet of email from Mail. Instead of pasting it back into a text file verbatim, let&#8217;s prepend &#8216;&gt; &#8216; to the beginning of each line. This way, when we paste our email&#8217;s snippet, we&#8217;ll know where the snippet begins and where it ends. This is a simple three-stage pipeline that uses <code>pbpaste</code> to take our clipboard and put it into the pipeline and then reads back the result from the pipeline back to the clipboard using <code>pbcopy</code>. In the middle, we use sed to insert the desired text at the start of each line:</p>
<pre><kbd>pbpaste | sed -e 's/^/&gt; /' | pbcopy</kbd></pre>
<p>Now, when you paste your clipboard, you&#8217;ll have a greater-than symbol at the start of each line. Naturally, check out the manual pages for all of these commands for more detailed information. For instance, type <code>man pbpaste</code> for more information about the <code>pbpaste</code> command.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/05/09/one-minute-mac-tip-use-the-command-line-to-edit-the-content-of-your-clipboard/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>One Minute Mac Tip: Use Mac OS X&#8217;s Keychain to Store, Recover, and Sync All Your Passwords From One Place</title>
		<link>http://maymay.net/blog/2008/05/06/one-minute-mac-tip-use-mac-os-xs-keychain-to-store-recover-and-sync-all-your-passwords-from-one-place/</link>
		<comments>http://maymay.net/blog/2008/05/06/one-minute-mac-tip-use-mac-os-xs-keychain-to-store-recover-and-sync-all-your-passwords-from-one-place/#comments</comments>
		<pubDate>Tue, 06 May 2008 09:08:34 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Security & Privacy]]></category>
		<category><![CDATA[Tech/Computing]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=429</guid>
		<description><![CDATA[Since Mac OS X 10.2 Jaguar, Mac users have been accustomed to the ease of use of Apple&#8217;s very cool Keychain Services technology. The Mac OS X Keychain basically a secure database of all your passwords, sorted into files called (unsurprisingly enough) &#8220;keychains.&#8221; Each user account on a Mac OS X system has a login.keychain, [...]]]></description>
			<content:encoded><![CDATA[<p>Since Mac <acronym title="Operating System">OS</acronym> X 10.2 Jaguar, Mac users have been accustomed to the ease of use of Apple&#8217;s very cool Keychain Services technology. The Mac <acronym title="Operating System">OS</acronym> X Keychain basically a secure database of all your passwords, sorted into files called (unsurprisingly enough) &#8220;keychains.&#8221; Each user account on a Mac <acronym title="Operating System">OS</acronym> X system has a <code>login.keychain</code>, and the system itself also has a <code>system.keychain</code>.</p>
<p>Whenever you tell an application to &#8220;Remember this password in my keychain,&#8221; what you&#8217;re doing is writing a new encrypted entry into your user account&#8217;s <code>~/Library/Keychains/login.keychain</code> file. Then, the next time the application needs to access a restricted resource, it just asks Mac <acronym title="Operating System">OS</acronym> X to get the password for it. Of course, all of this happens automatically, so except for that single checkbox most users probably don&#8217;t know that the keychain even exists.</p>
<p>What&#8217;s even more awesome than all of this automagic password storing action, though, is the fact that Apple has also provided an easy-to-use application to manipulate the keychain yourself. What good does this do us? Plenty! Observe.</p>
<p>Say you&#8217;ve just signed up with a new <acronym title="Internet Service Provider">ISP</acronym>. They send you a username and a password to log on to their ADSL network with. Of course, they send this password to you on paper—how insecure! Instead, after changing the password to something else first (something <em>other</em> than <kbd>mypassword</kbd>, which is the example password I&#8217;ll use here), we can use Mac <acronym title="Operating System">OS</acronym> X Keychain to securely store the password and retrieve it later.</p>
<ol>
<li>First, launch the Keychain Access application located in the <code>/Applications/Utilities</code> folder of your startup drive.</li>
<li>Next, click the &#8220;Create a new Keychain item&#8221; button (the +) button near the lower left-hand corner of the window. The Add Keychain Item sheet appears.</li>
<li>Enter a meaningful name, such as &#8220;ADSL <acronym title="Internet Service Provider">ISP</acronym> Account&#8221; in my example, in the Keychain Item Name field.</li>
<li>Enter the username or account name associated with this password in the Account Name field.</li>
<li>Enter the password into the Password field.</li>
<li>Click the Add button.</li>
</ol>
<p>That&#8217;s all there is to it. To later retrieve your password if, say, you ever forget it:</p>
<ol>
<li>Launch the Keychain Access application.</li>
<li>Locate and double-click the keychain item that stores the account and password information you want to retrieve.</li>
<li>Tick the &#8220;Show password&#8221; checkbox. You&#8217;ll be presented with a dialogue box that asks for your keychain&#8217;s master password. Unless you&#8217;ve already set it to something else, this is the same password you use to log in to your Mac <acronym title="Operating System">OS</acronym> X user account.<a href='/blog/wp-content/uploads/2008/05/mac-os-x-105-leopard-keychain-access-password-dialogue-box.png'><img src="/blog/wp-content/uploads/2008/05/mac-os-x-105-leopard-keychain-access-password-dialogue-box.png" alt="Screenshot of Mac OS X 10.5 Leopard\&#039;s Keychain Access application requesting password access to the user\&#039;s login.keychain file." title="mac-os-x-105-leopard-keychain-access-password-dialogue-box" width="500" height="321" class="alignnone size-full wp-image-430" /></a></li>
<li>Enter your keychain password and click &#8220;Allow.&#8221; If you click &#8220;Always Allow&#8221; instead, Keychain Access will not prompt you for your login keychain&#8217;s password the next time you ask to see this particular password. I <em>never</em> press that button.</li>
<li>Your password&#8217;s plaintext is now visible.<a href='/blog/wp-content/uploads/2008/05/keychain-access-showing-plaintext-password.png'><img src="/blog/wp-content/uploads/2008/05/keychain-access-showing-plaintext-password.png" alt="" title="keychain-access-showing-plaintext-password" width="211" height="23" class="alignnone size-medium wp-image-431" /></a></li>
</ol>
<p>This effectively obviates the need for third-party applications such as <a href="//fpx.de/fp/Software/Gorilla/">Password Gorilla</a>, <a href="//www.selznick.com/products/passwordwallet/index.htm">PasswordWallet</a> or <a href="//www.keepassx.org/">KeePassX</a> which are great programs, but all suffer from a lack of a good user interface. Furthermore, there&#8217;s no reason why we can&#8217;t store short arbitrary strings of sensitive information in the keychain temporarily. Sure, it might clutter up your keychain, but you can always search the entries using the standard Mac <acronym title="Operating System">OS</acronym> X filter search bar at the top right of the window.</p>
<p><ins datetime="2008-05-24T13:38:46+00:00">In fact, Apple&#8217;s been kind enough to offer an interface to do just that in an even more effective way, called Secure Notes. These are simply plain text strings of arbitrary length that can be stored securely inside your keychain, and that use the same interface to access (requiring your password to view). The only real difference is that instead of a single line, you&#8217;re given a fully scrollable text area in which to type your secure note.</ins></p>
<p>Moreover, because keychains can be synced to multiple Macs with .Mac Sync (or a third-party synchronization solution), you can always have access to all your passwords regardless of which physical Mac you&#8217;re using. Best of all, since you never have to remember another password ever again, you can quit using the same password for multiple accounts, and you can always use <a href="//grc.com/passwords" title="Get a really secure password from Gibson Research Corporation's popular Perfect Passwords page.">really hard-to-crack passwords</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/05/06/one-minute-mac-tip-use-mac-os-xs-keychain-to-store-recover-and-sync-all-your-passwords-from-one-place/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How To: Move all pages in an Apple WikiServer Group to a new Group</title>
		<link>http://maymay.net/blog/2008/05/01/how-to-move-all-pages-in-an-apple-wikiserver-group-to-a-new-group/</link>
		<comments>http://maymay.net/blog/2008/05/01/how-to-move-all-pages-in-an-apple-wikiserver-group-to-a-new-group/#comments</comments>
		<pubDate>Thu, 01 May 2008 09:18:16 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=427</guid>
		<description><![CDATA[As I&#8217;ve been blogging about, I&#8217;ve been playing a lot with Apple&#8217;s new WikiServer (or &#8220;Teams Server&#8221;) at work. We&#8217;re still evaluating what we&#8217;d like to use it for, but as part of the experiments, I&#8217;ve been finding myself having to do some pretty crazy things with the WikiServer. This one is pretty bizarre, and [...]]]></description>
			<content:encoded><![CDATA[<p>As I&#8217;ve been blogging about, I&#8217;ve been <a href="/blog/2008/04/05/a-web-developers-introduction-to-the-apple-wikiserver-part-1/">playing a lot</a> with Apple&#8217;s new WikiServer (or &#8220;Teams Server&#8221;) at work. We&#8217;re still evaluating what we&#8217;d like to use it for, but as part of the experiments, I&#8217;ve been finding myself having to do some pretty crazy things with the WikiServer. This one is pretty bizarre, and is probably not only very dangerous for the content of your group&#8217;s wiki and blog, but also almost certainly not a best-practice.</p>
<p>With that caveat out of the way, here&#8217;s how I managed to move all the pages in an Apple WikiServer group wiki and blog from one group to another.</p>
<h2>Dear God, please have a backup!</h2>
<p>Okay, step 1 is mundane, but seriously, please of please have a backup of your data before you do any of these things. To make a back up of your entire WikiServer&#8217;s data store, simply:</p>
<pre><kbd>sudo tar -cvzf <var>backup-file-name</var>.tgz /Library/Collaboration</kbd></pre>
<p>If anything goes wrong, you can restore from your backup just as simply:</p>
<pre><kbd>sudo tar -C /Library/Collaboration -xvzf <var>backup-file-name</var>.tgz</kbd></pre>
<p>Okay, with that out of the way, next make sure absolutely nobody is using any of the Group services for the group you are going to perform the move from, or to. People can work on other group&#8217;s wikis, it&#8217;s just the ones you&#8217;ll be touching you want people to avoid. You can enforce this with some Apache redirects, which is left as an exercise to the reader.</p>
<h2>Step 1: Rename or create a new Group in Workgroup Manager</h2>
<p>First, you need to either rename or create a new group in Workgroup Manager. If you make a new group, be sure to enable all the services that the old group used.</p>
<p>If you&#8217;re simply renaming a group, then you might not even have to go through this trouble. You merely need to change the group&#8217;s &#8220;Name&#8221; (as opposed to its &#8220;Short Name&#8221;) and then stop and start the Web Service from Server Admin to see the group&#8217;s name change. However, if you also want to change the group&#8217;s &#8220;Short Name&#8221; (i.e., the group&#8217;s POSIX group account symbolic name), then you will need to perform these steps.</p>
<p>Once you have the new group ready to go in Workgroup Manager and you have stopped and started your Web Service in Server Admin, continue to the next step.</p>
<h2>Step 2: rsync all your files from the old group to the new group</h2>
<p>This is simple. Just run:</p>
<pre><kbd>sudo rsync -avzE --progress /Library/Collaboration/Groups/<var>old-group</var>/ /Library/Collaboration/Groups/<var>new-group</var>/</kbd></pre>
<p>Note that the trailing slashes on the directory names in this command are quite important, as they tell <code>rsync</code> to take the <em>contents</em> of the first directory and place those items as the contents of the second directory. Without the trailing slashes, <code>rsync</code> will make extraneous directories for you, which Apple WikiServer won&#8217;t understand. See <code>man rsync</code> for more information.</p>
<h2>Step 3: Update the <code>plist</code>s for all your WikiServer pages in the new group</h2>
<p>Now, WikiServer has all the content of your old group but all of the internal references are wrong, since they still point to the old group. What you need to do is rewrite all those references so that they point to the new group address. The group references are stored in property list files. See my older blog entries for <a href="/blog/2008/04/08/a-web-developer’s-introduction-to-the-apple-wikiserver-part-2/">details about the filesystem structure of Apple&#8217;s WikiServer</a> data storage layout.</p>
<p>To do this is a relatively simple procedure. As root, do the following, and do it <em>carefully</em> because as root you can easily mess up (and there is no undo button on the command line!):</p>
<pre><kbd>sudo su -</kbd>
<kbd>cd /Library/Collaboration/Groups/<var>new-group</var></kbd>
<kbd>grep -ri "<var>old-group</var>" * | grep '^[^B]' | cut -d ':' -f 1 | grep 'plist$' | sort | uniq &gt; /tmp/<var>list_of_plist_files_to_edit</var></kbd>
<kbd>for i in `cat /tmp/<var>list_of_plist_files_to_edit</var>`; do sed -e 's/&lt;string&gt;groups\/<var>old-group</var>/&lt;string&gt;groups\/<var>new-group</var>/' $i &gt; $i.new; mv "$i.new" "$i"; chown teamsserver:teamsserver "$i"; chmod o-rwx "$i" done;</kbd></pre>
<p>In English, this means:</p>
<ol>
<li>Become root.</li>
<li>Change to the <code>/Library/Collaboration/Groups/<var>new-group</var></code> directory</li>
<li>Find all <code>plist</code> files that have the the string <var>old-group</var> in them, sort them, and write this list of files to the <code>/tmp/<var>list_of_plist_files_to_edit</var></code> file.</li>
<li>For each of the files listed in the <code>/tmp/<var>list_of_plist_files_to_edit</var></code>, find the text string <code>&lt;string&gt;groups/<var>old-group</var></code> and replace that text with <code>&lt;string&gt;groups/<var>new-group</var></code>, and save this change as the name of the file with <code>.new</code> appended. Finally, replace the original file with the file we modified, and give them the appropriate permissions.</li>
</ol>
<h2>Step 4: Create an Apache redirect to make sure no <acronym title="HyperText Markup Language">HTML</acronym> links are broken</h2>
<p>Okay, at this point your new group is up and running and it should be working. However, if you had any links at all in any of your group&#8217;s pages, they are now all broken because they still point to the old group. Rather than going through the <acronym title="HyperText Markup Language">HTML</acronym> itself and cleaning this up right now (because that&#8217;s very error-prone indeed, even with automated tools), it&#8217;s much easier to just tell Apache to redirect all requests for the old group to the new group.</p>
<p>To do this, edit the Apache configuration file of whatever Virtual Host you have been serving the WikiServer from. Most of the time, this will be at <code>/etc/httpd/sites/0000_any_80_.conf</code>.</p>
<p>The end of that file probably looks something like this::</p>
<pre>#       Include /etc/httpd/httpd_users.conf
#       Include /etc/httpd/httpd_directory.conf
        Include /etc/httpd/httpd_groups.conf
        Include /etc/httpd/httpd_teams_required.conf
        LogLevel warn
        ServerAlias *
&lt;/VirtualHost&gt;</pre>
<p>Right above these <code>Include</code> directives, simply add the following:</p>
<pre><kbd>        &lt;Location /groups&gt;
            &lt;IfModule mod_alias.c&gt;
                Redirect 301 /groups/<var>old-group</var> http://<var>your.server.address</var>/groups/<var>new-group</var>
            &lt;/IfModule&gt;
        &lt;/Location&gt;</kbd>
#       Include /etc/httpd/httpd_users.conf
#       Include /etc/httpd/httpd_directory.conf
        Include /etc/httpd/httpd_groups.conf
        Include /etc/httpd/httpd_teams_required.conf
        LogLevel warn
        ServerAlias *
&lt;/VirtualHost&gt;
</pre>
<p>There you have it. New Teams Server group, old group&#8217;s data.</p>
<h2>Caveats</h2>
<p>Note that this does <em>not</em> update any of the SQLite databases used to store things like revision history and so forth. These things are, for the most part, not really necessary to update but it would be ideal if the old <code>plist</code> revisions could be changed in there, too. That&#8217;s not so much more extra work, really, but I&#8217;ve found it typically unnecessary except in fringe cases, so I leave that as an exercise to the reader.</p>
<p>If you do this to your WikiServer and do not update the SQLite databases as well, just be mindful of that fact so that you&#8217;re not surprised if something goes wonky down the line.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/05/01/how-to-move-all-pages-in-an-apple-wikiserver-group-to-a-new-group/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to import CVS code repositories into Git using `git cvsimport`</title>
		<link>http://maymay.net/blog/2008/04/15/how-to-import-cvs-code-repositories-into-git-using-git-cvsimport/</link>
		<comments>http://maymay.net/blog/2008/04/15/how-to-import-cvs-code-repositories-into-git-using-git-cvsimport/#comments</comments>
		<pubDate>Tue, 15 Apr 2008 09:06:24 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=425</guid>
		<description><![CDATA[This should be straightforward, but it&#8217;s not. To import (not track, but just import) code from a remote CVS repository to a local git repository, you need to do the following: Be certain you have the git-core package installed on your system and that this package includes the git-cvsimport command. You can run git help [...]]]></description>
			<content:encoded><![CDATA[<p>This should be straightforward, but it&#8217;s not. To import (not <em>track</em>, but just import) code from a remote <acronym title="Concurrent Versions System">CVS</acronym> repository to a local git repository, you need to do the following:</p>
<ol>
<li>Be certain you have the git-core package installed on your system and that this package includes the <code>git-cvsimport</code> command. You can run <code>git help -a | grep cvsimport</code> to verify this.</li>
<li>Be certain you have the <code>cvsps</code> command-line tool installed. This does <em>not</em> come with the git suite of tools, so you&#8217;ll need to get it separately. If you&#8217;re a lazy Mac <acronym title="Operating System">OS</acronym> X user, like me, you can use MacPorts: <code>sudo port install cvsps</code>. Otherwise, get it from <a href="//www.cobite.com/cvsps/">the source</a>.</li>
<li>Prepare your <acronym title="Concurrent Versions System">CVS</acronym> login information for the remote server <em>before</em> you run <code>git cvsimport</code>. You need to do this so that the git tool will be able to log you in to the <acronym title="Concurrent Versions System">CVS</acronym> server automatically. The command for this looks like:
<pre>CVSROOT=:<var>cvs-login-method</var>:<var>cvs-user-name</var>@<var>cvs.server.name</var>:<var>/path/to/CVS/root</var> cvs login</pre>
<p> For example, if you&#8217;re pulling code from the anonymous <acronym title="Concurrent Versions System">CVS</acronym> server that runs on Drupal.org, you might use this: <code>CVSROOT=:pserver:anonymous@cvs.drupal.org:/cvs/drupal-contrib cvs login</code>. This command will prompt you for the password for the user you specified at the server you specified (for anonymous access, the password is almost always <code>anonymous</code>) and will hash this in the <code>~/.cvspass</code> file for future use by <acronym title="Concurrent Versions System">CVS</acronym></li>
<li>Finally, run the <code>git cvsimport</code> tool, and specify the proper options. Using the Drupal example above, your command might look like this:
<pre>git cvsimport -v -d :pserver:anonymous@cvs.drupal.org:/cvs/drupal-contrib contributions/modules/<var>module-name</var></pre>
<p> This would login to <code>cvs.drupal.org</code> using the <acronym title="Concurrent Versions System">CVS</acronym>&#8216;s <code>pserver</code> login method, provide the username <code>anonymous</code> and the password you specified in the previous step that is hashed in <code>~/.cvspass</code>, set the <acronym title="Concurrent Versions System">CVS</acronym> document root to <code>/cvs/drupal-contrib</code>, and pull the code located at <code>contributions/modules/<var>module-name</var></code> into the current working directory as a git repository.</li>
</ol>
<p>This works pretty nicely, and creates a git repository just as though you&#8217;d created it with <code>git init</code> in the current working directory.</p>
<p>If you get an error that looks like this:</p>
<pre>AuthReply: cvs [pserver aborted]: descramble: unknown scrambling method</pre>
<p>then you&#8217;ve most likely specified the <acronym title="Concurrent Versions System">CVS</acronym> document root incorrectly. Most notably, <code>git cvsimport</code> does not understand a <acronym title="Concurrent Versions System">CVS</acronym> document root wherein the password is specified in the document root <acronym title="Uniform Resource Locator">URL</acronym> itself. So, for example, <code>git cvsimport -d :pserver:<var>password</var>:<var>username</var>@<var>cvs.server.name</var>:<var>/path/to/CVS/root</var> <var>code/to/checkout</var></code> will not work. Omitting the password and the separating colon from the <acronym title="Uniform Resource Locator">URL</acronym> should fix it.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/04/15/how-to-import-cvs-code-repositories-into-git-using-git-cvsimport/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>HowTo: Use git for personal development when everyone else is using Subversion (part 2)</title>
		<link>http://maymay.net/blog/2008/03/28/howto-use-git-for-personal-development-when-everyone-else-is-using-subversion-part-2/</link>
		<comments>http://maymay.net/blog/2008/03/28/howto-use-git-for-personal-development-when-everyone-else-is-using-subversion-part-2/#comments</comments>
		<pubDate>Fri, 28 Mar 2008 08:20:36 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/2008/03/28/howto-use-git-for-personal-development-when-everyone-else-is-using-subversion-part-2/</guid>
		<description><![CDATA[When we left off, you had just finished transforming a remote Subversion repository into a git repository and optimizing it to save you some space. Now that you have a git repository, what do you do? First things first. Once you have an idea of what work you want to do, you should give yourself [...]]]></description>
			<content:encoded><![CDATA[<p>When we left off, you had just finished transforming a remote Subversion repository into a git repository and optimizing it to save you some space. Now that you have a git repository, what do you do?</p>
<p>First things first. Once you have an idea of what work you want to do, you should give yourself a space to do this work without disturbing anybody else&#8217;s work. Do this by making a new, personal branch. Unlike Subversion and some other centralized version control systems, git makes it possible to do make all kinds of changes to your repository, including making branches, and even save those changes without having to republish everything back to the central repository server at each step. In other words, if you thought Subversion branches were &#8220;cheap,&#8221; you&#8217;ll love git&#8217;s branches.</p>
<p>Also unlike Subversion, which stores its branches in completely separate pathnames, git keeps all branches in the same filesystem tree separated only with metadata (in <code>.git/refs/remotes</code> for remote branches and in <code>.git/refs/heads</code> for local branches, to be a bit more precise), so you don&#8217;t have to create lots of different directories for all your branches (unless you want to). With no branches defined, you&#8217;re working in the &#8220;master branch,&#8221; or &#8220;the trunk&#8221; by default.</p>
<pre><kbd>git branch</kbd>
<samp>* master</samp></pre>
<p>By saying <code>git branch</code> you ask git to print a list of all (local) branches. The one with the asterisk marks the current branch, the one you&#8217;re using at the moment you run the command. Since there are no branches, you&#8217;re currently in the &#8220;master&#8221; branch. But we don&#8217;t want to make changes here, we want to make changes in our own private branch, so we&#8217;ll make a new one.</p>
<pre>git checkout -b <var>new_branch_name</var></pre>
<p>This will create a new branch with the name <var>new_branch_name</var> and immediately switch to it. Notice that you&#8217;ve made absolutely no changes to the filesystem itself; only the git metadata has been altered. Saying <code>git branch</code> again will show you the change:</p>
<pre><kbd>git branch</kbd>
<samp>  master
* new_branch_name</samp></pre>
<p>Also note that since we haven&#8217;t comitted any changes, we don&#8217;t need a commit message (or &#8220;log message&#8221;) for creating this branch. We&#8217;ll add one later, when we need it. Now go ahead and write some code in your new branch. At any time, you can create a new branch in the same way you added the first. Each new branch is created at the <code>HEAD</code> (&#8220;latest&#8221;) revision of whatever branch you&#8217;re currently working in.</p>
<pre><kbd>git checkout -b <var>another_branch</var></kbd>
<samp>Switched to a new branch "<var>another_branch</var>"</samp>
<kbd>git branch</kbd>
<samp>  master
  new_branch_name
* another_branch</samp></pre>
<p>To switch back to any other branch, simply <code>git checkout</code> that branch again:</p>
<pre><kbd>git checkout master</kbd>
<samp>Switched to branch "master"</samp></pre>
<p>If you want to delete a branch you don&#8217;t like, that&#8217;s easy too:</p>
<pre><kbd>git branch -d <var>another_branch</var></kbd>
<samp>Deleted branch <var>another_branch</var></samp>.</pre>
<p>Keep in mind that throughout all of these branch creation and deletion actions, the only thing that&#8217;s being altered is the git metadata. That&#8217;s why it&#8217;s so cheap to create new branches. If you ever have a new idea you&#8217;re working on, it&#8217;s recommended that you create a branch for it, even if that branch is so short-lived it never gets published.</p>
<p>So you have a new local branch, and you&#8217;ve been working as you normally do for a few minutes, creating files, editting them, and so on. Running <code>git status</code> now will ask git to show you the changes you&#8217;ve made to your filesystem. If you&#8217;ve created any files in new directories that git doesn&#8217;t know about, it will simply report that directory. If you&#8217;ve made new files in directories git does know about, it will list all those files explicitly.</p>
<pre><kbd>git status</kbd>
<samp># On branch cartoon_contests
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	sites/default/modules/cartoon_contests/
#	sites/default/modules/factiva/.factiva.module.swp
#	sites/default/modules/testfile
#	sites/default/settings.php
nothing added to commit but untracked files present (use "git add" to track)
</samp></pre>
<p>In the above sample output, I&#8217;m working on a new Drupal module for a web site. I&#8217;ve created a new directory, <code>sites/default/modules/cartoon_contests/</code> (note the trailing slash), and I have several untracked files. One is my <a href="//vim.org/">vim</a> swap file for a different module, <code>.factiva.module.swp</code>, one&#8217;s an unimportant <code>testfile</code>, and the last is the Drupal configuration file, <code>settings.php</code>.</p>
<p>The only thing I want to commit is the new <code>cartoon_contests</code> directory, and all the files within it. Like Subversion, I have to tell git that I want to <dfn>track</dfn> this directory, which is done simply by saying <code>git add cartoon_contests</code>. Unlike Subversion, future invocations of <code>git status</code> let me see everything that git is going to go in the next commit.</p>
<pre><kbd>git status</kbd>
<samp># On branch cartoon_contests
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	new file:   sites/default/modules/cartoon_contests/cartoon_contests.info
#	new file:   sites/default/modules/cartoon_contests/cartoon_contests.module
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	sites/default/modules/factiva/.factiva.module.swp
#	sites/default/modules/testfile
#	sites/default/settings.php</samp></pre>
<p>The &#8220;Changes to be committed&#8221; section of the output is called the <dfn>staging area</dfn>, or the <dfn>index</dfn>. In this way, I can prepare all the changes I want to commit before I do so, making sure they&#8217;re perfect before I actually commit them to the git repository. At any time before I commit, I can make additional modifications, such as <code>git add</code>ing more files or directories, <code>git reset</code>ing to unstage all (or some) of my changes, etc. <code>git help reset</code> also has a number of handy explanations with examples for different things you might need to do at this point.</p>
<p>If you were using <code>svn:ignore</code>, equivalent functionality exists in git. Simply append file glob patterns, one per line, to the <code>$GIT_DIR/info/exclude</code> file in your git repository. Like so:</p>
<pre><kbd>echo -e "*.swp\nsites/default/settings.php" >> .git/info/exclude ; git status</kbd>
<samp># On branch cartoon_contests
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	new file:   sites/default/modules/cartoon_contests/cartoon_contests.info
#	new file:   sites/default/modules/cartoon_contests/cartoon_contests.module
#
</samp></pre>
<p>If you&#8217;ve got many of these, you can use <code>git svn show-ignore >> .git/info/exclude</code> to search through your old Subversion repository and look for any and all ignores, automatically adding them to git&#8217;s exclude list. (Checkout <a href="//tsunanet.blogspot.com/2007/07/learning-git-svn-in-5min.html">Tsuna&#8217;s blog entry on learning git</a> for more tips like this.)</p>
<p>Finally, after you&#8217;ve done some of your work and you&#8217;ve finished <dfn>staging</dfn> your changes, you&#8217;re ready to commit them to the repository. On the other hand, if you hate what you&#8217;ve done and want to undo it all, you can say <code>git reset --hard HEAD</code> to throw away all your local changes. To throw away changes to just a single file, just checkout that file again by saying <code>git checkout <var>filename</var></code>. This is the equivalent of Subversions <code>svn revert <var>filename</var></code> command.</p>
<p>Before you actually make your first commit, however, you should properly introduce yourself to git. You don&#8217;t have to do this because git will try to figure out who you are by itself (<a>details explained in detail here</a>), but you probably should at least create global defaults for your user (which git will store in <code>~/.gitconfig</code>). If you want to, you can also create per-repository defaults (which git will store in <code>.git/config</code>), or even system-wide defaults for all users of this computer (which git will store in <code>/etc/gitconfig</code>). To do so, say this:</p>
<pre><kbd>git config --global user.name "Your Full Name"
git config --global user.email "you@example.com"</kbd></pre>
<p>This will create the file <code>~/.gitconfig</code> if it doesn&#8217;t alreay exist and will write your name into it. You can also just edit the file directly yourself instead of using <code>git config</code> commands.</p>
<p>Like Subversion, committing will create a saved, fixed point-in-time that marks the changes you have made to your files. Like branches, commits are also very cheap in git, so go ahead and commit at any time you like. Remember to stage your files (by <code>git add</code>ing them), and then just <code>git commit</code>.</p>
<pre><kbd>git add <var>filepattern</var></kbd>
<kbd>git commit -m "My very frst git commit!"</kbd>
<samp>Created commit ef483c1: My very frst git commit!
 5 files changed, 58 insertions(+), 12 deletions(-)</samp></pre>
<p>If you forget to specify a commit log message (<code>-m "log message"</code>) on the command line, or if you want to enter a multi-line commit log, git will prompt you for it in your favorite <code>$EDITOR</code>. You can view a history, including all the log messages, for your project with <code>git log</code>. You can even the view logs in a number of pretty formats. Check <code>git help log</code> for more information.</p>
<p>If you want to change anything about the commit you just made, such as the author, you can just run <code>git commit</code> again with the <code>--amend</code> flag added to the command. Notice the typo in the commit log? Fixing it is really easy:</p>
<pre><kbd>git commit --amend -m "My very first git commit!"</kbd>
<samp>Created commit 88602f6: My very first git commit!
 5 files changed, 58 insertions(+), 12 deletions(-)</samp></pre>
<p>Finally, with your new code commited to your local git branch, it&#8217;s time to share that code with your colleagues who are (for some inexplicable reason) still using Subversion. This is also extremely simple. Just say <code>git svn dcommit</code>. (That&#8217;s right, <code><strong>d</strong>commit</code>, not just commit. I don&#8217;t know why….)</p>
<p>Not sharing your changes via Subversion, but with a patch instead? <code>git diff -p</code> will generate patches for you. See <code>git help diff-files</code> and look for the &#8220;GENERATING PATCHES WITH -P&#8221; section.</p>
<p>If you found this helpful, you may also enjoy an <a href="//cworth.org/hgbook-git/tour/">alternative tour for beginners from Carl Worth</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/03/28/howto-use-git-for-personal-development-when-everyone-else-is-using-subversion-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HowTo: Use git for personal development when everyone else is using Subversion (part 1)</title>
		<link>http://maymay.net/blog/2008/03/26/howto-use-git-for-personal-development-when-everyone-else-is-using-subversion-part-1/</link>
		<comments>http://maymay.net/blog/2008/03/26/howto-use-git-for-personal-development-when-everyone-else-is-using-subversion-part-1/#comments</comments>
		<pubDate>Wed, 26 Mar 2008 06:54:57 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/2008/03/26/howto-use-git-for-personal-development-when-everyone-else-is-using-subversion-part-1/</guid>
		<description><![CDATA[Let&#8217;s just jump into it. Using Mac OS X, first make sure you have the git core installed as well as the git-svn components. Unlike other version control systems, git is not one monolithic program but a collection of smaller utilities, and the Subversion conduits are a subset of these utilities. The git-Subversion utilities themselves [...]]]></description>
			<content:encoded><![CDATA[<p>Let&#8217;s just jump into it.</p>
<p>Using Mac <acronym title="Operating System">OS</acronym> X, first make sure you have the git core installed as well as the git-svn components. Unlike other version control systems, git is not one monolithic program but a collection of smaller utilities, and the Subversion conduits are a subset of these utilities. The git-Subversion utilities themselves depend on having the <code>Perl::Subversion</code> bindings installed for Perl 5.</p>
<p>For the lazy MacPorts user, simply run:</p>
<pre>sudo port install git-core +svn</pre>
<p>This will install the git-core, the git-svn packages, as well as all the documentation for git and any required dependencies you don&#8217;t already have. Note that the documentation (man pages) is installed in <code>/opt/local/man</code>, which may not be in your default <code>$MANPATH</code>, so be sure to add that directory if <code>man git</code> returns a &#8220;No manual entry for git&#8221; error.</p>
<p>Alternatively, if you don&#8217;t want to use MacPorts, you can <a href="//git.or.cz/#download">download a pre-compiled Mac <acronym title="Operating System">OS</acronym> X binary</a> that includes git, the git docs, and the git-svn package from the git web site that comes complete with a standard <acronym title="Graphical User Interface">GUI</acronym> installation procedure.</p>
<p>Next, initialize a new git repository that tracks a remote Subversion one. This allows you to work privately using git, but to collaborate with other people who are using Subversion. Running</p>
<pre>git svn init svn://my.svn.server/path/to/svn/repo <var>workingcopy</var></pre>
<p>will give you an empty git working copy named <var>workingcopy</var> configured to use the remote Subversion repository at <var>svn://my.svn.server/path/to/svn/repo</var>. This step is analogous to the need to run <code>svnadmin create <var>repo_db</var></code>, to initialize a new repository database (where all the file versioning information will be stored). Unlike Subversion, git&#8217;s distributed database means that the working copy itself is <em>also</em> the location of the repository database, so there&#8217;s no need to deal with two filesystem paths anymore.</p>
<p>Next, change directory to your working copy, and run</p>
<pre>cd <var>workingcopy</var>
git svn fetch</pre>
<p>to populate your new, empty git working copy (and repository) with all the files from the remote Subversion repository.</p>
<p>Now that you have filled your git repository with a lot of data, <e>if you want to</em>, you can now also save a significant chunk of disk space by repacking that data into a more single, efficient, native packed git archive format (a <code>.pack</code> file). The <code>git-repack -a</code> command is used to do this, and its manual page says:</p>
<blockquote><p>Instead of incrementally packing the unpacked objects, pack everything referenced into a single pack. Especially useful when packing a repository that is used for private development and there is no need to worry about people fetching via dumb protocols from it.</p></blockquote>
<p>According to <a href="//utsl.gen.nz/talks/git-svn/intro.html#howto-fetch-convert" title="An introduction to git-svn for Subversion/SVK users and deserters">some sources</a>, this can turn a <acronym title="353 Megabyte(s)">353MB</acronym> Subversion repository into <acronym title="31 Megabyte(s)">31MB</acronym> of git pack. Say:</p>
<pre><kbd>git repack -a -d -f</kbd>
<samp>Generating pack...
Counting objects: 284
Done counting 4475 objects.
Deltifying 4475 objects...
 100% (4475/4475) done
Writing 4475 objects...
 100% (4475/4475) done
Total 4475 (delta 1876), reused 0 (delta 0)
Pack pack-a115c320ff9c9968248bd250bdfea3110d0f0c1a created.
Removing unused objects 100%...
Done.
</samp></pre>
<p>to perform the compression. For even greater savings, increase the compression by stipulating a high <code>--window</code> option, such as <code>git repack -a -d -f --window=100</code>. (<code>--window</code> defaults to 10—the higher the window, the harder <code>git-repack</code> will try to compress your stuff.) This turned a <acronym title="36 Megabyte(s)">36MB</acronym> Subversion repository in one of my projects to a <acronym title="20 Megabyte(s)">20MB</acronym> git pack. As always, your mileage may vary.</p>
<p>Congratulations, you have transformed your old Subversion repository to a git repository. All that&#8217;s left to do now is to get to the coding. Perhaps start by making a local (cheaper than cheap!) git branch….</p>
<p>That was easy, right? Most things in git are, in fact, that easy. If you&#8217;ve never used other version control systems before, be grateful. If you have, you can breathe a sigh of relief. Still not convinced? Don&#8217;t take my word for it…<a href="//video.google.com/videoplay?docid=-2199332044603874737">ask Linus Torvalds</a> (or <a href="//video.google.com/videoplay?docid=-3999952944619245780">Randall Schwartz</a>).</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/03/26/howto-use-git-for-personal-development-when-everyone-else-is-using-subversion-part-1/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>No-Framework Ruby on the Web using eRuby on Mac OS X</title>
		<link>http://maymay.net/blog/2007/10/25/no-framework-ruby-on-the-web-using-eruby-on-mac-os-x/</link>
		<comments>http://maymay.net/blog/2007/10/25/no-framework-ruby-on-the-web-using-eruby-on-mac-os-x/#comments</comments>
		<pubDate>Thu, 25 Oct 2007 05:00:16 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[Web Design]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/archives/2007/10/25/no-framework-ruby-on-the-web-using-eruby-on-mac-os-x/</guid>
		<description><![CDATA[I have a suspicion that there are a lot of web developers out there who, like me, are eager to start learning more about Ruby but who are stunted by the incredible amount of unfamiliar conventions that are used in Rails. For many of us, our first introduction to Ruby was (or is) through Rails [...]]]></description>
			<content:encoded><![CDATA[<p>I have a suspicion that there are a lot of web developers out there who, like me, are eager to start learning more about <a href="//ruby-lang.org/">Ruby</a> but who are stunted by the incredible amount of unfamiliar conventions that are used in <a href="//rubyonrails.com/">Rails</a>. For many of us, our first introduction to Ruby was (or is) through Rails and the challenge of learning <em>both</em> Ruby and Rails at once should not be underestimated; frankly it&#8217;s damn hard.</p>
<p>Thankfully, there&#8217;s an easier way. Especially if you&#8217;re accustomed to &#8220;old-school&#8221; development workflows that you learned through, say, <acronym title="PHP Hypertext Preprocessor; an HTML-embedded scripting language">PHP</acronym> or perhaps Perl scripting, then ditching Rails and starting purely with Ruby might be the way to go. Doing things on your own without the &#8220;magic&#8221; of Rails will let you learn Ruby in a simple, yet fully-featured environment, much like the way you might have learned classic <acronym title="Common Gateway Interface">CGI</acronym> programming.</p>
<p>Specifically, by using <a href="//eruby.info/">eRuby</a>, the Embedded Ruby interpreter, you can make Ruby web development feel just like <acronym title="PHP Hypertext Preprocessor; an HTML-embedded scripting language">PHP</acronym> development. Install it, upload an <acronym title="HyperText Markup Language">HTML</acronym> file with some embedded Ruby code in it, and—voila—you have a single-page web application.</p>
<h3>Why this tutorial?</h3>
<p><a href="http://www.hiveminds.co.uk/node/3094">Hivemind&#8217;s Getting Started with Ruby on the Web</a> is an excellent resource that described this process from start-to-finish for Windows users. In fact, it was after finding that article that I realized web development with Ruby didn&#8217;t have to be governed by Rails and, being a web developer like the authors of <cite>Hiveminds</cite>, I wanted an easy way to use my Ruby knowledge on the Web.</p>
<p>However, I couldn&#8217;t find any similar tutorial or walkthrough for those of us who use Macs. Even the Linux walkthroughs are lacking (or at least my Googling skill for them is). After spending a little while successfully getting eRuby set up on my Mac running Mac <acronym title="Operating System">OS</acronym> X 10.4 Tiger, I thought I&#8217;d share what I learned with others, so I wrote this article. Its content mirrors the one from Hiveminds to a great degree but focuses on getting eRuby installed on Mac <acronym title="Operating System">OS</acronym> X instead of Windows (obviously). I imagine these instructions should be pretty similar if not identical for any other *nix-like platform.</p>
<h3>The Setup</h3>
<p>Getting eRuby installed and configured with your web server is actually pretty straightforward and won&#8217;t take an experienced web developer much time at all. All we&#8217;re going to need is the <a href="//httpd.apache.org/">Apache web server</a> and the <a href="//ruby-lang.org/">Ruby programming language</a> to start, both of which are already pre-installed on Mac <acronym title="Operating System">OS</acronym> X 10.4 Tiger. (And in Mac <acronym title="Operating System">OS</acronym> X 10.5 Leopard, Apple is even <a href="/blog/archives/2007/10/18/the-10-geekiest-leopard-features-i-will-probably-love/#li-1">shipping new Macs with Ruby On Rails preconfigured</a>, but that&#8217;s a subject for another time.) However, Apple typically ships an older copy of Ruby than is readily available, so you might choose to use a newer version of Ruby that you download yourself.</p>
<p>The easiest way to get a copy of eRuby (and an updated Ruby, if you want it) is with a package manager such as <a href="//macports.org/">MacPorts</a>. With MacPorts installed (which is a simple, standard package installation downloadable from the MacPorts home page), simply run</p>
<pre><kbd>sudo port install eruby</kbd></pre>
<p>from your terminal to download the latest stable Ruby and eRuby in one fell swoop. After this runs, you&#8217;ll have a new Ruby in <code>/opt/local/bin/ruby</code> and an eRuby in <code>/opt/local/bin/eruby</code>. Alternatively, of course, you could compile and install eRuby yourself. <a href="//eruby.info/" title="Scroll to the 'How do I get eRuby?' section.">Instructions for that</a> are on the eRuby homepage.</p>
<p>As a quick test to see if everything is installed and working correctly, create a plain text file with your favorite editor that contains the following code:</p>
<pre><code class="ruby">Hello world! The time is now &lt;%= Time.now %&gt;.</code></pre>
<p>All this does is print out a &#8220;Hello world!&#8221; greeting and then announces the current time (as reported by your system clock, of course).</p>
<p>If you named the above file <var>helloworld.rhtml</var> then you can feed this file to the <code>eruby</code> interpreter as follows:</p>
<pre><kbd>eruby helloworld.rhtml</kbd></pre>
<p>Note that the file extension doesn&#8217;t actually matter. You could use <code>.erb</code>, if you like, or any other arbitrary file extension. The file extension is, as you&#8217;ll see later, only used for telling Apache which kind of file it is. So once you come up with file extension you like, stick with it. The standard file extensions are either <code>.rhtml</code> or <code>.erb</code>, so I&#8217;d recommend using one of those. (I prefer <code>.erb</code>, myself, since I don&#8217;t necessarily only want to create <acronym title="HyperText Markup Language">HTML</acronym> pages. I might want to create <acronym title="eXtensible Markup Language">XML</acronym> documents like news feeds or even <acronym title="eXtensible Markup Language">XML</acronym> databases, so <code>.erb</code> seems a more reasonable file name extension, though most of the eRuby documentation uses <code>.rhtml</code>.)</p>
<p>If things worked properly, you should see output similar to the following:</p>
<pre><samp class="plaintext">Hello world! The time is now Wed Oct 24 21:58:54 -0400 2007.</samp></pre>
<h3>Serve it up!</h3>
<p>Now that eRuby is installed and working, the next step is to set it up as a <acronym title="Common Gateway Interface">CGI</acronym> so that when your web server (Apache, in my case) fetches the file it will first feed it through eRuby for processing before sending it back to the browser. The simplest way to do this is to configure Apache to use a specific directory somewhere on your filesystem as a <acronym title="Common Gateway Interface">CGI</acronym> directory—that is, a directory whose contents are all treated as <acronym title="Common Gateway Interface">CGI</acronym> programs. You do this via Apache&#8217;s <a href="//httpd.apache.org/docs/1.3/mod/mod_alias.html#scriptalias" title="Documentation for Apache's ScriptAlias directive."><code>ScriptAlias</code></a> directive.</p>
<p>Conveniently, standard installations of Mac <acronym title="Operating System">OS</acronym> X already come with a <acronym title="Common Gateway Interface">CGI</acronym> directory. It&#8217;s located at <code>/Library/WebServer/CGI-Executables</code>. This directory is just like any other, except that Apache treats it specially. It treats it specially because Apache&#8217;s configuration file, <code>/etc/httpd/httpd.conf</code> contains a line of text that reads as follows. (On a standard installation of Mac <acronym title="Operating System">OS</acronym> X client, this is line 671 of the file.)</p>
<pre><code class="httpd-conf">ScriptAlias /cgi-bin/ "/Library/WebServer/CGI-Executables/"</code></pre>
<p>This line basically just tells apache, &#8220;Treat every file in the <code>/Library/WebServer/CGI-Executables</code> directory as though it were a <acronym title="Common Gateway Interface">CGI</acronym> program.&#8221; So, since that&#8217;s how we&#8217;re treating eRuby, we&#8217;re going to want to put our <code>eruby</code> binary in that directory. However, we don&#8217;t actually want to make copies of the binary. Having too many copies of a program on your system can easily get confusing. So instead, we&#8217;ll make a symbolic link (or an alias to use the classic Mac terminology) to the binary.</p>
<pre><kbd>ln -s /opt/local/bin/eruby /Library/WebServer/CGI-Executables/eruby</kbd></pre>
<p>With our <code>eruby</code> <acronym title="Common Gateway Interface">CGI</acronym> executable in the proper place for Apache to find it, we can now tell Apache which files we want it to send to this program. We do this using the <a href="//httpd.apache.org/docs/1.3/mod/mod_mime.html#addhandler" title="Documentationf or Apache's AddHandler directive."><code>AddHandler</code></a> and <a href="//httpd.apache.org/docs/1.3/mod/mod_actions.html#action" title="Documentation for Apache's Action directive."><code>Action</code></a> directives.</p>
<p><code>AddHandler</code> simply tells Apache to treat files with a certain extension in a certain way. For instance, you can say something like, &#8220;Treat all files ending in <code>.php</code> as <acronym title="PHP Hypertext Preprocessor; an HTML-embedded scripting language">PHP</acronym> scripts.&#8221; Similarly, you can (and will) tell Apache, &#8220;Treat all files ending in <code>.rhtml</code> or <code>.erb</code> as eRuby <acronym title="Common Gateway Interface">CGI</acronym> pages.&#8221;</p>
<p>To do this, we add the following line to our <code>/etc/httpd/users/<var>username</var>.conf</code> file somewhere inside the <code>&lt;Directory&gt;</code> and <code>&lt;/Directory&gt;</code> block. Naturally, replace <var>username</var> with, of course, your <a href="//docs.info.apple.com/article.html?artnum=106824" title="Apple KBase Article number 106824 describes use short names in more detail.">Mac <acronym title="Operating System">OS</acronym> X user&#8217;s short name</a>:</p>
<pre><code class="httpd-conf">AddHandler rubypage .erb .rhtml</code></pre>
<p>Again, this just tells Apache that files ending in <code>.erb</code> and <code>.rhtml</code> should be treated the same way other <code>rubypage</code>s are treated. But how are eRuby pages supposed to be treated? They&#8217;re supposed to be handed off to the eRuby program, of course, so we need an <code>Action</code> directive that applies to the <code>rubypage</code> handler we just defined.</p>
<p>Right below the above line, add the following line, too:</p>
<pre><code class="httpd-conf">Action rubypage /cgi-bin/eruby</code></pre>
<p>This line tells Apache that any file that it is treating as a &#8220;rubypage&#8221; file should be sent to the program at the <acronym title="Uniform Resource Locator">URL</acronym> accessible at <code>/cgi-bin/eruby</code>, which we&#8217;ve defined earlier to be our symbolic link to the <code>eruby</code> interpreter.</p>
<p>Your completed user-specific Apache configuration file should now look something like this:</p>
<pre><code class="httpd-conf">&lt;Directory "/Users/<var>username</var>/Sites/"&gt;
&hellip;
    # Let eRuby files get parsed through the proper <acronym title="Common Gateway Interface">CGI</acronym> binary
    AddHandler rubypage .erb .rhtml
    Action rubypage /cgi-bin/eruby
&lt;/Directory&gt;</code></pre>
<h3>Are You Being Served?</h3>
<p>That&#8217;s it, everything should now be in place. To make sure, move your earlier <code>helloworld.rhtml</code> file into your user&#8217;s <code>Sites</code> folder, and now simply point your browser to <code>http://localhost/~<var>username</var>/helloworld.rhtml</code> (again, replacing <var>username</var> with your Mac <acronym title="Operating System">OS</acronym> X user short name, of course). Congratulations, you&#8217;re serving up Ruby-coded applications via eRuby.</p>
<h3>Additional Reading</h3>
<p>This is just the set up, of course. Now the real fun begins: learning Ruby. Here are some suggested places to start.</p>
<ul>
<li><a href="//www.ruby-doc.org/docs/ProgrammingRuby/html/web.html">Programming Ruby: Ruby and the Web</a> — A chapter out of the free book <cite>Programming Ruby</cite> all about Ruby as a <acronym title="Common Gateway Interface">CGI</acronym> programming language.</li>
<li><a href="//hiveminds.co.uk/node/3189">Hiveminds: eRuby: How to use Ruby <acronym title="Common Gateway Interface">CGI</acronym> and ERB templating for Web Pages</a> — a quick&#8217;n'dirty article explaining the basics of using Ruby on web pages in classic <acronym title="Common Gateway Interface">CGI</acronym> style where program logic and <acronym title="HyperText Markup Language">HTML</acronym> templates are kept separated, as opposed to classic <acronym title="PHP Hypertext Preprocessor; an HTML-embedded scripting language">PHP</acronym> style, where the two are mingling together on one page.</li>
<li><a href="//coolnamehere.com/geekery/ruby/web/cgi.html">COOLNAMEHERE: Simple Ruby <acronym title="Common Gateway Interface">CGI</acronym></a> — Like the Hiveminds example above, another quick&#8217;n'dirty Ruby <acronym title="Common Gateway Interface">CGI</acronym> how-to.</li>
<li><a href="//ruby-doc.org/stdlib/libdoc/cgi/rdoc/index.html">cgi: Ruby Standard Library Documentation</a> — Ruby&#8217;s standard library contains a rich set of features, and the <acronym title="Common Gateway Interface">CGI</acronym> objects are among them. They are well-documented in the official Ruby Documentation Project.</li>
</ul>
<p>Naturally, feel free to leave comments if you have more resources that you found helpful.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2007/10/25/no-framework-ruby-on-the-web-using-eruby-on-mac-os-x/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>How to Make WordPress-generated Pages Outside the WordPress Install Directory</title>
		<link>http://maymay.net/blog/2004/10/22/how-to-make-wordpress-generated-pages-outside-the-wordpress-install-directory/</link>
		<comments>http://maymay.net/blog/2004/10/22/how-to-make-wordpress-generated-pages-outside-the-wordpress-install-directory/#comments</comments>
		<pubDate>Sat, 23 Oct 2004 00:26:28 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">/?p=95</guid>
		<description><![CDATA[I wanted to use my blog entries, created in WordPress to generate content for pages on my site that were not in my blog. This seemed simple enough, and it is, but without some guidance this can be a really confusing situation. While WordPress supports a pseudo-templating system that can be used to easily customize [...]]]></description>
			<content:encoded><![CDATA[<p>I wanted to use my blog entries, created in WordPress to generate content for pages on my site that were <em>not</em> in my blog. This seemed simple enough, and it is, but without some guidance this can be a really confusing situation. While WordPress supports a pseudo-templating system that can be used to easily customize the look and feel of a WordPress blog, getting that blog-portion of the site to play nice with the other parts of a site (or the converse, as the case may be) is often not as easy as it seems.</p>
<p>I believe this is one of the reasons why WordPress&#8217;s popularity has not yet reached its enormous potential.</p>
<p>But without further ado, here&#8217;s what I did to get WordPress to generate pages in a directory completely outside WordPress&#8217;s own installation directory.</p>
<h2>The Solution</h2>
<p>The solution involves replacing all occurences of WordPress&#8217;s erroneous absolute link-creation output and replace it with output appropriate to the <code>/newsection</code> structure. This was done with <acronym title="PHP Hypertext Preprocessor; an HTML-embedded scripting language">PHP</acronym>&#8216;s output buffering. Then, to make it work with the permalink structure, I made some edits to the WordPress-generated <code>RewriteRule</code>s. In the hopes that this will be of use to someone, here&#8217;s what I did:</p>
<ol>
<li>
<p>In the top of your new section&#8217;s template (/newsection/index.php), following the line with the <code>require()</code> statement, put a new line that reads:</p>
<pre>ob_start();</pre>
<p>This will start the output buffer.</p>
</li>
<li>
<p>At the very bottom of your template, after the <code>&lt;/html&gt;</code> add the following lines:</p>
<pre>&lt;?php
&#036;page_content = ob_get_contents();
&#036;replace_this = 'href="http://mysite.com/blog';
&#036;with_this = 'href="http://mysite.com/newsection';
&#036;modified_page_content = str_replace(&#036;replace_this, &#036;with_this, &#036;page_content);
ob_end_clean();
echo &#036;modified_page_content;
?&gt;</pre>
<p>These do the replacements you need. Obviously, change the <code>mysite.com</code> to whatever your site domain is, change the <code>/blog</code> to whatever path your WordPress install is at, and change the <code>/newsection</code> to the path of the new section you&#8217;re creating.</p>
<p>With these lines wrapped around your template, you can use all of WordPress&#8217;s original template tags like <code>the_permalink()</code> and <code>wp_list_cats()</code> just as you would if you were using them in the original section.</p>
<p><strong>Note to regex wizards:</strong> this is obviously a <em>very</em> crude string replacement, and I don&#8217;t know how well it will work in situations not like my own. I&#8217;m not very good with regular expressions, however, so if you can think of one that would work better with <code>preg_replace()</code> please let me know.</p>
</li>
<li>
<p><strong>If you&#8217;re using WordPress&#8217;s virtual site structure (pretty-permalinks):</strong> Copy the rules WordPress wrote for you at Options->Permalinks (or from your existing <code>.htaccess</code> file) and paste them into a new text document. This will become your new section&#8217;s <code>.htaccess</code> file.</p>
<ol>
<li>
<p>In the line that begins with <code>RewriteBase</code> replace the old base with the new base path to your section. If the line read <code>RewriteBase /blog/</code> then you would replace <code>/blog/</code> with <code>/newsection/</code>.</p>
</li>
<li>
<p>Finally, for the second, third, and fourth lines that begins with <code>RewriteRule</code> replace the old actual path with the actual path to your new section. So, continuing the example above, if you have a line that reads like this,</p>
<pre>RewriteRule ^category/?(.*) /blog/index.php?category_name=&#036;1 [QSA]</pre>
<p>replace it with this:</p>
<pre>RewriteRule ^category/?(.*) /newsection/index.php?category_name=&#036;1 [QSA]</pre>
</li>
<li>
<p>Save this file as a new <code>.htaccess</code> file and upload it to your server so that it resides at <code>http://mysite.com/newsection/.htaccess</code></p>
</li>
</ol>
</li>
</ol>
<p>No matter what section/directory of your site you&#8217;re putting WordPress templates in, you can use this method to point links to the current section, and thus load WordPress content in the templates within that section/directory. One important caveat to this method is that every time a template using this method is accessed, your server works a little over-time to do the <code>str_replace()</code> on your content. This won&#8217;t be noticeable on small or short pages, but could really become an issue on oft-visited, long, long pages. As always, use at your own risk.</p>
<p>Improvements/warnings/suggestions/hate mail are welcome.</p>
<h2>External Resources</h2>
<ul>
<li>The <a href="http://wordpress.org/support/3/15291">original support forum thread.</a></li>
<li>The <a href="http://wiki.wordpress.org/HowTo/UseTemplatesInAnyDirectory">Wiki HowTo node</a> I wrote.</li>
<li><a href="http://developedtraffic.com/resources/wordpress-notes.php">WordPress Customization Notes.</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2004/10/22/how-to-make-wordpress-generated-pages-outside-the-wordpress-install-directory/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Make Marked-Up Lists Look Like Paragraph Text</title>
		<link>http://maymay.net/blog/2004/10/06/make-marked-up-lists-look-like-paragraph-text/</link>
		<comments>http://maymay.net/blog/2004/10/06/make-marked-up-lists-look-like-paragraph-text/#comments</comments>
		<pubDate>Wed, 06 Oct 2004 21:03:58 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HOWTO]]></category>

		<guid isPermaLink="false">/?p=66</guid>
		<description><![CDATA[Here&#8217;s a useful little snippet of CSS2 lifted straight off a personal project I&#8217;ve been working on. The following four rules display, find, and insert appropriate punctuation for making unordered lists read like English prose. ul, ul li { display: inline; list-style: none; margin: 0; padding: 0; } li:after { content: ", "; } li:last-child:after [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a useful little snippet of <acronym title="Cascading Style Sheets level 2">CSS2</acronym> lifted straight off a personal project I&#8217;ve been working on. The following four rules display, find, and insert appropriate punctuation for making unordered lists read like English prose.</p>
<pre>ul, ul li {
    display: inline; list-style: none; margin: 0; padding: 0;
}
li:after { content: ", "; }
li:last-child:after { content: "."; }
li+li:last-child:before { content: "and "; }
</pre>
<p>Here&#8217;s what&#8217;s happening.</p>
<ol>
<li>First they display the entire list and each list item as an inline element. This causes them to show up right up against any other text around them.</li>
<li>Then they add a comma and a space after each list item.</li>
<li>The last list item, however, gets a period and no space.</li>
<li>Finally, the word &ldquo;and&rdquo; followed by a space is inserted before the last list item if, and only if, there is a list item before it (it has a sibling).</li>
</ol>
<p>There you have it. List markup that looks just like a normal paragraph, complete with proper punctuation! A great little tip that makes lists a whole lot more flexible!</p>
<p>Note that as of this writing this won&#8217;t work in Internet Explorer because it can&#8217;t understand the last three rules. Since it does understand the first, the result will merely be an inline box for the whole list, sans punctuation.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2004/10/06/make-marked-up-lists-look-like-paragraph-text/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

