This is, by itself, a fine practice. The curious part to me has always been that Perforce (our version control software) has the ability to send out emails for every check-in. My old boss would subscribe to every check-in in our branch, for instance, so she could keep tabs on what the group was doing. But that's not what we use.
Over time, I've come to understand the rationale of our redundant workflow. People can attach screenshots (I do work for a game company, after all) and the subject line can provide project categorization and a short description that perforce doesn't know about. Also, culturally speaking, if everyone in your company does this and you don't, people have a harder time figuring out what you do.
But I still find the workflow annoying. You submit your changes in Perforce. Then you go to the "submitted changelists" pane and double-click on the changelist you just submitted. You select all the text and then copy it (this view has more info in it — such as the list of files — than the text you wrote when submitting, so you can't just use that). You alt-tab over to Outlook, open a new message, address it to the studio email address, attach your pithy subject, and then copy and paste in the changelist info. (You also use this moment to attach screenshots, if relevant.) You send the email and then alt-tab back over to Perforce (or your IDE) to do more work.
I finally decided to automate the process a bit using Ruby to tie together Outlook and Perforce. I set it up to work with my needs, so it may be of limited use to anyone else. For instance, we have a custom of using "mini" to indicate minor, one-liner types of fixes. Otherwise, I tend to use "submit." Also, sometimes I want to aggregate a few recent changelists in one email. That's what the
-count
argument does. I also put all the config info (username, password, etc.) into a separate yaml file so that I can distribute the script without sending around my network password. Finally, I specified a sendMode of either Display or Send. Display opens the email for you and lets you customize it. Send just kicks it out the door. The former is useful for screenshots and the like. The sendMode
and project
config file options provide defaults, but they can be overridden. Sometimes I do work in another functional project and need to change the email accordingly.You'll need p4Ruby to make this work. (I think the OLE stuff is built in to the Ruby for Windows installation.) Perforce returns information in sort of an odd way: a changelist will have the list of revisions as one field and the list of files as another. The indexes line up, but it takes a bit more work to get the info you want.
There are no doubt better ways to do this: I'm still fumbling around with Ruby.
require 'win32ole'
require 'P4'
require 'yaml'
is_mini = false
subject = ""
num_cls = 1
def assert_value(obj,message_on_fail)
if !obj
puts message_on_fail
Kernel.exit
end
end
# load the yaml settings first
assert_value((File.exists? 'p4_email.yaml'),'You must have a p4_email.yaml file in the same directory')
config = YAML.load_file 'p4_email.yaml'
sendMode = config['sendMode']
project = config['project']
assert_value(config['p4User'],'No p4User specified!')
assert_value(config['p4Password'], 'No p4Password specified!')
assert_value(config['p4Client'], 'No p4Client specified!')
assert_value(config['p4Host'],'No host specified!')
# now parse ARGs. In particular, see if the user has overridden config settings
ARGV.each_index do |index|
if ARGV[index] == '-sendMode'
sendMode = ARGV[index+1]
# check value
assert_value(sendMode == 'Display' || sendMode == 'Send',"Invalid sendMode value: #{sendMode}")
end
if ARGV[index] == '-project'
project = ARGV[index+1]
end
if ARGV[index] == '-mini'
is_mini = true
end
if ARGV[index] == '-subject'
subject = ARGV[index+1]
end
if ARGV[index] == '-count'
num_cls = ARGV[index+1].to_i
end
end
puts "count: #{num_cls}"
assert_value(project,'No project specified! Add to p4_email.yaml or use the -project command-line argument')
# set up p4 connections
p4 = P4.new
p4.client = config['p4Client']
p4.password = config['p4Password']
p4.user = config['p4User']
p4.host= config['p4Host']
p4.connect
p4.run_login
# retrieve recent changelists
lists = p4.run_changes('-u',p4.user,'-m',num_cls, '-s','submitted')
#get the id
msg_body = ""
(0...(num_cls)).each_with_index do |obj,index|
cl_num = lists[index]['change']
#get the full details for that cl
cl_full = p4.run_describe(cl_num)[0]
cl_action_list = cl_full['action']
cl_rev_list = cl_full['rev']
msg_body = msg_body + "Change #{cl_num} by #{p4.user}@#{p4.client}\n\n"
msg_body = msg_body + cl_full['desc'] + "\nAffected files ...\n\n"
cl_full['depotFile'].each_index do |index|
msg_body = msg_body + cl_full['depotFile'][index] +\
"##{cl_rev_list[index]} " + cl_action_list[index] + "\n"
end
end
p4.disconnect
#compose email
outlook = WIN32OLE.new('Outlook.Application')
message = outlook.CreateItem(0)
submit_type = "submit"
if is_mini
submit_type = "mini"
end
message.Subject = "p4 [#{project}] #{submit_type}: #{subject}"
message.Body = msg_body
message.To = '[studioemail]'
# todo: should invoke the method by using reflection
if sendMode == 'Display'
message.Display
elsif sendMode == 'Send'
message.Send
end