Jobmerge.rb

What It's For
As of 2006.1 (change 103651), the Perforce server will detect concurrent edits to jobs by comparing the Date field (or any similar field in your jobspec) of an incoming job to the current value. If they differ, it means the user was editing an old version of the job, and they will be rejected with an error message like "Date is a read-only always field and can't be changed...".

This form-in trigger builds on this method of concurrent edit detection and the existence of a spec depot to do automated merging when two users edit a job concurrently. Before the server checks the updated job, the trigger uses the modified date to set up a simple three-way merge that preserves edits made to different fields. If it is successful, the incoming form is replaced with the merge results, which includes an updated Date field (thereby bypassing the error). If the merge fails because the same field was edited by both users, the trigger emits a warning indicating which field is in conflict, but doesn't touch the spec.

Requirements
You need P4Ruby, an existing spec depot, and a server that supports form-in triggers.

Note that to find the base of a merge, the trigger will try to do a print of the spec depot file as of the Date in the spec, so if that timestamp predates the spec depot, the merge won't work (until the job is updated and a fresh version is stored with a fresh timestamp).

Basic Installation
Modify the beginning of the script to supply the required information about your connection settings and your spec depot.

Add a trigger entry like this:

Triggers: jobmerge form-in job "ruby jobmerge.rb %formfile% %user%"

Extra Options
You might have some fields whose values you don't care enough about to block conflicting edits of, or users who you'd rather lose edits than encounter errors (e.g. automated processes or any data produced by them which will just get regenerated anyway). The script lets you resolve these conflicts ahead of time as follows:

accept_yours specifies an array of fields where it's always okay to override what's in the db.

accept_theirs specifies an array of fields where it's always okay to override the user's change.

ignore_users specifies an array of users where it's always okay to ignore their conflicting edits.