How to migrate a CVS module to Git and GitHub

Since it took me a while to figure out, I figured this might be useful to document: migrating code from CVS to Git. Specifically, I was moving modules in a CVS repository on SourceForge over to GitHub.

Here are the versions of the tools that I used:

$ rsync --version | head -1
rsync version 3.1.0 protocol version 31
$ cvs --version | head -2 | tail -1
Concurrent Versions System (CVS) 1.12.13 (client/server)
$ git --version
git version 2.6.3
$ cvsps -V
cvsps: version 3.13

First, I grabbed a copy of the CVSROOT, and checked out the module so I had a reference copy to compare to when I’m done.

$ rsync -av aolserver.cvs.sourceforge.net::cvsroot/aolserver/ aolserver-cvs
$ cvs -d $(pwd)/aolserver-cvs co -d nsmysql-cvs nsmysql

Then, I create the working directory for the local git repo.

$ mkdir nsmysql
$ git init nsmysql

Next, do the actual CVS-to-Git conversion.

$ cvsps --root $(pwd)/aolserver-cvs nsmysql --fast-export | git --git-dir=nsmysql/.git fast-import

Finally, do a diff to compare the two working directories to make sure the import worked correctly.

$ cd nsmysql
$ git checkout master
$ diff -x .git -x CVS -urN . ../nsmysql-cvs

If everything looks good, go ahead and push it up to GitHub.

$ git remote add origin git@github.com:aolserver/nsmysql.git
$ git config remote.origin.push HEAD
$ git push -u origin master

I don’t do this often, but when I do, I always have to figure it out each time, so hopefully next time I’ll find this blog post at the top of my search results and save myself some time.

MySQL Geo Distance Code and Samples

Over the years, I’ve implemented and re-implemented the haversine formula whenever I’ve needed to compute great-circle distances, which is pretty common when you’re doing geospatial proximity searches, e.g., “What’s near me?” or “How far are these two locations from each other?”

For an implementation of the formula in MySQL, Alexander Rubin’s presentation is quite useful, and is what I’ve based the following code on this time around.

Hopefully, rather than re-implementing this yet again the next time I need it, I’ll find my own blog entry on it and just reuse this code. I keep forgetting where I’ve stashed the most recent copy, which is why I keep ending up re-implementing this every time I’ve needed it.

Here’s the code, tested on MySQL 5.1.41:

DELIMITER $$

DROP FUNCTION IF EXISTS geodist $$
CREATE FUNCTION geodist (
  src_lat DECIMAL(9,6), src_lon DECIMAL(9,6),
  dst_lat DECIMAL(9,6), dst_lon DECIMAL(9,6)
) RETURNS DECIMAL(6,2) DETERMINISTIC
BEGIN
  SET @dist := 3956 * 2 * ASIN(SQRT(
      POWER(SIN((src_lat - ABS(dst_lat)) * PI()/180 / 2), 2) +
      COS(src_lat * PI()/180) *
      COS(ABS(dst_lat) * PI()/180) *
      POWER(SIN((src_lon - dst_lon) * PI()/180 / 2), 2)
    ));
  RETURN @dist;
END $$

DROP FUNCTION IF EXISTS geodist_pt $$
CREATE FUNCTION geodist_pt (src POINT, dst POINT) 
RETURNS DECIMAL(6,2) DETERMINISTIC
BEGIN
  RETURN geodist(Y(src), X(src), Y(dst), X(dst));
END $$

DROP PROCEDURE IF EXISTS geobox $$
CREATE PROCEDURE geobox (
  IN src_lat DECIMAL(9,6), IN src_lon DECIMAL(9,6), IN dist DECIMAL(6,2),
  OUT lat_top DECIMAL(9,6), OUT lon_lft DECIMAL(9,6),
  OUT lat_bot DECIMAL(9,6), OUT lon_rgt DECIMAL(9,6)
) DETERMINISTIC
BEGIN
  /*
   * src_lat, src_lon -> center point of bounding box
   * dist -> distance from center in miles
   * lat_top, lon_lft -> top left corner of bounding box
   * lat_bot, lon_rgt -> bottom right corner of bounding box
   */
  SET lat_top := src_lat - (dist / 69);
  SET lon_lft := src_lon - (dist / ABS(COS(RADIANS(src_lat)) * 69));
  SET lat_bot := src_lat + (dist / 69);
  SET lon_rgt := src_lon + (dist / ABS(COS(RADIANS(src_lat)) * 69));
END $$

DROP PROCEDURE IF EXISTS geobox_pt $$
CREATE PROCEDURE geobox_pt (
  IN pt POINT, IN dist DECIMAL(6,2),
  OUT top_lft POINT, OUT bot_rgt POINT
) DETERMINISTIC
BEGIN
  /*
   * pt -> center point of bounding box
   * dist -> distance from center in miles
   * top_lft -> top left corner of bounding box
   * bot_rgt -> bottom right corner of bounding box
   */
  CALL geobox(Y(pt), X(pt), dist, @lat_top, @lon_lft, @lat_bot, @lon_rgt);
  SET top_lft := POINT(@lon_lft, @lat_top);
  SET bot_rgt := POINT(@lon_rgt, @lat_bot);
END $$

DROP PROCEDURE IF EXISTS geobox_pt_bbox $$
CREATE PROCEDURE geobox_pt_bbox (
  IN pt POINT, IN dist DECIMAL(6,2), OUT bbox POLYGON
) DETERMINISTIC
BEGIN
  /*
   * pt -> center point of bounding box
   * dist -> distance from center in miles
   * bbox -> bounding box, dist miles from pt
   */
  CALL geobox_pt(pt, dist, @top_lft, @bot_rgt);
  SET bbox := Envelope(LineString(@top_lft, @bot_rgt));
END $$

DELIMITER ;

And, here’s examples on how to use the above function and procedures:

SELECT @src := pt FROM exp_geo
WHERE postal_code = '07405' AND city = 'Butler';

CALL GEOBOX_PT(@src, 10.0, @top_lft, @bot_rgt);
SELECT Y(@top_lft) AS lat_top, X(@top_lft) AS lon_lft,
       Y(@bot_rgt) AS lat_bot, X(@bot_rgt) AS lon_rgt;

CALL GEOBOX_PT_BBOX(@src, 10.0, @bbox);
SELECT AsWKT(@bbox);

-- Assuming INDEX on (lat, lon) and SPATIAL INDEX on (pt) ...

-- Fast:
SELECT g.postal_code, g.city, g.state,
       GEODIST(Y(@src), X(@src), lat, lon) AS dist
FROM exp_geo g
WHERE lat BETWEEN Y(@top_lft) AND Y(@bot_rgt)
AND lon BETWEEN X(@top_lft) AND X(@bot_rgt)
HAVING dist < 5.0
ORDER BY dist;

-- Also fast:
SELECT g.postal_code, g.city, g.state, GEODIST_PT(@src, g.pt) AS dist
FROM exp_geo g
WHERE lat BETWEEN Y(@top_lft) AND Y(@bot_rgt)
AND lon BETWEEN X(@top_lft) AND X(@bot_rgt)
HAVING dist < 5.0
ORDER BY dist;

-- Slow:
SELECT g.postal_code, g.city, g.state, GEODIST_PT(@src, g.pt) AS dist
FROM exp_geo g
WHERE Y(pt) BETWEEN Y(@top_lft) AND Y(@bot_rgt)
AND X(pt) BETWEEN X(@top_lft) AND X(@bot_rgt)
HAVING dist < 5.0
ORDER BY dist;

-- Also slow:
SELECT g.postal_code, g.city, g.state, GEODIST_PT(@src, g.pt) AS dist
FROM exp_geo g
WHERE MBRContains(@bbox, pt) = 1
HAVING dist < 5.0
ORDER BY dist;

Normally, I try to explain the stuff I post, but this time I’m doing it for somewhat selfish reasons — so I don’t lose this work yet again. I’m just throwing this up here so Google will index it, so I can find it the next time I need it.

I suppose if you read this and have questions, please ask them in the comments below. I’ll do my best to answer, if I can.

Android USB tethering on Mac OS X

If you’ve got an Android-based phone, and want to do simple USB-based tethering on your Mac, you will find this guide useful. For reference, I performed this with the following equipment:

  • Samsung Captivate on at&t running custom Cognition 4.1.1 ROM.
  • MacOS X 10.6.6

The standard disclaimers apply here: follow these instructions at your own risk. This may void your warranty. Discontinue use if a rash develops.

Getting started: Preparing Android

All we need to do on Android is turn on “USB debugging” – do NOT fiddle with any of the “USB tethering” options or anything else. So, go into Settings > Applications > Development, and check the box next to “USB debugging.”

Android screenshots

After turning on “USB debugging” connect the device to your Mac using the USB cable.

Next, configure the Mac

After connecting the USB cable, your Mac should pop up a window saying that a device “SAMSUNG_Android” needs to be configured, like this:

Mac screenshot

This is a good sign. Click the “Network Preferences…” button, and find that device in your System Preferences’s “Network” section, which should look something like this:

Mac screenshot 1

The first thing to do is enter the values for this screen. Use the following settings:

Mac screenshot 2
  • Telephone Number: *99#
  • Account Name: wap@cingulargprs.com
  • Password: cingular1

Next, click on the “Advanced…” button towards the bottom right of the window. That should bring you to a screen that looks like this:

Mac screenshot 3

First, click on “Generic” and select “Samsung” for the vendor. Next, click on “Dialup” and select “GPRS (GSM/3G)” for the model. Enter in “wap.cingular” for the APN. Leave the CID as “1” which is the default. When everything is done, the window should now look like this:

Mac screenshot 4

Once that’s done, click “OK” which should bring you back to the previous screen. Next, click the “Apply” button to save all these settings.

Lets try connecting

At this point, you’re ready to try tethering! Go ahead and click on that “Connect” button. You should now see something like this:

Mac screenshot 5

If everything goes well, after 5-10 seconds, it should change to something that looks like this:

Mac screenshot 6

That’s it, now you’re tethered

Not terribly painful, no goofy software installation needed and hoops to jump through. And, here’s a speedtest for folks who are curious:

Speedtest

3.4 Mbit/s down, and 330 Kbit/s up on a 400ms ping isn’t fantastic, but it’s more than adequate for getting work done while out and about.

I hope you’ve found this guide useful and are happily tethered now. If you have any questions or comments, feel free to share them in the comments below!

Added on 2012-11-20: A reader named Art emailed me about HoRNDIS: a USB tethering driver for MacOS X. This may be useful for folks who are still interested in USB tethering on OSX.

Annoying change in MacOS X 10.5+ Samba clients

So, my friend Jason asked me:

Why are my MacOS X 10.5+ Samba clients ignoring the “force create mode” and “force directory mode” settings for the share on my Samba server?

He was trying to setgid the directory and force files and directories to be group writable (i.e., “force create mode = 02770” and “force directory mode = 02770“), so that different users creating files and directories on the same share volume that belong to the same group can all write to to them. However, his MacOS X 10.5+ clients were able to ignore these settings somehow.

Turns out, this is a known issue:

The summary is that as of MacOS X 10.5 Leopard, its Samba client uses CIFS UNIX extensions to manipulate permissions, which Samba servers currently don’t enforce restrictions specified by the older “mode” settings. The work-around is to disable these CIFS UNIX extensions on the Samba server by putting “unix extensions = off” in the [global] section of your smb.conf file.

Using MySQL Meta Data Effectively at ODTUG Kaleidoscope 2010

Since Oracle owns MySQL through its acquisition of Sun, more Oracle conferences are providing MySQL content. This past Oracle Development Tools User Group (ODTUG) Kaleidoscope 2010 conference from June 27 through July 1 had a whole dedicated track for MySQL.

Using MySQL Meta Data Effectively - title slide thumbnail

I was fortunate enough to have the opportunity to speak on MySQL metadata, titled “Using MySQL Meta Data Effectively“. Here’s the abstract:

This presentation discusses what MySQL meta data is available including the ‘mysql’ meta schema, the INFORMATION_SCHEMA (I_S) tables first introduced in MySQL 5.0 and extended in MySQL 5.1, storage engine specific INFORMATION_SCHEMA tables, as well as techniques for writing your own INFORMATION_SCHEMA plug-ins. MySQL also provides a number of SHOW commands that provide easily formatted presentation of MySQL meta data. Dossy Shiobara will also discuss some of the limitations and performance implications of the INFORMATION_SCHEMA.

Paper first page thumbnail

You can download the materials from my session here:

Looking for WordPress, Drupal or Joomla help?

Are you looking for help with your WordPress, Drupal or Joomla-based website? Having trouble customizing your theme? Need help installing or configuring a plugin? Would you like to have a custom plugin written to do something you need?

I’m once again looking for work, and in the meantime, I’d be happy to lend a hand to folks who need it. Let me know if you’ve got something you want me to take a look at for you, and we’ll work something out.

Ah, brain, you cruel mistress

So, I had grandiose plans of trying to post updates to the blog at least three times a week, every week, for the month of May. Uh, the last update before this one was April 28th. Basically, I blogged more the last week of April than I have the whole month of May, so far. What the heck happened?

I just don’t get it. It’s like my brain is sabotaging my plans! Why is it so hard for me to write things down? I have the same problem with writing documentation at work: I tend to think I write very well, but I just can’t commit words to paper, or in this case, an editing buffer. Tons of words, sentences, ideas, etc., flow through my brain at an incredible pace, but nothing wants to come out. I sit with my hands resting on the keyboard, but every time I move my fingers to type something, my brain stops me and I feel like what would have come out wasn’t the right thing to say.

***

Got a bit of the man-cave (the garage) cleaned up with the help of my Dad, and set up the bench grinder that my wife got me for Father’s day last year. Now I can sharpen all sorts of things, and buff and polish others, with ease — sure, the Dremel “does the job” but this just makes things so much easier and better. The table saw and miter saw are also stored in a better place that makes them easier to take out and use, and my Dad ran a new outlet to the post between the two cave openings (garage doors). All very useful things for DIY projects.

***

On May 7 and 8, I attended PICC’10 in New Brunswick, NJ. It was a really great, fun, two-day conference for IT professionals, primarily focused at system administrators.

The next conference I’m planning to attend is ODTUG Kaleidoscope 2010, June 27 to July 1, down in Washington, DC. I’ll probably only be there for two of the days. If you’re going to be there and want to meet up, let me know!

***

I set up a VMware guest with CentOS 5.4 x86_64 with EPEL 5, as my development sandbox for work, since that’s what they deploy on. It’s actually quite nice, not nearly as bad as I remember Redhat-based distributions being in the past.

***

I’ve set up a copy of CrowdFusion on my laptop, and plan to start working on a few plugins. I’m tired of dealing with crappy CMS‘es like Drupal or Joomla! but CrowdFusion is still quite “beta” in some ways. I figure if I can contribute here and there, the sooner I could propose it seriously in RFP responses and the happier I’d be. I’ll say this: as “beta” as it might be, CrowdFusion 2.0 is already better than Drupal or Joomla! at its core. Once a suitable collection of plugins are developed and tested, and a theme gallery is available and populated with attractive themes, there’ll be no reason to use anything else.

Getting ActiveState’s “teacup” working on MacOS X

ActiveState has created a Tcl Extension Archive tool called teacup which simplifies the installation of binary extensions to Tcl. It’s included with ActiveTcl, but if you’re using Tcl from MacPorts and want to use teacup, it’s fairly easy:

1. Download teacup for MacOS X

The teacup binary can be downloaded from this location:

Here is a direct link to the latest teacup binary. The file is named file.exe — simply rename that to teacup and put it in /usr/local/bin or another convenient place in your $PATH.

2. Create the installation repository

You will need an installation repository where teacup can store its data locally. The default location is /Library/Tcl/teapot and you can create it like this:

$ sudo teacup create
Repository @ /Library/Tcl/teapot
    Created

3. Patch MacPorts tclsh to handle teapot repositories

$ sudo teacup setup /opt/local/bin/tclsh
Looking at tcl shell /opt/local/bin/tclsh ...
  Already able to handle Tcl Modules.
  Already has the platform packages.
  Patching: Adding code to handle teapot repositories ...
Done

4. Link teacup to MacPorts tclsh

$ sudo teacup link make /Library/Tcl/teapot /opt/local/bin/tclsh
Ok

That’s it! You’re done. You should now be able to list available packages within TEA using teacup list and install them using sudo teacup install "packagename".

I’ve tested this on MacOS X 10.6.1 Snow Leopard with Tcl 8.5.7 from MacPorts.

Tags: , , , ,

D. J. Bernstein is legendary

I’ve been using djbdns and qmail for many years, specifically because after reviewing its code and comparing it to other possible alternatives, I objectively decided that these two pieces of software are superior in all aspects.

Lots of people have cast aspersions on D. J. Bernstein and his software, usually with emotional and irrational claims. Of course, most of these people can’t even read code well enough to understand what it does or how it does it. However, when you encounter the opinions of actual programmers, we all tend to share a similar but different opinion.

Today, Aaron Swartz put this into words better than I could: D. J. Bernstein is the greatest programmer in the history of the world. The money quote:

[…] djb

Disabling service updates on SA2 TiVo’s

I needed to re-enable service updates on my SA2 TiVo tonight and I’d forgotten how to toggle it after having disabled them when I first hacked my TiVo, and had a tough time finding the information so I figure I’ll post it to my blog so I’ll be able to find it again.

The key command is bootpage – use “bootpage -p /dev/hda” to see the current settings. Then, use “bootpage -P "..." /dev/hda” to change them. Specifically, change “upgradesoftware=false” to “upgradesoftware=true” or vice versa.

Tags: , ,