terminal craziness

What errant key or cosmic ray consistently makes it impossible to switch screen tabs with ctrl-A and the number? It just prints the number, then when I hit backspace to delete the number, then it acts like I hit ctrl-A backspace instead and goes to the previous tab, whichever that is.

Even more galling is I have yet to figure it out. I just have to wait until, sometimes, after waiting long enough, it starts working again. Like I completely closed every screen tab and screen and the terminal session and iTerm, and when I logged back in it was still broken—yet in just the time it has taken to write this, it has resolved itself without explanation and works again.

After all these years I have no idea how terminals work. It's still completely high magic and I'm totally stuck whenever it breaks. It doesn't help that it's completely impossible to search the internet for keystrokes.

JumpDomain sucks

JumpDomain is totally screwing me by not renewing my markpasc.org domain even though I paid them to renew it on the 4th.

People have had to resort to messaging me on Flickr and elsewhere to ask me about stuff. The site is still available at a different name thanks to Cornerhost’s nice every-name-a-subdomain feature, but that doesn’t help anyone searching or, say, sending me email. The earliest disruption was when I tried to reply to my sister-in-law about getting gifts for my nephews (noted earlier) and Comcast rejected my mail; I didn’t realize at the time why but the next day my web site was down too, so it was obvious.

As everyone else on the internet seems to note (I included this, this, and this in my message to Tucows; also this) JumpDomain was highly regarded when they first started, but seem to be not even answering support requests anymore. How Tucows or Enom would let them get away with running a business that irresponsibly is beyond me. (My support request has only been open a few days, but after reading these stories, I gave up and contacted Tucows directly today.)

I have to admit I’m surprised that Tucows would throw a tasting style page up on my domain. Even before I found out they were doing that, I fantasized a couple minutes yesterday I might start my own registrar or reseller; one feature would be a more helpful failwhale style “Technical difficulties!” page warning a customer that a domain had expired, but I wasn’t sure ICANN would allow a registrar to take over an expired domain immediately like that. (I figure this kills your site from search engine listings either way.) It’s sad that it’s possible but Tucows is spamvertising instead. Hopefully they can make up for it by helping me get the name back.

Also not encouraging is that on the Tucows Domain Name Help Center, the “you can go here for assistance” link doesn’t work. Fortunately they have other links that do, such as their “If my provider does not help me, can you assist?” FAQ.

I did contribute to this myself by not realizing I had an old email for my admin address on that domain. I may need to file the Change of Admin Email form with Tucows for them to help me renew/release the domain. Oddly enough this never mattered before in the several years I’ve been renewing this domain, so I never noticed. (Registrar feature #2: better integrated monitoring and updating of contact emails across an account and all its domains.)

My other domains are with WebLaunching.net, though I haven’t had a customer service emergency to test with them either. At least they don’t have the vociferous web hate JumpDomain now has, plain as day on the first page of Google results.

Are your names coming up for renewal? Who’s your registrar? Do you like them?

Untitled

There once was a young man from Flint
Who’d torture with both eyes a-glint
For all he would say,
Every night and each day,
Was, “Any you quaids got a smint?”

Five months in 15 pictures

I only read Activate for the pictures, as they’re so good at picking out the best of Reuters. I caught up from issue 100 (late May), and here are 15 favorites.

  1. A woman dressed as a maiko (apprentice geisha) walks down a street wearing US Democratic Party candidate Barack Obama campaign buttons in Kyoto, Japan, on May 20, 2008.”
  2. “White House staff, press, and Secret Service personnel sit outside a luxury trailer where US first lady Laura Bush flies in privacy inside a C-17 military aircraft, during a seven-hour flight from Afghanistan to Slovenia, on June 8, 2008.”
  3. People watch fireworks during the first edition of the Golden Nights International Pyrotechnic Festival in Bucharest, Romania, on July 5, 2008.”
  4. “Firefighter Cody Cox of Colorado looks over a burned redwood forest while working to control hot spots during a wildfire in Big Sur, California, on July 7, 2008.”
  5. “People walk across a copy of Russian-born expressionist Vassily Kandinsky’s painting ‘Weilheim-Marienplatz’ on the pavement of the market square in the southern Bavarian town of Weilheim, Germany, on July 28, 2008.”
  6. A magnet carries confiscated guns, to be thrown into a melting pot and destroyed, at an iron and steel plant in Montevideo, Uruguay, on July 24, 2008.”
  7. “A reveller swims in tomato pulp during the annual tomatina (tomato fight) in the Mediterranean village of Buñol, Spain, on August 27, 2008.”
  8. “A man carries drinking water through a flooded street in the northern Indian city of Lucknow, on August 27, 2008.”
  9. “Informatics PhD student Sebastian Bitzer performs push-up exercises with a programmed Kondo humanoid robot, at the newly opened Informatics Forum building of the University of Edinburgh, Scotland, on September 3, 2008.”
  10. A US soldier waves to residents at the newly opened Mithaq swimming pool in Baghdad’s Sadr City, on August 30, 2008.”
  11. “A worker mows around a sculpture entitled ‘Innerscape on the Move’ by artist Zadok Ben-David at a Sotheby’s exhibition at Chatsworth House in England, on September 16, 2008.”
  12. “A worker climbs among skylights on the ‘living roof’ — a 2.5 acre expanse of native California plants — at the California Academy of Sciences building in San Francisco, California, on September 18, 2008.”
  13. “Museum of Tropical Queensland researcher Neil Bruce studies specimens in a lighted aquarium on Lizard Island Reef in far-northern Australia.”
  14. “Spanish flamenco dancer Andres Marin performs as musician Llorenc Barber plays bells, during a rehearsal of ‘El Cielo de tu Boca’ at the Biennial of Flamenco in Seville, Spain, on September 22, 2008.”
  15. A Kazakh officer shows off a large map with a plan of the joint Kazakh-Russian military exercise at Otar range, some 93 miles west of Almaty, Kazakhstan, on October 3, 2008.”

Recovering from "(no branch)" during a git rebase

I was using git rebase to merge changesets from one subversion repository onto code from a completely different repository. Figuring out multiple svn-remotes and the attendant issues was fun1, though once I figured out I did want to rebase, which onto what, how to delete a remote branch, and how to use rebase --interactive to edit git svn’s ported commit messages, it worked pretty well. But that’s not important.

During the rebase, I ended up off the branch I was trying to do the merge “in,” where git branch said I was on (no branch). However, like everyone else on the internet, I blithely continued past that point. How do I recover from (no branch) without losing the completed rebase?

mpaschal@mpaschal-mt:~/svn/mt/git$ git branch -a
* (no branch)
  atompub
  master
  git-svn
  github/master
  trunk

Of the search results I consulted, Mark Guzman best described what happened:

Little did I know that I had entered the “(no branch)” state. At this point I was pretty much gunning to create orphaned blobs, commits and other such items.

So (no branch) is when HEAD is a commit that is no longer one of the leading branch commits (which is what it means to be “on a branch”). If as in this case I want atompub to match HEAD, I have to git merge the outstanding HEAD commits over to atompub. That works fine since the new commits are changesets atop atompub in the first place; it’s as though I’m on a branch of atompub, only I never explicitly branched, so it doesn’t have a name. Instead I have to refer to it by the commit ID.

As I hadn’t switched back to the real branch yet, I didn’t have to recover my nameless HEAD commit the way Mark did. Instead I could look directly at the log:

mpaschal@mpaschal-mt:~/svn/mt/git$ git log -1 --pretty=oneline
658b8173ab396c7bb765f990c2bc2fdc7d639c86 Merged all ...

Then switch and merge:

mpaschal@mpaschal-mt:~/svn/mt/git$ git checkout atompub
Switched to branch "atompub"
mpaschal@mpaschal-mt:~/svn/mt/git$ git merge 658b817
Updating 461f2f7..658b817
Fast forward
  ...

It’s like magic!2

1 Not actually fun.

2 It’s a long incantation you have to research to discover, and getting it wrong can have disastrous consequences.

Untitled

I’m always eager to believe people who tell me I’m smart and creative, but is this Psychology Today article1 some cold reading bullshit or what?

Or as put by the author: “Here are the 10 antithetical traits often present in creative people that are integrated with each other in a dialectical tension.”

  1. You’re energetic, except when you’re exhausted; you’re sexually charged, except when you’re not.
  2. You’re smart, but not too smart, and not always.
  3. You work hard and play hard.
  4. You’re in the here and now, except when you’re off in your own world.
  5. You like crowds and company, except when you don’t.
  6. You crow about your accomplishments, yet you know how much you suck.
  7. You’re strong, but have a soft side.
  8. You have enough experience in your area to make what’s good even better.
  9. You’re both enthusiastic and analytical in your work.
  10. Your awareness in your area of expertise is a blessing and a curse.

If this is what makes you creative, it’s even more proof of Ken Robinson’s claim that everyone can be creative.

1 It’s gratifying enough I forgot where I got the link before reading it, yet came to a similar conclusion.

Untitled

Awesome dinner last night with David and folks for his birthday. Much wine and laughter.

As dream imagery goes, calling 911 and getting phone trees, someone's voicemail, hold music, and ultimately the business end of my alarm clock seems like a bad sign.

“No such file or directory” checking out gitosis-admin repo (git-shell not on path)

Am I the only person who’s found git 1.6.0 doesn’t work with gitosis 0.2? I found a couple references to this error trying to check out the gitosis-admin project, but no solutions—at least not the one I had to make up.

mpaschal@hostname:~$ git clone git@hostname:gitosis-admin.git
Initialized empty Git repository in /home/mpaschal/gitosis-admin/.git/
Traceback (most recent call last):
  File "/usr/local/bin/gitosis-serve", line 8, in <module>
    load_entry_point('gitosis==0.2', 'console_scripts', 'gitosis-serve')()
  File "/usr/local/lib/python2.5/site-packages/gitosis-0.2-py2.5.egg/gitosis/app.py", line 24, in run
    return app.main()
  File "/usr/local/lib/python2.5/site-packages/gitosis-0.2-py2.5.egg/gitosis/app.py", line 38, in main
    self.handle_args(parser, cfg, options, args)
  File "/usr/local/lib/python2.5/site-packages/gitosis-0.2-py2.5.egg/gitosis/serve.py", line 192, in handle_args
    os.execvp('git-shell', ['git-shell', '-c', newcmd])
  File "/usr/local/lib/python2.5/os.py", line 353, in execvp
    _execvpe(file, args)
  File "/usr/local/lib/python2.5/os.py", line 389, in _execvpe
    func(fullname, *argrest)
OSError: [Errno 2] No such file or directory
fatal: The remote end hung up unexpectedly
mpaschal@hostname:~$

gitosis sets up so it runs git-shell as the git user’s login command, but git 1.6.0 apparently installs everything in the “gitexecdir,” which by default ends up /usr/local/libexec/git-core. Which of course is not on the user’s path. Normally that’s fine since you write git command and /usr/local/bin/git rewrites that as git-command, and /usr/local/bin/git knows exactly where all those are, but that means you can’t yourself run git-shell directly.

The gitosis directions I was looking at also suggest making /bin/sh the git user’s shell, which means .bash_profile isn’t evaluated on login. So I couldn’t just add /usr/local/libexec/git-core to git’s PATH (even if I put it in regular .profile—dunno if I was goofing it up somehow, or if ssh default commands don’t start the shell first, or what).

I gave up and copied git-shell to /usr/local/bin, where regular git lives.

good question



I made something up.

Untitled

By way of the previous post, a thought of the day:

resoundingsalmon: Search Engine Optimization people are evil. They want to eat your fucking soul.

oic.

Untitled

I would feel better about the latest turn in Twilight Princess if, when you listened in on the guards in Castle Town, they had a conversation like this one:

Bell: Dammit, I forgot my lunch sack again.
Frid: Ha, I hear that kid from Ordon will fetch any damn thing.
Bell: No shit? Tell him my lunch sack is vital to Hyrule’s security!

And then they laugh like Tom Nook.

git equivalent to “svn copy” for forking files with history?

As might be obvious from my previous post, I don’t yet grok git. (It took three tries over about a week to figure out what I posted there.) My other major question as a dual git/subversion user is how do I svn copy in git? I don’t see that adequately answered anywhere.

The most common use of svn copy is to branch, which is precisely what I don’t mean here. git seems to promote branches to a first-order concept, in that the entire git repository exists across branches, and there are specific commands for branching and merging. You can’t have a nonstandard trunk/branch/tag hierarchy like you do sometimes in subversion, because there is no hierarchy. git branches are completely orthogonal to your file structure.

Git From the Bottom Up suggests (perhaps a little facetiously) phrasing your problem in git’s language in order to understand:

Understanding commits is the key to grokking Git. You’ll know you have reached the Zen plateau of branching wisdom when your mind contains only commit topologies, leaving behind the confusion of branches, tags, local and remote repositories….

In these terms, you find branches are really names for other commits besides the master head main trunk commit. It’s not really that branches are first-order things, but that branches are names for commits instead of files. Either way, they’re completely orthogonal to the filesystem.

Looking again just now for the answer to my question, I found this thread, which illustrates git’s current position on copying, and how it’s contrary to this second use of svn copy that I’m trying to figure out:

svn copy::
Duplicate something in working copy or repository, remembering history.
cp A B; git add B::
Git doesn’t have a direct equivalent of svn copy. It’s arguable whether it needs it once the user knows they can git-add so easily.

Git wins. Git’s ability to detect copies after-the-fact, mean that a git-copy isn’t necessary.

svn copy is more like git checout -b, i.e. it’s primary purpose is not to “copy” things, it is to create branches. You generally do not copy code (I hope).

Well, in fact, I often do copy code with svn, because I want to fork a file with history. Often I discover when I’m working on (say) some class, I’ve accreted unrelated functionality around the class’s real work, and I need to separate it out. Obviously I can do that just fine and check both parts in, but if I naïvely fork one file in twain—by doing a real file copy and adding the new file, say—the new one will lose all its history. The first commit git will know about for it is the one where it appears fully formed from Zeus’ head, though it happens to share an equivalent blob with some other file in the commit.

In git terms, you can see why it’s not obvious how to copy with history: to duplicate svn copy A B, you want git to understand when you ask about B’s history to include all of A’s previous commits. It’s as though you want to change all A’s commits retroactively to include B, sort of. It’s more about the behavior of the tools than anything you can articulate in a git repository’s data.

So I looked for behavior: lo and behold, Andy Parkin’s message above notes that git can “detect copies after-the-fact,” and I guess he means for example git log’s -C and --find-copies-harder options. According to the manual, this seems to be exactly the behavior I need:

-C
Detect copies as well as renames. See also --find-copies-harder.
--find-copies-harder
For performance reasons, by default, -C option finds copies only if the original file of the copy was modified in the same changeset. This flag makes the command inspect unmodified files as candidates for the source of copy. This is a very expensive operation for large projects, so use it with caution. Giving more than one -C option has the same effect.

If only it worked that way. See the terminalcast I did showing what I mean: once I duplicate the file, svn log doesn’t show fred’s initial commit in wilma’s history, even with the -C or --find-copies-harder flags.

I would be delighted to be wrong, but as far as I can tell, it’s not possible to fork files in git, while it’s trivial with svn copy.

Moving commits from git to subversion

It’s fairly well documented what to do if you have a subversion repository and want to develop on it with git. What if you have a project you started in a git repository, but now need to publish it to a subversion repo?

After several attempts and resets, this seems to be what you have to do to check a project you built with local git into an arbitrary place in a subversion repository.

  1. Make a new git repo: mkdir ~/import; cd ~/import; git init
  2. Make the new remote directory in the svn repo: svn mkdir http://example.com/proj/
  3. Link up with the empty path using git-svn: git svn clone -T '' http://example.com/proj/
  4. Add your original repo as a remote: git remote add dev file:///home/username/work/proj
  5. git pull dev master to pull in all the original git repo’s commits.
  6. git svn rebase to rebase all the commits on top of the svn commit.
  7. In my case, the rebase halted on some commits in the git history where I added files. I had to git add the files manually, then git rebase --continue.
  8. git svn dcommit (or with -n to check… but it’s just a list of commit IDs, so it sure didn’t make me feel that much better about doing it)

You can then really check it worked by comparing the subversion content to your git repo:

  1. cp -R ~/work/proj proj-git
  2. rm -r proj-git/.git
  3. svn export http://example.com/proj/ proj-svn
  4. diff -rub proj-svn proj-git

As usual in UNIX, silence is golden.

New light

Our intranet’s page header is in Helvetica Neue Light. Now that I’m using Firefox 3 again, I noticed it wasn’t rendering right; it was regular Helvetica. Firefox 3 has better font rendering, so I knew it’s supposed to be able to use it. Why didn’t it?

For it to show up in Safari, you have to put the typeface name and the variant in the font-family, and spell it a little weird, like so:

font-family: "HelveticaNeue-Light";

Some Googling says you can use Helvetica Neue Light in Firefox if you spell it out like a normal font name:

font-family: "Helvetica Neue Light";

I assume that works in Firefox 2, but it doesn’t seem to in Firefox 3. After enough banging on it, I found Firefox 3 (reasonably) wants you to specify the font in font-family and the weight variant the real CSS way, with font-weight:

font-family: "Helvetica Neue";
font-weight: 100;

So to cover all the bases, in practice you’d write:

font-family: "HelveticaNeue-Light", "Helvetica Neue Light",
             "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: 100;

Firefox 3

Download DayKesh’s post reminds me: Firefox 3 comes out tomorrow, Tuesday the 17th—but I’ve already been using it. Despite overcoming the lack of Greasemonkey and Firebug, Safari still has no Awesomebar, and I can happily report that since upgrading to Firefox 3 rc2 (now rc3) and Firefox 3 versions of my extensions (Firebug, Greasemonkey, and Adblock Plus), I haven’t noticed any crashing, either.

  • That first link is about Spread Firefox’s Download Day 2008, the attempt to get Firefox into the Guinness World Record book for “most software downloads in 24 hours.”
  • Deb Richardson compiled a field guide to Firefox 3 showing off all the new features and improvements.
  • If you don’t want to read, watch Mike Beltzner’s screencast guide to the major features instead.
  • The improved default theme for OS X is more OS X-y, but if it’s not quite OS X-y enough for you with all the rounded buttons and whatnot, try one of the GrApple themes.
  • Lastly, feel for Mark Smith, who’s working at Mozilla, supporting all this craziness.

If you aren’t going to use Firefox 3, there’s still good news: even at $0, the market for browsers is competitive again. Safari is a better browser because of Firefox, and Firefox 3 is a better browser because of Safari. Here’s looking forward to a Safari 4 that makes me want to switch again! (But hopefully not too soon.)

CommitBit

Hmm, my test CommitBit install doesn’t have the right CSS at all. Am I missing something? I installed CommitBit from subversion with Jifty from CPAN, and it doesn’t look anything like Best Practical’s.

Jifty seems to do this weird CSS compilation thing so I can’t tell where the CSS is supposed to be coming from, either.

Update: yeah, Jesse’s suggestion to use the CPAN version of CommitBit works great. Thanks!

TAP in pyparsing

Paul McGuire, author of pyparsing, was nice enough to write up a TAP parser using it for comparison to my yeanpypa attempt. A few days earlier I had hacked up my own pyparsing version too, as pyparsing has a few features that seemed like it would make a more forgiving parser. Here’s the pyparsing version I wrote:

Read more... )

Some interesting features:

  • I used the pydoc and the examples instead of the actual manual, so I didn’t see setDefaultWhitespaceChars that Paul used. I had to use CharsNotIn('#\n') in description and (?s) in the directive regexp so the dot wouldn’t match the \n.
  • I used a parse action to strip the optional leading dash from description, rather than try to match it. Looking back now I don’t see why I couldn’t include the Optional('-') on the front, but it seemed to make sense when I wrote it.

Using Combine and the naming feature means I get immediately useful results with this parser, unlike the yeanpypa parser, which ends up being more of a tokenizer.

>>> from tap_parser import tap
>>> test1 = """\                                                                                                          
... 1..4                                                                                                                  
... ok 1 - Input file opened                                                                                              
... not ok 2 - First line of the input valid                                                                              
... ok 3 - Read the rest of the file                                                                                      
... not ok 4 - Summarized correctly # TODO Not written yet
... """
>>> res = tap.parseString(test1)
>>> res.plan
'4'
>>> res.tests[0].ok
'ok'
>>> res.tests[1].ok
''
>>> res.tests[1].notok
'not ok'
>>> res.tests[1].description
'First line of the input valid'
>>> [res.tests[3][f] for f in ('num', 'todo', 'description')]
['4', 'todo', 'Summarized correctly ']
>>>

Paul still uses a function in his example to massage the results into output, but my results map almost exactly into the Django model objects I planned to make.

On the other hand, mine fails Paul’s test3 example, which is certainly proper TAP. Seems to not be handling post-planned results due to my attempted use of Each (the & operator). Hmm.

Update: Oh, no, it was the missing test numbers that made it barf. Somehow I’d read into the TAP spec that a test number was required if there was a description… or at least accidentally written that into the parser. Changing test_line’s definition thusly made the tests work (though I’m only testing one stream for correctness so far):

test_line = result + Optional(test_num) +
            Optional(description) + Optional(directive)

Boxed

Fair's fair

Somehow I got onto WebKit nightlies instead of stable Safari 3, and even after uninstalling SIMBL and losing magic Greasemonkey powers, it’s crashy. Just so you know.

Parsing in Python

I want a TAP parser in Python, so I tried yeanpypa:

from yeanpypa import *

non_zero_number = AnyOf('123456789') + ZeroOrMore(digit)
rest_of_line    = OneOrMore(NoneOf('\n'))

plan = Literal('1..') + non_zero_number

todo_directive = Optional(' ') + rest_of_line
skip_reason    = ZeroOrMore(NoneOf(' ')) + Literal(' ')
               + rest_of_line
skip_directive = Optional(' ') + Literal('# ')
               + Literal('skip') + Optional(skip_reason)
directive      = Optional(' ') + Literal('# ')
               + (skip_directive | todo_directive)

description = Optional(' ') + Optional('- ')
            + ZeroOrMore(NoneOf('#\n'))
ok_not_ok   = Literal('ok') | Literal('not ok')
test_num    = Optional(' ') + non_zero_number

test = ok_not_ok + Optional(test_num)
     + Optional(description) + Optional(directive)

plan_skipped   = Literal('1..0') + skip_directive
plan_first_tap = plan + ZeroOrMore(Literal('\n') + test)
plan_last_tap  = test + ZeroOrMore(Literal('\n') + test)
               + Optional(Literal('\n') + plan)

tap = plan_skipped | plan_first_tap | plan_last_tap

I guess it works, but it feels like writing a regular expression longhand. I would probably also make it more lax if I wrote it as an re, as it would be easier to write \s*-\s* in the description rule, say.

Elder 20