Thursday, May 28, 2009

Random Monotone Hacks

I imagine most people who bother to read this blog know that I am rather fond of Monotone, the distributed version control system (a.k.a. DVCS) that we use to maintain Pidgin's code. One of the most convenient features of monotone is that it's extensible via the Lua scripting language. Over our time using monotone, some of us have come across (or written!) some useful snippets of lua code that can be tossed into ~/.monotone/monotonerc to make things easier on us.

The first such snippet is pretty simple. I have three monotone keys that I use for various purposes. One is for Pidgin development, another is for my work on the Guifications project and the Purple Plugin Pack. The third is for my private projects. Instead of needing to remember to specify which key I want to use in specific circumstances, a small snippet of lua can take care of this for me (of course, anyone wanting to use this will need to edit branch patterns and key names appropriately):

function get_branch_key (branch)
d = { ["im.pidgin"]="rekkanoryo@pidgin.im",
["org.guifications"]="rekkanoryo@guifications.org",
["org.rekkanoryo"]="rekkanoryo@rekkanoryo.org"
}

for k, v in pairs(d) do
if string.find(branch, k) then
return v
end
end
end


Monotone also has the ability to cherry-pick revisions from one branch to transplant into another. (Of course, I recognize that other DVCS tools have this capability too.) To do this, ordinarily we would issue a command like mtn pluck some_revision_id within a working copy of the branch we want to transplant the revision to. In our experience, the default log messages for a pluck leave some to be desired. My fellow developer Sadrul wrote this cool bit to add a pluck-log command to Monotone.

The pluck-log command takes a series of individual revision ID's as arguments. For each revision ID in the list of arguments, the command will execute mtn pluck $REV to grab and apply the changes to the workspace. Additionally, the plucked revision's original changelog entry will be inserted into the changelog for the new commit on the current branch. This is particularly useful if you're creating a new release branch by branching from a previous tag, then grabbing individual revisions from your main development branch. This command became popular among us Pidgin developers while we were preparing the Pidgin 2.5.6 release.

Here's the code:

--[[
Pluck a revision with the log and authors filled in for the next commit log.

@author: Sadrul Habib Chowdhury (updated for mtn 0.43 by John Bailey)
--]]

-- pluck-log command
function pluck_log(...)
local revs = {...}
local result
local topsrcdir
local logfile
local log

-- mtn_automate() returns a pair of a boolean and a string; we don't really
-- care about the boolean here, but we need to do something with it.
result, topsrcdir = mtn_automate("get_workspace_root")
topsrcdir = string.gsub(topsrcdir, "\n", "")
logfile = io.open(topsrcdir .. "/_MTN/log", "r")
log = ""

if logfile then
log = logfile:read("*all")
logfile:close()
end

table.foreach(revs,
function (index, rev)
r, sel = mtn_automate("select", rev)

if r == false then return end

for rev in sel:gmatch("%S+") do
r, certs = mtn_automate("certs", rev)

certs:gsub("%s+key \"(.-)\"\n%s*signature \"(.-)\"\n%s*name \"(.-)\"\n%s*value \"(.-)\"\n%s*trust \"(.-)\"",
function(key, sig, name, value, trust)
if name == "changelog" then
log = log .. "*** Plucked rev " .. rev .. " (" .. key .. "):\n" .. value .. "\n"
end
end
)
execute("mtn", "pluck", "-r", rev)
end
end
)

logfile = io.open(topsrcdir .. "/_MTN/log", "w")
logfile:write(log)
logfile:close()
end

register_command("pluck-log", "REVISION1 [REVISION2 [...]]", "Pluck a revision with a good log",
"This plucks a list of revisions, each individually, and adds the changelog of each revision for the next commit log." ..
"\nEXAMPLE:\tmtn pluck-log h:im.pidgin.pidgin deadbeef\n",
"pluck_log")


The resulting log entry will look something like this:

*** Plucked rev 074c5aedf9bbc512331f0d3130f076190b290676 (rekkanoryo@pidgin.im):
Set the default pager host to scsa.msg.yahoo.com; this seems to be what the
official client uses.


Originally, Sadrul wrote this code for mtn 0.42 and earlier, which did not have the mtn automate get_workspace_root functionality. I updated the code to call mtn_automate("get_workspace_root") instead of finding the workspace's root with successive checks of parent directories. The revision ID printed in the log was also truncated to the first 8 digits. Ordinarily, this is fine; however, it's possible that in the future a new revision will be created that has the same first 8 digits and thus the short ID will be ambiguous. I wanted to avoid this situation, so I removed the truncation. I also rearranged a few things to make it easier for me to read. I also have to credit my fellow Pidgin developer Elliott with figuring out that I needed to kill the trailing newline in the string returned from mtn_automate("get_workspace_root").

Hopefully we're not the only ones who find this stuff useful. As I make frequent use of other useful monotone lua hacks, I'll probably post about them here too.

Sunday, May 24, 2009

Pidgin 2.5.6

Well, as most people have noticed by now, we recently released Pidgin 2.5.6. This release was simply a bug and security fix release. Hopefully it will hold everyone over until we can kick 2.6.0 out the door!

Saturday, May 2, 2009

Linux Journal Readers' Choice Award

Yesterday, Linux Journal issued a press release announcing the winners of its annual Readers' Choice Awards. It's an annual event that attracts a lot of attention in the magazine. In their effors to "take the pulse of the Linux community," they run this poll and announce the winners and grant honorable mentions to "strong contenders" in the pool of runners-up.

This year, it's been announced that Pidgin has won a Readers' Choice award for Favorite Communications Tool, a category that we're no stranger to winning--we won this same category last year as well. The landscape is similar as well. This year, we won with 42% of the votes, beating out honorable mention Skype, which received 18% of the votes. Last year, we also garnered 42% of the votes, with Skype and Kopete earning honorable mentions at 17.8% and 12.8% respectively.

Winning this award for the second year in a row reminds us that our work is quite well appreciated, something that is often easy to forget. It also reminds us that every once in a while we need to stand back and thank everyone involved in making Pidgin such a popular project. In this case, we need to thank the 2,000+ people who voted for Pidgin in these Readers' Choice Awards, as well as all our developers, Crazy Patch Writers, drive-by contributors who spot a simple bug and fix it, and our users. All of these people in our community come together to make Pidgin a success as a project, and while we'd be just as happy to work on Pidgin if we had only a few hundred users, we certainly appreciate all of the contributions to our success. Thanks!

Monday, April 20, 2009

And the Summer of Code is set!

Well, Google finally announced the list of accepted students for this year's Summer of Code. You can read about our accepted proposals here. Of course, we're all very excited about the projects we've chosen for this year. We have two students returning to us this year, both with projects that will be hugely important moving forward. Those students are Eric Polino and Sulabh Mahajan.

Eric has chosen to work on GObjectification, which will move libpurple from using our own object system to taking advantage of the GObject capabilities of GLib, one of our existing dependencies. As a result of this project, a massive amount of libpurple infrastructure will change, allowing us to leverage a tried and true typing system and giving plugins an incredible amount of increased flexibility by allowing them to subclass objects and providing interfaces they can implement. This will, of course, have huge rammifications for everyone using libpurple--us, plugin authors, Adium's authors, and even the Instantbird authors. We're confident the result will be worth the effort, though.

Sulabh has volunteered to take on the Privacy Rewrite. What makes this such a daunting task is that the protocols we support provide a very wide range of privacy options, some of which are unique. For example, ICQ supports an "invisible" list and a "visible" list in addition to a "block" list and probably a number of other things that I'm forgetting. Sulabh will have to look at what all our protocols support and provide a foundation in libpurple for all the protocol plugins to provide the privacy options their protocol allows for. Additionally, he'll have to smooth over the differences between protocols to make things consistent.

In addition to these projects, we've accepted two proposals for native Windows user interfaces. Each project will take a different approach to achieve the same goal--providing a user interface that fits better into a Windows desktop than Pidgin currently does. I've already seen a few complaints that we accepted two projects for this. Quite frankly, I don't understand the complaints. We chose two projects for two reasons--first, we want to have the highest possible chance to better serve our Windows users, and second, it's entirely possible that a single Windows UI project won't be able to do enough to satisfy all our users. Having two Windows UIs will allow each to focus on whichever set of users it is more appropriate for.

We've also accepted projects that will make XMPP transports based on libpurple, allow libpurple to use telepathy protocol support in addition to or instead of our own, and using webkit for our message displays. Each of these projects is going to be challenging in its own right. Of all the projects, the XMPP transports will certainly be the least user-visible, as the transports will run on an XMPP server. Conversely, the most visible will probably be the webkit message view, as this will completely replace what we currently use to display messages. By using webkit, it's possible that we'll eventually be able to support Adium Message Styles (no, I'm not promising this support will happen, but it will be possible). The Telepathy plugin will provide some interesting functionality by allowing us to use nothing but telepathy for protocol support if the user so chooses.

There are other deeper details in these projects, but I've already wasted too much time obsessing over this post and discussing the larger projects in detail. I'll leave further discussion of the technical merits and details of projects to the students and mentors. Needless to say, this post could have gone on just about forever. ;)

Overall, this Summer of Code looks like it will be one of our best. Good luck to all our students!

Thursday, March 26, 2009

It's that time again...

Well, once again we've come to the student application phase of Google's Summer of Code program. We're several days into the process, and we've seen a marked decrease in our intake of student applications compared to prior years. Why is anybody's guess, but I'm personally hoping it means that potential applicants are spending more time polishing their applications before submitting.

Based on the applications we've seen so far, I'd like to publicize a few notes for applicants:
  • Provide a detailed timeline for your project. "I expect to complete work in 10 weeks" doesn't cut it here. Tell us what milestones you expect to achieve and how far along. You could instead estimate how long a specific goal will take to implement. Yes, your estimate could ultimately prove wrong, but that's not necessarily the end of the world. We really want to see that you have a concept of time management and prioritization.
  • Don't plagiarize. If we know you're plagiarizing, we'll invalidate your application. If you can't deliver an application without plagiarizing, you shouldn't be applying. We don't mind if you use some of the text on our ideas page to help with the abstract, but keep in mind that a serious application won't rely on simply copying and reformatting what we've already said.
  • Don't be afraid to come up with a unique idea! The ideas page are not the only ideas we'll entertain. We love to see well thought-out, original ideas, especially ones that make us wonder why no one proposed it before.
  • Make sure your proposal is for a specific project idea. A general "I want to work with Pidgin for the summer" is a sure ticket to the reject bin.
  • You don't have to write an encyclopedia for the application, but you do have to give us something to work with. There's an old adage that "less is more." Sometimes that's true. Sometimes the opposite is true. The point here is that you should be verbose enough to explain your idea, but don't ramble. I know this can be difficult to judge. Just re-read the application, make sure it makes sense, and make sure it doesn't drag on needlessly.
  • You have to apply using the SoC webapp, not our mailing lists. We have to have applications submitted via the SoC webapp in order to review them and have them in the running for our student slots. This is a Google thing, and it makes everyone's lives a lot easier.
  • The application isn't final until submissions close. We will provide feedback on your application if it needs work. You can modify your application to address our feedback until applications close. Use this to your advantage!
  • We don't yet know who will mentor any given project. We don't assign final mentors and backup mentors to projects until we have decided which projects we want to accept. Asking us about this is just wasting your time.
  • We expect you to treat the project as a full-time job. That means at least 35 hours per week. We want to make sure everyone gets the most out of Google's money, and this is one way to do that. Since you'll technically be a contract worker, we expect the contracted work (your project) to take priority.
  • We expect you to remain actively involved with us after the Summer of Code finishes. Quite frankly, if you're going to collect the checks and run, you're missing the entire point. The Summer of Code is intended to attract new contributors and get them involved in open source software, turning them into long-term contributors. Participating in the Summer of Code and then disappearing isn't serving that intention, and leaving us with code we have to maintain ourselves is quite rude. If that's your intention, please don't apply. Let the potential for acceptance go to someone who will stay with us.
Keep these in mind, and happy applying!

Thursday, February 26, 2009

Saved Statuses for Fun and Profit

From my limited experience with Pidgin users among my family and coworkers, I've discovered that a number of users don't know about Pidgin's saved status features and instead use only the transient statuses created directly in the status selector by typing a message. Some users don't even realize that they can select a previously used transient status from the middle section of the status selector's menu. As an attempt to spread deeper insight into Pidgin, I submit for your reading this saved status tutorial.

Overview of Saved Statuses

In Pidgin, a saved status gives you a considerable amount of flexibility. For example, if you use six accounts, three of which are personal and three of which are for work, you can use a saved status to have your work accounts away while your personal accounts are available and vice-versa. Or, if the text box you get from using the status selector irritates you, you can use saved statuses to get rid of it forever.

Creating a Simple Saved Status

Let's start with two basic saved statuses--one Available status and one Away status.

Click the status selector at the bottom of the buddy list window. You should see something like this:


Select the "New status..." entry. You should see something similar to this:


The fields here should be pretty obvious and self-explanatory. The title will be what you see in the status selector menu. Generally, I use a descriptive title, such as "Away - Sleeping" or "Available - no message," that will quickly identify the message's contents to me without needing to read the message. For this example, I'll use "Away - example."

For Status, obviously you want to choose one of the basic statuses listed--Available, Away, Invisible, Extended Away, Offline, Do Not Disturb, or Invisible. If you use only one account, your choices could be significantly different. For this example, we'll accept the default of Away.

in the Message box, type your status message. For my example Away status, I'll use the message "Away for the sake of being away."

Click Save. Alternatively, if you want to use this status now, click "Save & Use." You could also click "Use," but then the status would not be saved.

Now, repeat the process for an Available status. In this example, I'll have a title of "Available - no message", a status of Available, and a blank message.

Now, if you select "Saved statuses..." from the buddy list window, you should see something like this, but probably with a lot fewer statuses listed:


Creating a Complex Saved Status

A complex saved status is where the real power of saved statuses becomes obvious. Let's modify the existing away example we created. Select it in the saved status list and click "Modify..." Now click the expander just to the side of "Use a different status for some accounts" and observe the list of accounts that appears.

Put a checkbox in one of your accounts. For this example, I'll use my pidgin.im XMPP account. Now you see a much simpler new dialog:


For simplicity's sake in this example, I will choose "Extended away" as the status and use "test" as my message. After clicking OK, I return to the modify status dialog, to see something similar to this:


Now you can click "Save" or "Save & Use." This gives you essentially the simplest form of complex status--one in which only one account differs in status from the other accounts. Using this status will cause all but that one account to appear as away, and cause that one specific account to appear as extended away (note the clock vs. the circular sticky note).

Using a Saved Status

To use a saved status, you can select it in the status selector's menu if it's listed. If it's not listed, simply click "Saved statuses..." in the status selector to bring up the Saved Statuses dialog, then select the status you want and click "Use." The status should now be remembered in the "popular statuses" (middle) area of the status selector menu. Of course, with disuse or use of a large number of statuses, a given saved status can fall out of the saved statuses list, in which case you'll need to repeat the process of finding it again. If you use the statuses a lot, though, this won't be a problem.

Practical Applications

Saved statuses aren't for everyone, of course. They do provide a number of possible complex status combinations limited only by the number of accounts you have in Pidgin. They also let you get rid of the ugly text box for status messages for as long as you use saved statuses. They also offer a relatively quick setup time that allows you to create your status once and use it as many times as you want without ever having to think about how to configure the status again.

Enjoy playing with your newfound saved statuses!

You Can't Please Anyone

Occasionally we make changes to Pidgin which displease some subset of our users. For an example, I'll give a brief history lesson.

We released a series of six betas leading up to our name change to Pidgin. In our first beta, 2.0.0beta1, we introduced the concept of the status selector. At this time it was a rather crude creation; it simply mashed a few widgets together to accomplish the basic tasak. When we introduced this status UI, we also introduced the concept of two ways to handle status messages. The first, and most obvious, way to handle status messages was to present a text box when selecting a basic status from the status selector in which to enter the status message. The other method was a bit more complex but significantly more powerful--this was the saved statuses feature accessible from the "Saved statuses..." entry in the status selector's menu.

When we first inroduced this UI, the behavior of the text box was to retain the status message whenever the status changed from, for example, available to away or from away to available. A number of people, myself included, were not happy with this. Eventually we changed the behavior to clear the message on status change. This displeased another group of users. Now here we are, two years later. We changed back to retaining the status message on status changes pursuant to a discussion on the development mailing list. Again, we've displeased a group of users.

The problem with this particular change is that both behaviors are valid, and fans of each behavior think their preferred behavior is the only correct behavior. Of course, now that we acknowledge that both behaviors are valid, many users' first reaction would be to say "Make it a preference!" Of course, that's a whole new argument in itself, but this is such a minor feature that it's not important enough to warrant a preference.

Note that the people who don't like the retention of the status message are inconvenienced by a single keystroke if the intended result is to clear the message, and not inconvenienced at all if the intention is to use a new message. This inconvenience, or lack thereof, is because we chose to implement the retention such that the retained message is highlighted. This means that simply hitting backspace will clear the message and typing an entirely new message will replace the message text with what you've typed.

Simply put, this change is just further proof that when you're involved in a project of any significance, you're damned if you do and damned if you don't, no matter what you do or don't.

I'm sure this post will inspire some criticism. For the time being, though, I think it's best if we ride this wave of criticism out for a bit and see if this is simply resistance to change or a genuine "problem."