Archive for the ‘Coding’ Category

Updating Git to the Google Groups Git-OSX-Installer

Friday, September 19th, 2008

gitLogo_vert.gif

As I was reading my Git Book this morning I noted that I was on v1.5.4.3 on my laptop, and it just occurred to me to check what the latest version of Git really is. I liked that this guy made an installer package that worked great as a Universal app on 10.5 (Leopard), but how far behind was he?

Turns out, a little bit.

I found that he had released a v1.5.5.0 Universal for Leopard that fixed the syncing over http, I think, but then I went to the source, and Git is really on 1.6.0.2 (stable), and that's a more significant version jump. Also, I saw that the Google Groups Git-OSX-Installer was on 1.6.0.1, and while it was Intel-only, that's all I've got for Leopard. So that seemed like a good move to make.

The first package deposited a lot of things in /usr/local/bin and such, whereas the Google Groups package is in /usr/local/git and everything is hanging off there (for the most part, we'll get to the exceptions in a minute). This looked like a cleaner uninstall as well, should Apple decide in Snow Leopard (10.6) to add in Git like they did Subversion for 10.5.

So I figured out how to get rid of the old package. Go into it's Contents directory and there should be a file called Archive.pax.gz where all the files are packed together. We can get a look at them with:

  gzip -d < Contents/Archive.pax.gz | pax -v | awk '{ print $9 }'

and all the files will be listed. Nice. I made a script to clear it all out and ran it. I then installed the new Git 1.6.0.1 package and it went in well, but the git commands like git-svn weren't in the /usr/local/git/bin directory, so they weren't going to be seen by the command line. I suppose that's not what this guy's doing, and that makes me a little nervous, but I'll go with it for now.

In order to get the paths right, I had to modify the installed file /etc/paths.d/git to look like:

  /usr/local/git/bin
  /usr/local/git/libexec/git-core

and then make use of the fact that in OS X 10.5, Leopard, the directories /etc/paths.d and /etc/manpaths.d are set up to take files listing directories to add to their respective paths if you know how to use it. So I added to my !/.tcshrc the lines:

  #
  # First, let's pick up all the paths from the system
  #
  if (-x /usr/libexec/path_helper) then
    eval `/usr/libexec/path_helper`
  endif

and we'll get the directories added to the path.

I then set up my Git global environment so that I should be ready to start working with it. I added my name and email... set up to use the colors on the commands... set up the ignore file... that kind of stuff. Nothing necessary, but all nice things to do before starting to use the tool. I think I'm ready.

Note: I like this logo for Git more as it seems to say to me the adding and deleting as well as the cycling nature of source control. And at the same time, like an emoticon, turn your head sideways and it's "Git". Sweet. Clever cats, these guys.

UPDATE: Interesting... it seems that as I read more, the commands like git-svn are really simply alternative ways of calling git commands directly. For example, git-svn is a direct command for git svn (no hyphen). This means that the Google Groups installer was right and I didn't need to add the /usr/local/git/libexec/git-core/ directory to my path! Very interesting. However, as you can imagine, if you want to call git-svn directly, then you need this directory in your path.

I've decided that the book I'm reading does not use the hyphenated commands, so I'm going to leave the install as-is and that's a big load off. It means that the guys building it are thinking the same as the author, and that's the kind of consistency I need in learning a tool like this.

Realizing What’s Important to Me

Thursday, September 18th, 2008

cubeLifeView.gif

I've been doing a lot of thinking this morning about what's important to me. I can't deny that the main reason I'm in the job I'm in is because of the amazing pay. I mean, it's amazing. And I have to admit that the development work is fun. But I can do that anywhere - I'm a developer, after all.

But that's the point. I want to develop. I don't want to mess with Jira tasks. Especially ones that are as poorly written and duplicate the same problem, cover multiple topics, used as email, etc. It's not what a bug tracking system is ment to be doing. It's a hack. Product itself is probably fine. It's the usage.

So I've been thinking about what I want to do. I want to code.

I heard about a job today that just mentioned Mac OS X as a "plus". That single fact was enough to get me interested in the job. Simple things like the platform you really like make all the difference. Heard about another doing more Java work - same thing in reverse. I can do Java, but it's not exciting to me anymore.

I'm reading about Git - sounds fun. Why? Because it's a new way of doing the same old thing, but getting around some of the problems I've had for ages. How to do a CVS check-in on the train in the evening? Can't. Can with Git. Cool. That kind of stuff.

So as I'm sitting here thinking about what I need to be doing next, I'm realizing that a new challenge really does sound like fun. Something new to do, not change for change's sake - something interesting. We'll see what comes up.

Getting Closer to Using Git

Thursday, September 18th, 2008

gitLogo.gif

This morning I was chatting with a good friend and we were talking about working with Git, and the next step for me is to get a good book Git like I had on CVS when I was learning it. I want to know how the repo is laid out, how to fix it, etc. I do not want to look at this as a 'black box' as that's just far far too dangerous for a developer to trust a single component. You should know how it works, just in case it might fail, so you can fix it.

Anyway, I found this book that looks to be very nice. So I ordered it as a PDF because I have my Kindle if I need to view it in that format, but I don't need another paper book. I've got a quick start on it on my Mac, and we'll see how long it takes me to get through it. I need to really understand what it's doing and then I'll feel comfortable putting my code in it. I also want to see how I want to set up anything on the home network to hold things there. Just don't know.

Which brings up another point made by my friend - get a Git hosting plan like GitHub. I have to say, I haven't been a huge fan of hosted CVS sites like SourceForge because of the licensing they put on the repos stored there. This was the reason for setting up my own CVS repo. But then I got HostMonster and I'm a huge fan of hosting now. I just have to be sure they aren't going anywhere.

So I signed up for a free GitHub account - I can upgrade it anytime to a paying account if I want to put my stuff there in a private repo, which I'll do if I decide not to set up my own Git repos at home. I certainly like the way they handle it - SSL and all, and the prices aren't too bad, but for the 'Small' plan, it's $12/month and that's $144/yr and that's more than I pay for HostMonster with a lot more storage, etc. HostMonster just doesn't seem to have Git hosting - yet. I'll have to check with them to see.

In any case, I'm getting a lot closer. Read the book, pick a hosting plan and start. Sweet.

Interesting Way to Read Last Line of a Log File

Wednesday, September 17th, 2008

cplusplus.jpg

I was messing around with trying to create a feedback mechanism from one application (server) that I had no control of whatsoever, to my application that was feeding this app tick data. The problem was I seemed to be able to flood the input and create a back-up by sending in too many price events a second, and the only monitoring I had was what I was going to make. So I had to come up with a clever idea.

My clever idea was really pretty simple - monitor the log of the second process, and see if it was done processing the last bit of data I sent. If not, then wait for it, if so, then continue on. It's not rocket science, but the devil is in the details. What to do if the log message is not something I expect? What to do if the log isn't moving? All these details pop up when you put a feedback loop into your code and don't want it to hang when the other app is hanging.

But the interesting part is the reading of the log. It's a fast moving system, so I can't be assured that the file is going to stay the same for any length of time, but I need to get the snapshot of the last line in the file as it's being written. Not easy. But I came up with what I think is a clever solution:

  1. CKString readLastLine( const CKString & aFilename )
  2. {
  3. bool error = false;
  4. CKString retval;
  5.  
  6. // now let's open this file for reading
  7. std::ifstream src;
  8. if (!error) {
  9. // open it for reading
  10. src.open(aFilename.c_str(), std::ios::in);
  11. if (!src || !src.is_open()) {
  12. /*
  13.   * While this is an error, I don't want to throw an exception
  14.   * because it's possible that this file just isn't there. In
  15.   * those cases, log the error and let it go.
  16.   */
  17. error = true;
  18. std::ostringstream msg;
  19. msg << "[readLastLine] While trying to open the file '"
  20. << filename << "' for reading the last message, an error "
  21. "occured: " << strerror(errno);
  22. SPLog::error(msg.str());
  23. }
  24. }
  25.  
  26. // let's back up to the last '\n' and read what we have up to there
  27. if (!error) {
  28. char buff[256];
  29. int i = 0;
  30. // zero this out to make sure it's clean - no matter what
  31. bzero(buff, 256);
  32. /*
  33.   * We need to get to the char *before* the end, and the way this
  34.   * is done is to have an offset of (-1) and the location the 'end'.
  35.   * We need to do this as opposed to start at the end because if
  36.   * we do the latter, we'll never get off the end. This allows us
  37.   * to back up the file to get what we need.
  38.   */
  39. // get to the last character in the file
  40. src.seekg(-1, std::ios::end);
  41. // take a look at it, and if it's not a '\n', keep it
  42. buff[i] = src.peek();
  43. if (buff[i] != '\n') {
  44. ++i;
  45. }
  46. // back-up past this last character so we can loop
  47. src.seekg(-1, std::ios::cur);
  48. // keep backing up until we hit a '\n' and then stop
  49. while ((buff[i++] = src.peek()) != '\n') {
  50. src.seekg(-1, std::ios::cur);
  51. if (i == 255) {
  52. break;
  53. }
  54. }
  55. // see if we backed up so far that we missed the last full line
  56. if (i == 255) {
  57. error = true;
  58. std::ostringstream msg;
  59. msg << "[readLastLine] While trying to read the last "
  60. "line of the file '" << filename << "' for the last "
  61. "message, an error occured and a complete log message "
  62. "couldn't be read.";
  63. SPLog::warn(msg.str());
  64. } else {
  65. // get back to the last good char we read
  66. --i;
  67. // now, strip the beginning newline - if it's there
  68. if (buff[i] == '\n') {
  69. --i;
  70. }
  71. // reverse the line into a CKString
  72. for (int j = i; j >= 0; --j) {
  73. retval.append(buff[j]);
  74. }
  75. }
  76. // close the file
  77. src.close();
  78. }
  79.  
  80. return retval;
  81. }

The interesting stuff starts with the open() on line 10. Typically, you might write that as:

  1. // open it for reading
  2. src.open(aFilename.c_str(), std::ios::in | std::ios::ate);

but if you did that, you'd end up at the end of the file - as if to append to it, and you would not be able to "back up" into the file. This is the key to this code - find the end, sit on it, and then even if the file is added to, the pointer you have won't move and you can back up to get a line.

The seekg() in line 40 puts the 'marker' at the end of the file, and then reversing the buffer as you walk 'up' the file, 'peeking' the data out of it is pretty easy. The tough part was opening and quickly getting to the end while being able to back up.

In the end, this is working wonderfully for me. It's fast, stable, and as long as the log writer is buffered on newlines, we're going to get nice, complete, lines. Sweet.

Thinking About Springing for an Aeron Chair

Monday, September 15th, 2008

aeron.jpg

This last episode with my back is proving to be a real hassle to deal with. The chair in my home office was a $99 chair (I was cheap) purchased many years ago (we had no money) and when I've had to sit in it these last few weeks it seems to make my back problems worse. I know it's the chair because I can sit in other chairs and don't get these aches that I'm getting from my office chair.

Yet I can't help it - I have to be able to get some work done. It's just a fact of the business I'm in. So I'm thinking of springing for a refurbished Aeron chair. I can get one for about $700 - half off. That's not a bad deal, and it's the exact model I've used at a previous job for a while and loved every minute of it. Excellent chair.

I have a hard time spending that much money on a chair for an office that I don't sit in on a daily basis. It is, after all, a lot of money for a chair. Heck, I can get a Lazy-Boy for that money... but it's not a good, working, office chair. I think it's time to realize that I'm not getting any younger and it's time to invest in a good chair for the rest of my professional life.

Maintenance Release for BBEdit 9.0.1

Monday, September 15th, 2008

BBEdit.jpg

This morning I saw that BareBones released BBEdit 9.0.1 with tons of little bug fixes. Looks very much like a maintenance release and that's great news. I have to say that I've been playing with it for a while and while I understand the type-ahead and hints, I'm not sure that I'm the kind of guy that really likes to use them.

I love ctags, and that gets me a long way, and I work around a lot of guys that probably couldn't write a method without it. I know they couldn't write C++, so all that's left is Java. OK... I'm probably being a little mean here, but I'm certain all but one couldn't do it. The days of IDEs have taken away the skills of real programming in favor of click-n-drag development. It's a trade-off, but I think they are the worse for their dependency.

As for me. I want to know my code. Understand it inside and out. That's how you debug something. Single stepping is the last resort as it modifies the execution in all but the simplest of applications.

Anyway... kudos to the guys are BareBones for keeping BBEdit going. If only the Coding Monkeys updated SubEthaEdit...

Warming Up to the Idea of Distributed Source Control

Friday, September 12th, 2008

gitLogo.gif

I've been thinking about Subversion today. It's been brought on by the fact that the main Subversion server for the Shop has been down due to some reason that they never explained. At the same time, my local CVS pserver has been working just fine. But it got me to thinking. svn is nice for the ability to do svn status and get diffs and such. That's really nice. But if that's something you want to have, why not take it another step and make it all on your box - there's a Distributed SCM system. Like Git.

So... is it time to get into something like Git? Not sure. I was talking to a friend a while back and he's going in that direction because there are a lot of advantages to this scheme. Face it - the one thing CVS, Subversion, ClearCase, PVCS, etc. all have in common is that they have a central repository. This is great for a company that wants to have a 'vault' for their code. Some place to lock down, back-up, secure and control.

But if you say that's not important because there will be enough copies of the repository around, you don't have to worry about losing the whole thing. You can get it from your buddy. OK, "bad" for corporate-types, but for guys writing code on Open Source projects, it's ideal. I've got it - you've got it, and I don't have to constantly be connected to "The Source" to work and have version control. I only need to be connected to "The Source" if I want it to have what I've been doing.

Think of the case where one developer fixes one file and some of the other members need to get this file. With CVS you all get it when you do anything SCM-related. Nice if you have a fast network connection to "The Source", but if you don't it's painful. And if you don't need the change, you get it anyway, most likely.

Git (as an example) would let a group develop different parts of the project without having to connect to one another until they decided that it was time to share code - then they'd do it. And only then, share what they wanted. You could choose to have Git hosted in a central location for synching - much like a traditional 'primary' repository, if you wanted. There's no one way to do it.

I'm getting interested in the idea of having a central Git repository for historical records and then using Git locally to do most of the work. It would mean larger disk space usage, but I'm guessing with decent laptop drives it's not that big a deal. And there's TimeMachine to back it up. Might be a good idea. Have to give it more thought.

Conceded to Removing Constants from BKJEP’s getSymbols()

Wednesday, September 10th, 2008

BKit.jpg

Today one of the more annoying developers I work with reported a 'bug' in the BKJEP parser's getSymbols() method - saying that the symbols 'null', 'e', and 'pi' weren't supposed to be there. Well... those are the constants I added a little while back to allow the testing for null as well as the basic math constants. So they are symbols in the JEP sense of the word, but this guy's code wasn't smart enough to realize that not all symbols are those that he supplied.

What I think he's doing is assuming that all symbols are, in fact, tickers to be processed. He then tries to process these tickers, doesn't trap for the possibility that the user entered bad data, and then it bombs because he's done all this optimistic coding and this is just the first place it's been caught.

My first response was to say "Nope. These are symbols and you need to deal with the fact that users might enter bad data as well." But then I got to thinking. Were constants the equivalent of variables?

I had thought BKJEP overrode the getSymbols() method from JEP, but it hadn't. So I really was free to think of this in terms of what they user might really want. When I took the annoying developer out of the mix, and thought about the role of constants in the expression parsing I came to the conclusion that it probably is better to think of them as "invisible" to the variable space. They aren't to be changed... they support the processing, but may take no part in it's execution... in many ways they aren't the same as the other variables returned from getSymbols().

So I filtered them out of the getSymbols() call. I suppose that the better thing to add would be a getConstants() and then maybe a getAllSymbols() or something like that. It you break down the JEP symbols in a way that I thought it was originally, but wasn't: variables, constants, and both.

So, I guess the lesson is try to keep an open mind and even an annoying jerk of a programmer can get something right - even if by accident.

Panic Releases Coda 1.5.1

Wednesday, September 10th, 2008

Coda.jpg

Hey! This morning the guys at Panic released Coda 1.5.1 - a bug list of bug fixes for the all-in-one web development tool. They have an interesting way of doing the updates - within the app, but not with Sparkle - at least not that I can see. No matter, it's nice to see that they were so quick with the update given the time it took to get 1.5 out the door.

I do wish I did more of this kind of web development on my Mac - just because I like this tool so much. It really is a nice way to deal with the non-web app sites.

Fixed Scaling for Axis Changes of the BKSimpleScatterGraph

Tuesday, September 9th, 2008

BKit.jpg

A developer stopped by today - OK, well he didn't stop by, I had to walk to his place, but still... he pointed out that if you make a selection on the z-axis of the BKSimpleScatterGraph and then change the x (or y) axis, the graph doesn't properly re-scale it's limits.

The code I had in for the rescaling was (is) in the updateVisibility() method and that wasn't getting called for axes changes. All I had to do was to place a call to that method in the setColumnsToGraph() and it picked up the rescaling nicely.

Good fix, all changes now are reflected in the re-drawn graph.