walls.corpus

By Nathan L. Walls

Articles tagged “development”

Tool Sharpening: June 8, 2014

For some background on what’s going on here, see the first tool sharpening post

This past week found me still getting over the last vestiges of a cold, then traveling for a conference. Consequently, not a whole lot this week. But, on to it:

In Mail.app, I created a Smart Mailbox for any email that contains the word “unsubscribe”. I caught this somewhere in my online travels in the last week, but I’m not able to put a finger on who I picked it up from. When I find out, I’ll update with credit. The goal here is to review for mailing lists in general from one spot and decide if they’re still valuable.

I created a training session template in BBEdit for note-taking during RubyNation 2014. I focus on talks and lectures by writing notes down in outline format. It was a habit I built up during college lectures, and one that I retain when I’m processing new material. This template gave me the ability to quickly create a Markdown with YAML front matter document, tab through some placeholders to fill-in some document tags, the name of the talk and the presenter. From there, I just need to name the document and I’m ready to take notes. During the two day conference, I created 21 documents, iterating on the template during the first quarter of those sessions.

I’ll have more to say on the conference itself later this week. As a preview: Good to great talks and a whole lot of processing to do with some thought provoking material.

Tool Sharpening: June 1, 2014

For some background on what’s going on here, see the first tool sharpening post

This week was slower than previous weeks. I’ve been sick the second half of the week and just being moderately productive Thursday and Friday was a challenge. Excuses aside, here’s what’s new, this week:

OmniFocus

OmniFocus 2 was officially released. The new release has presented an opportunity to make some adjustments.

  • Created some new custom perspectives
    • “Fast Actions” for items that I can complete in 15 minutes or less
    • “Oldest” shows items by order of creation. This will be useful for looking at items that have been lingering for weeks, months or longer and make a call about whether I’m ever going to carry those actions out and, if not, delete them
  • Set custom icons for all of my custom perspectives from Josh Hughes’ set

Instapaper

Not a developer thing, but bear with me.

  • Updated token so favorited articles will post to my Pinboard account. I’d like to do some link blog mining using this workflow as a starting point
  • Renewed my Instapaper subscription to gain access to full-text search

Tool Sharpening: May 25, 2014

For some background on what’s going on here, see the first tool sharpening post

This past week’s refinements started with more BBEdit adjustments. I’ve been spending a lot of time in the text editor. Thinking through it, it’s overdue. There are several actions in my daily workflow that feel inefficient to me, ones that I know an editor like Emacs or vi(m) has readily available. And, as it turns out, as I have been looking for solutions, I have been finding them.

In my previous entry, I mentioned the BBEdit 10.x release notes containing a lot of information about existing features of which I was taking insufficient advantage of. I alluded to some keyboard binding changes I made in favor of built-in shortcuts. Those are pretty great. What’s also great is that several Mac OS X applications support using a number of Emacs key bindings because there’s a whole range of default shortcuts for text manipulation that work in Mac OS X applications that make use of the Cocoa Text System. What’s very nice about that is effort I put into learning more of the these shortcuts in BBEdit are likely to pay off in other OS X applications I use.

One of these Emacs shortcuts I learned about from BBEdit’s version 10.x release notes is about C-u (Control-u if you’re not versed in how Emacs documentation refers to this). C-u takes a number and then a character to repeat that number of times.

A sample case is this: I will use a series of #‘s in a source code file as a header or section separater. I’ve tried approaches from create a clipping for that to typing four or five of them then cut-and-repetitive-pasting. This, instead, gives me something more flexible.

By example:

1
C-u 20 #

will yield:

1
####################

There are several other immediately helpful shortcuts, too, such as C-t, which will transpose two selected characters, as such: ab becomes ba. In BBEdit, if the selection range is larger than two characters, the first and last characters in the selection are transposed, so abcd becomes dbca.

Functionality for transposing words also works, but transposing lines does not. If I end up needing that, I’ll just need to use slightly longer shortcuts around line manipulation. If I need it more consistently, I can write a text filter.

Finding these shortcuts have helped to alleviate the low-grade sensation that I was working too hard to edit text. The rest of this week’s changes are below. Enjoy.

Other BBEdit changes

  • Added a shortcut for prefix/suffix line
  • Added a shortcut for reapplying the last text filter used
  • Updated a text filter I’ve been using for a long while that queries a JIRA instance and provides me with the case title and a link in a Markdown list

TextExpander changes

  • I keep a food journal in a text document, so there are a few items I type repetitively. To that end, I want less typing and correct spelling.
    • Replace “Worchester” with “Worcestershire”
    • Expand “CAJ” to “Cup-a-Joe”, a local coffeehouse
    • Expand ;cs to “chicken salad”
    • Expand ;tm to “trail mix”
  • Added a shortcut for “stand-up”
  • Reviewed how to chain shortcuts in TextExpander
  • Created a shortcut that allows me to pre-fill “.webassign.net” for SSH and moves the cursor to right before the first dot in order to

Other misc changes

  • Created a TextExpander perspective in OmniFocus in order to quickly focus on pending adjustments
  • Created new search profiles for Ruby, JavaSCript, HTML + CSS, datastores and “DevOps” tools in Dash

Locally testing destructive Git actions

My team is responsible for maintaining a production line in our various Git repositories. After releases, we’re responsible for merging the development line to the production line, so any bug fix release starts from the basis of what’s currently running in production.

Making a longer story shorter, we had a release that we cancelled and decided to roll into a future release. But this was after we’d already made the merge to the production branch. We further had a mix of fast-forward commits with no merge commit and non-fast-forward merges across the different repositories that comprise a product release. We want to get our production line back to where production is actually at.

I researched a few strategies, centered around git revert and git reset for how to step forward and wanted to test them out.

Since each Git clone is complete unto itself (and we use a single remote versus multiple points of authority), I have the entire public history. So, it’s very easy to make a copy of a repo, make a bare clone as a “remote” and test changes locally.

Before we start

First, some words about safety. Out of an abundance of caution, I recommend the following before we start the experiment:

  • Make sure your remote origin is up-to-date
  • Make sure you are up-to-date with the remote origin
  • Make sure the remote origin is backed-up
  • Disable networking on your machine until the experiment is concluded

I also need your understanding that I’m describing procedures for experimentation, not trying to solve for your problem. We’re going to use git reset below and it is a destructive action. You own your data and are much better equipped to understand your repository and situation. Act with prudence.

If you’re looking for info on addressing various changes to repositories, you’d do worse than having a look at Kai Howelmeyer’s “Git Undo by Example” post.

Local and destructive testing

Our safety pre-check complete, here’s how to test destructive Git repository changes locally:

  1. Determine where you’re going to be working on this test. I recommend something like git-experiment underneath /tmp.

    1
    
    $ mkdir -p /tmp/git-experiement/
    
  2. Copy the repository in question to git-experiment, or clone if it’s a small repository. For this example, let’s pretend this repository is named smith. I’m going to refer to this as the local clone.

    1
    
    $ cp -R /path/to/repo/smith /tmp/git-experiment/smith
    
  3. Create a bare clone of smith in a new remotes directory. This will allow us to push the local clone to what we’ll call the remote.

    1
    2
    3
    
    $ cd /tmp/git-experiment
    $ mkdir remotes
    $ git clone --bare smith remotes/smith.git
    
  4. Go into your experimental copy of smith and open the .git/config file and update the url for the remote origin to point to your bare clone of smith.

    1
    2
    
    $ cd smith/.git
    $ vim config
    

    Before:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    [remote "origin"]
        url = git@example.com:smith.git
        fetch = +refs/heads/*:refs/remotes/origin/*
    [branch "master"]
        remote = origin
        merge = refs/heads/master
    [branch "production"]
        remote = origin
        merge = refs/heads/production
    

    After:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    [remote "origin"]
        url = file:///tmp/git-experiment/remotes/smith.git
        fetch = +refs/heads/*:refs/remotes/origin/*
    [branch "master"]
        remote = origin
        merge = refs/heads/master
    [branch "production"]
        remote = origin
        merge = refs/heads/production
    
  5. Go into the remote clone of smith. Instead of .git/config, open config here. Remove the remote origin block. Also remove branch info that ties back to origin. This isn’t strictly necessary, but we’re just going to keep things clean and not run the risk of pushing changes where they shouldn’t go.

    1
    2
    
    $ cd ../remotes/smith.git
    $ vim config
    

    Before:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    [remote "origin"]
        url = git@example.com:smith.git
        fetch = +refs/heads/*:refs/remotes/origin/*
    [branch "master"]
        remote = origin
        merge = refs/heads/master
    [branch "production"]
        remote = origin
        merge = refs/heads/production
    

    After:

    1
    2
    3
    4
    
    [branch "master"]
        merge = refs/heads/master
    [branch "production"]
        merge = refs/heads/production
    
  6. With this done, clone the bare remote repository as a second working copy, if you’d like to check the workflow once you publish your destructive change.

    1
    2
    
    $ cd /tmp/git-experiment
    $ git clone remotes/smith.git smith-two
    
  7. Since there’s a good chance you’ll want to try a few different approaches of your destructive change, make a copy of your test set-up and set it as read only:

    1
    2
    3
    
    $ cd /tmp
    $ cp -R git-experiment git-experiment.orig
    $ chmod -R ugo-w git-experiment.orig
    
  8. Go into your experimental clone and make your destructive change and see what happens with it. You can safely push to your remote and see how that process works with doing a push and then git fetching or git pulling changes into the second copy.

    In my case, I was experimenting with reverting branch merges and resetting and doing git push --force to publish changes. Below, I’m using HEAD@{3} but this could just as easily be a hash reference or a tag.

    1
    2
    3
    4
    
    $ cd /tmp/git-experiment/smith
    $ git checkout production
    $ git reset --hard HEAD@{3}
    $ git push --force
    

    The --force is important here, because otherwise, Git believes you to be doing something it doesn’t think you should. And 99 percent of the time, Git would be correct, but we’re explicitly seeking to do something destructive.

  9. Go check the results of your experiment in the second local clone:

    1
    2
    3
    
    $ cd /tmp/git-experiment/smith-two
    $ git checkout production
    $ git pull --rebase
    
  10. When you’re done, package everything up with a note or just rm -rf /tmp/git-experiment. If you’re saving the iteration, give it a meaningful name:

    1
    2
    
    $ cd /tmp
    $ tar -czf git-experiment.git-reset.tgz git-experiment
    

Results and Iteration

The first experiment is complete. You can shake out what to do and discuss it with your team, safely not affecting what other users are seeing on a repository. Determine what your next steps are, then move your original test aside, copy in the back-up and run further iterations.

In particular, you may have other questions to consider, such as determining what happens if you force a merge commit, provide tags, delete branches, and so on. What’s it going to be like publishing the changes? What’s it going to be like trying to fetch or pull the changes? Are there any other workflow considerations? How are you going to inform other users?

Hopefully, these experiments help you sort that out and provide a well-known path for your users. This contained experiment gives you a margin of safety to answer those questions.

Happy experimenting.

Tool Sharpening: May 17, 2014

For some background on what’s going on here, see the first tool sharpening post

In the past week, I’ve put a heavy focus on tuning up BBEdit. As part of this, I reread the BBEdit 10.x release documentation to get a better sense of features I was overlooking. I found number things to identify and tweak.

  • Installed new-to-me BBEdit language modules
  • Installed two new BBEdit packages
    • Better Tongs for improving text selection and manipulation with some helper scripts
    • Email for working with email composition through BBEdit. This is built for Mutt, but I’m going to see if I can make it useful anyhow
  • Created a BBEdit project with /etc/hosts, ~/.ssh/config and ~/.ssh/known_hosts, files I typically need to touch or update frequently as I work with local Vagrant virtual machines
  • Created a Text Expander shortcut to set-up Jinja2 if blocks for Ansible templates
  • Created a BBEdit project for working with BBEdit packages, scripts and settings
  • Updated BBEdit keyboard shortcuts to:
    • Copy the url of a given file. That ends up looking like file://localhost/foo/bar/baz/bippy/2014-05-18-tool-sharpening.html.md
  • Set-up a Git commit message template
  • Removed some OS X system-level keyboard shortcuts that were interfering with BBEdit-specific shortcuts for manipulating text
    • Unbeknownst to me before reading the 10.x documentation, BBEdit has shortcuts for moving lines up and down and deleting lines without needing to invoke the clipboard or select the whole line. No, this isn’t different than what vi(m) or Emacs provide for, but a particularly good reason for me to review what the capabilities of my editor are.

A larger aim I’ve had with this project is finding somewhat like activities and starting to refactor them so they can be automated. For instance, I want to have a standard way of prefacing new OmniFocus entries I make for ideas. Then, I can trigger that same entry with Text Expander. From there, I expect I could script a pass through OmniFocus and either auto-file things or do some other post-processing with them. The goal I have is to use OmniFocus on my desktop, iPad or iPhone as an entry point, but have a desktop-based script go into my OmniFocus inbox and filter those idea items into text files, like the one I keep as a Markdown list for improving my environment set-up.