“Next/Previous Tab” Keyboard Shortcuts on Windows

On my Windows laptop, I use the following four programs with tabbed interfaces on a regular basis:

  • Firefox
  • Thunderbird
  • Instantbird
  • Komodo IDE

(I’d love to have tabs in my Windows terminal app of choice, Mintty, but its developer thinks tabs should be implemented at the window manager level.)

Unlike on my Mac, all those programs implement the same keyboard shortcut for switching to the previous/next tab, and it’s a simple one with just a two-key chord: Control + PageUp / PageDown.



“Next/Previous Tab” Keyboard Shortcuts on Mac

On my Mac, I use the following five programs with tabbed interfaces on a regular basis:

  • Firefox
  • Thunderbird
  • Adium
  • Terminal
  • Komodo IDE

And those programs implement the following five different keyboard shortcuts for switching to the previous/next tab:

  • Control + PageUp / PageDown (Firefox, Thunderbird)
  • Command + LeftArrow / RightArrow (Adium)
  • Command + PageUp / PageDown (Komodo IDE)
  • Command + Shift + [ / ] (Terminal)
  • Command + Shift + LeftArrow / RightArrow (Terminal)



gitflow vs. the SDK

gitflow is a model for developing and shipping software using Git. Add-on SDK uses Git, and it too has a model, which is similar to gitflow in some ways and different in others. Here’s a comparison of the two and some thoughts on why they vary.

First, some similarities: both models use multiple branches, including an ongoing branch for general development and another ongoing branch that is always ready for release (their names vary, but that’s a trivial difference). Both also permit development on temporary feature (topic) branches and utilize a branch for stabilization of the codebase leading up to a release. And both accommodate the occasional hotfix release in similar ways.

(Aside: gitflow appears to encourage feature branches, but I tend to agree with Martin Fowler through Paul Julius that continuously integrating with a central development branch is preferable.)

Second, some differences: the SDK uses a single ongoing stabilization branch, while gitflow uses multiple short-lived stabilization branches, one per release. And in the SDK, stabilization fixes land on the development branch and then get cherry-picked to the stabilization branch; whereas in gitflow, stabilization fixes land on the stabilization branch and then get merged to the development branch.

(Also, the SDK releases on a regular time/quality-driven “train” schedule similar to Firefox’s, while gitflow may anticipate an irregular feature/quality-driven release schedule, although it can be applied to projects with train schedules, like BrowserID.)

A benefit of gitflow’s approach to stabilization is that its change graph includes only distinct changes, whereas cherry-picking adds duplicate, semi-associated changes to the SDK’s graph. However, a downside of gitflow’s approach is that developers must attend to where they land changes, whereas SDK developers always land changes on its development branch, and its release manager takes on the chore of getting those changes onto the stabilization branch.

(It isn’t clear what happens in gitflow if a change lands on the development branch while a release is being stabilized and afterward is identified as being wanted for the release. Perhaps it gets cherry-picked?)

Overall, these models seem fairly similar, and it wouldn’t be too hard to make the SDK’s be essentially gitflow. We would just need to stipulate that developers land stabilization fixes on the stabilization branch, and the release manager’s job would then be to merge that branch back to the development branch periodically instead of cherry-picking in the other direction.

However, it isn’t clear to me that such a change would be preferable. What do you think?


Administer Git? Get a job!

As I mentioned recently, Git (on GitHub) has become a popular VCS for Mozilla-related projects.

GitHub is a fantastic tool for collaboration, and the site does a great job running a Git server, but given the importance of the VCS, and because Mozilla’s automated test machines don’t have access to servers outside the Mozilla firewall, Mozilla should run its own Git server (that syncs with GitHub, so developers can continue to use that site for collaboration).

Unfortunately, the organization doesn’t have a great deal of in-house Git server administration experience, but we’re hiring systems administrators, so if you grok Git hosting and meet the other requirements, send in your resume!


Why the Add-on SDK Doesn’t “Land in mozilla-central”

Various Mozillians sometimes suggest that the Add-on SDK should “land in mozilla-central” and wonder why it doesn’t. Here’s why.

The Add-on SDK depends on features of Firefox (and Gecko), and the SDK’s development process synchronizes its release schedule with Firefox’s. Nevertheless, the SDK isn’t a component of Firefox, it’s a distinct product with its own codebase, development process, and release schedule.

Mozilla makes multiple products that interact with Firefox (addons.mozilla.org, a.k.a. AMO, is another), and distinct product development efforts should generally utilize separate code repositories, to avoid contention between the projects regarding tree management, the stages of the software development lifecycle (i.e. when which branch is in alpha, beta, etc.), and the schedules for merging between branches.

There can be exceptions to that principle, for products that share a bunch of code, use the same development process, and have the same release schedule (cf. the Firefoxes for desktop and mobile). But the SDK is not one of those exceptions.

It shares no code with Firefox. Its process utilizes one fewer branch and six fewer weeks of development than the Firefox development process, to minimize the burden of branch management and stabilization build testing on its much smaller development team and testing community. And it merges its branches and ships its releases two weeks before Firefox, to give AMO and addon developers time to update addons for each new version of the browser.

Living in its own repository makes it possible for the SDK to have these differences in its process, and it also makes it possible for us to change the process in the future, for example to move up the branch/release dates one week, if we discover that AMO and addon developers would benefit from three weeks of lead time; or to ship twice as frequently, if we determine that doing so would get APIs for new Firefox features into developers’ hands faster.

Finally, the Jetpack project has a vibrant community of contributors (including both organization staff and volunteers) who strongly prefer contributing via Git and GitHub, because they find it easier, more efficient, and more enjoyable, and for whom working in mozilla-central would mean taking too great a hit on their productivity, passion, and participation.

Mozilla Labs innovates not only on features and user experience but also on development process and tools, and while Jetpack didn’t lead the way to GitHub, we were a fast follower once early experiments validated its benefits. And our experience since then has only confirmed our decision, as GitHub has proven to be a fantastic tool for branch management, code review/integration, and other software development tasks.

Other Mozillians agree: there are now almost two hundred members and over one hundred repositories (not counting forks) in the Mozilla organization on GitHub, with major initiatives like Open Web Apps and BrowserID being hosted there, not to mention all the Mozilla projects in user repositories, including Rust and Zamboni.

Even if we don’t make mozilla-central the canonical repository for SDK development, however, we could still periodically drop a copy of the SDK source against which Firefox changes should be tested into mozilla-central. And doing so would theoretically make it easier for Firefox developers to run SDK tests when they discover that a Firefox change breaks the SDK, because they wouldn’t have to get the SDK first.

But the benefit to Firefox developers is minimal. Currently, we periodically drop a reference to the SDK revision against which Firefox changes should be tested, and developers have to do the following to initiate testing:

  wget -i testing/jetpack/jetpack-location.txt -O addon-sdk.tar.bz2

  tar xjf addon-sdk.tar.bz2
  cd addon-sdk-[revision]
  source bin/activate
  cfx testall --binary path/to/Firefox/build

We can simplify this to:


  cd addon-sdk
  source bin/activate
  cfx testall --binary path/to/Firefox/build

Whereas if we dropped the source instead of just a reference to it, it would instead be the only slightly simpler:

  cd testing/jetpack/addon-sdk

  source bin/activate
  cfx testall --binary path/to/Firefox/build

Either of which can be abstracted to a single make target.

But if we were to drop source instead of a reference thereto, the drops would be larger and riskier changes. And test automation would still need to be updated to support Git (or at least continue to use brittle Git -> Mercurial mirroring), in order to run tests on SDK changes, which periodic source drops do not address.

Now, this doesn’t mean that no SDK code will ever land in mozilla-central.

Various folks have discussed integrating parts of the SDK into core Firefoxincluding stable API implementations, the module loader, and possibly the bootstrapperto reduce the size of addon packages, improve addon startup times, and decrease addon memory consumption. I have written a very preliminary draft of a feature page describing this work, although I do not think it is a high priority at the moment, relative to the other priorities identified in the Jetpack roadmap.

And Dietrich Ayala recently suggested integrating the SDK into core Firefox for use by core features, by which he presumably also means the API implementations/module loader/bootstrapper rather than the command-line tool for testing and packaging addons.

Nevertheless, I am (and, I suspect, the whole Jetpack team is) even open to discussing integration of the command-line tool (or its replacement by a graphical equivalent), merging together the two products, and erasing the distinction between them, just as Firefox ships with core features for web development.  We’ve even drafted a feature page for converting the SDK into an addon, which is a big step in that direction.

But until that happens, farther on up the road, the SDK is its own product that we develop with its own process and ship on its own schedule. And it has good reason to live in its own repository, and a Git one at that, as do the many (and growing number of) other Mozilla projects using similar processes and tools, which our community-wide development, collaboration, and testing infrastructure must evolve to accommodate.


SDK Training and More at Add-on-Con

Next Wednesday, December 8, I’ll be at Add-on-Con.

In the morning, I’ll conduct a training session introducing Mozilla’s new Add-on SDK, which makes it faster and easier to build Firefox add-ons. Afterwards, I’ll be around and about to discuss add-ons and answer questions about the SDK and add-on development generally.

Lots of other Mozilla folks will also be on hand over the course of the two-day conference, including Dave Townsend, Jorge Villalobos, Jeniffer Boriss, Mark Finkle, and Justin Scott. A rockin’ time should be had by all. Join us!


Further Adventures In Git(/Hub)ery

This evening I decided to check if there were any outstanding pull requests for the SDK repository (to which I haven’t been paying attention).

There were! The oldest was pull request 29 from Thomas Bassetto, which contains two small fixes (first, second) to the docs.

So I fetched the branch of his fork in which the changes reside:

$ git fetch https://github.com/tbassetto/addon-sdk.git master

But that branch (and the fork in general) is a few weeks out-of-date, so “git diff HEAD FETCH_HEAD” showed a bunch of changes, and it was unclear how painful the merge would be.

Thus I decided to try cherry-picking the changes, my first time using “git cherry-pick“.

The first one went great:

$ git cherry-pick 8268334070d03a896d5c006d1b4db94d4cb44b17
Finished one cherry-pick.
[master ceadb1f] Fixed an internal link in the widget doc
 1 files changed, 1 insertions(+), 1 deletions(-)

Except that I realized afterward I hadn’t added “r,a=myk” to the commit message. So I tried “git commit --amend” for the first time, which worked just fine:

$ git commit --amend
[master 2d674a6] Fixed an internal link in the widget doc; r,a=myk
 1 files changed, 1 insertions(+), 1 deletions(-)

Next time I’ll remember to use the “--edit” flag to “git cherry-pick“, which lets one “edit the commit message prior to committing.”

The second cherry-pick was more complicated, because I only wanted one of the two changes in the commit (in my review, I had identified the second change as unnecessary); and, as it turned out, also because there was a merge conflict with other commits.

I started by cherry-picking the commit with the “--no-commit” option (so I could remove the second change):

$ git cherry-pick --no-commit 666ad7a99e05e338348dfc579d5b1f75e8d3bb1b
Automatic cherry-pick failed.  After resolving the conflicts,
mark the corrected paths with 'git add <paths>' or 'git rm <paths>' and commit the result.
When commiting, use the option '-c 666ad7a' to retain authorship and message.

The conflict was trivial, and I knew where it was, so I resolved it manually (instead of trying “git mergetool” for the first time), removed the second change, added the merged file, and committed the result, using the “-c” option to preserve the original author and commit message while allowing me to edit the message to add “r,a=myk”:

$ git add packages/addon-kit/docs/request.md
$ git commit -c 666ad7a
[master 774d1cb] Completed the example in the Request module documentation; r,a=myk
 1 files changed, 1 insertions(+), 0 deletions(-)

Then I used “gitg” and “git log master ^upstream/master” to verify that the commits looked good to go, after which I pushed them:

$ git push upstream master
[git's standard obscure and disconcerting gobbledygook]

Finally, I closed the pull request with this comment that summarized what I did and provided links to the cherry-picked commits.

It would have been nice if the cherry-picked commit that didn’t have merge conflicts (and which I didn’t change in the process of merging) had kept its original commit ID, but I sense that that is somehow a fundamental violation of the model.

It would also have been nice if the cherry-picked commit messages had been automatically annotated with references to the original commits.

But overall the process seemed pretty reasonable, it was fairly easy to do what I wanted and recover from mistakes, and the author, committer, reviewer, and approver are clearly indicated in the cherry-picked commits (first, second).

[Also posted to the discussion group.]