Version Control for Forms and Fragments

It’s a little late in the season for spring cleaning, but better late than never. I have struggled with how best to deliver and (more importantly) update the samples delivered on this blog. Normally what I do is add a note to the blog entry where the sample was introduced and then hope that people notice (do RSS readers notify you when an entry gets updated?) But then there’s the problem where a framework has evolved over a series of blog entries. Which entry has the most recent version of the validation framework? Dunno. How do you know if you’re using the most recent version of the debugger or the lint checker?  What if I find a bug in the tool and want to send you an update? How do I best communicate that to you?

I am fairly certain that I’m not the first to struggle with these problems. Many of you will have similar issues in distributing forms to your end-users. Given that, I am working on a methodical way to track content. The result is a framework that you could adapt for your own form distribution.

Here’s my revised plan for distributing content:

  • Distribute script objects as fragments (in addition to embedding them inside the samples)
  • Embed version information in both the sample forms and fragments
  • Post an inventory XML file with version information on the blog site
  • Embed script in the sample forms so they can “call home” and check their version number(s)

Distribute as fragments

From now on when I distribute a sample I will also distribute any re-usable pieces (subforms or scripts) as downloadable fragments (XDP files).

The sample forms will have their fragment references embedded. This is to make it easier to open the sample in Designer — without the need to re-connect the fragments.

Embed Version History

Once version information is embedded in a form or fragment, then we have the basis for checking whether there is a newer version available.  The question is how best to embed the version information.

My first thought was to embed the information in the form metadata. But there is not yet enough tooling and support around metadata to make this work well. In the long run, I think this would be the right solution. But in the short term we can’t easily get there from here.

The next best solution is to embed the version information in script object variables. Here is the script object variable for the fragment used in the sample that allows formcalc to be called from JavaScript:

var oVersionInfo = {
  identifier: "FormCalcFromJavaScript",
  assetType: "fragment",
  description: "JavaScript access to FormCalc built-in functions.", 
  currentVersion: 2,
};

Some interesting things to note:

  • The same script object is used to describe both fragments and forms.
  • The variable must be named “oVersionInfo” in order to be detected by the version checking mechanism.
  • A form that uses multiple fragments will have several of these “oVersionInfo” variables embedded.

Inventory

Having version information in the form is the first step.  The second step is to have a central location to store the up to date version information. To this end, I’ve posted an "inventory" at: http://blogs.adobe.com/formfeed/Samples/Inventory.xml

The inventory will be used to compare the version information in a given form against the most recent available. The xml for the inventory looks very similar to the JavaScript object:

<inventory xmlns="http://blogs.adobe.com/formfeed/">
  <asset>
    <identifier>PhoneHome</identifier>
    <assetType>fragment</assetType>
    <description>Compare version info to the latest</description>
    <currentVersion>1</currentVersion>
    <filename>checkVersion.xdp</filename>
  </asset>

  <asset>
    <identifier>FormCalcFromJavaScript</identifier>
    <assetType>fragment</assetType>
    <description>Support for FormCalc functions</description>
    <currentVersion>2</currentVersion>
    <filename>scFormCalc.xdp</filename>
  </asset>

  <asset>
    <identifier>ExceptionHandler</identifier>
    <assetType>fragment</assetType>
    <description>Handle exception objects</description>
    <currentVersion>2</currentVersion>
    <filename>scMessage.xdp</filename>
  </asset>

  <asset>
    <identifier>FCfromJSSample</identifier>
    <assetType>form</assetType>
    <description>Demonstrates how to call FC from JS.</description>
    <currentVersion>2</currentVersion>
    <filename>FormCalcFromJS.pdf</filename>
  </asset>
  …
</inventory>

Phone Home

Now to put it all together.  We need some script to check whether a form has the most recent versions of all its content.

The first step is to update the sample from the “FormCalc from JavaScript” entry.  I added support for FormCalc’s Get() function.   In order to retrieve the inventory, the form performs a call:

fc.func.Get(“http://blogs.adobe.com/formfeed/Samples/Inventory.xml”);

(Acrobat/Reader will warn you about this request)

The result then loaded into an E4X XML object. Meanwhile we scan the rest of the form looking for script objects with an “oVersionInfo” variable. We compare the version information embedded in the form against the version information in the inventory and notify regarding any available updates.

The fragments to make this all possible are:

scFormCalc.xdp : The subform holding the FormCalc functionality.

scMessage.xdp : Updated exception handling methods

scVersion.xdp : Contains the logic for the "phone home" capability — compare the form version information against the inventory.

scXML.xdp : Has a method for trimming an XML string so that E4X can load i
t.

Futures

Server-side logic

I chose to store the version checking logic in the sample form itself.  A better solution would be for that logic to reside on the server.  That way, the version checking logic could be updated without changing all the distributed forms.  But given my limitation of distributing via a blog site, I went with the client side logic.

Tools

I have a couple house-keeping tools I’m using that are not ready for prime time:

  • A form to harvest version information from a fragment/form and update Inventory.xml
  • A form to externally introspect a form for the latest version information (as opposed to embedding this logic in the form itself)

If there’s interest, I will consider polishing these to the point where they can be shared.

Source Control

I’ve looked at the versioning problem primarily from a distribution point of view.  I didn’t try to do anything from the perspective of source control.  There are things that could be done to make source code control easier:

  • Store revision details — e.g. Store comments, dates, author info for each change made to a form or fragment
  • A tool for tracking differences between versions of forms. e.g. report on all added/removed/modified fields/subforms/scripts etc between versions.
  • Integration of version information with form metadata

(No promises that I’ll manage to get to these topics.)

Samples

In the short term my challenge is to update a bunch of the samples I’ve previously distributed.