Source Code Management
Source Code Management
Version Control Systems
A version control system is critical to managing source code, whether development is occuring in a single- or multiple-developer environment. Version control systems track all changes made to a set of files (allowing for easy, accurate rollback to a clean copy of a codebase when necessary). They provide a failsafe backup mechanism without the overhead of manually-coordinated backups. For groups of developers, a central version control system provides a clean, straightforward mechanism for coordinating each individual's changes to the shared codebase.
CVS: Open-Source Version Control
While anyone with a few hundred thousand dollars to burn is free to purchase a commercial CVS system, an excellent and widely used open-source version control system is free for the downloading: CVS, at http://www.cvshome.org, can be run from servers running a wide variety of operating systems; clients are also available for many operating systems and IDEs.
The Streek project utilizes a CVS repository on canvas.berkeley.edu, a machine maintained by IS&T-CCS.
Change Management Standards
Project Version Numbering
Each project should maintain a three-part version number of the form major-minor-rev (e.g. 1.0.2).
major
This number should increment when a significant number of features are added or when an important technological change has been introduced. Examples:
- a web application has been modified to use the servlet filter mechanism introduced in Servlet specification 2.3.
- an enterprise application has been modified to use container-managed persistence rather than bean-managed persistence.
minor
This number should increment when a single new feature or enhancement has been added. Examples:
- an application has added a calendaring component (new feature).
- an application containing rosters has introduced digital photos of the roster members (enhancement).
rev
This number should increment when a refactoring has taken place or when a bug fix is installed. Examples:
- an application with several similar data access objects has been simplified so that they all use a common superclass (refactoring).
- eliminated out-of-memory error caused by ... (bug fix).
Project Build Number and Timestamp
Each project should maintain a sequential build number that is incremented and timestamped each time the project has a deployment candidate build. Example:
A project contains a build target named "compile" and a build target named "jar". Invoking ant compile would not increment the build number, while ant jar would.
version.properties
Each project should contain a properties file named $project-version.properties where $project is the working or code name of the project. Example:
LMS enterprise integration project name is Strawberry Creek and code name is "streek" so the version properties files would be streek-version.properties.
The properties file should be placed on the classpath of a web application (i.e. $docroot/WEB-INF/classes) or simply included in the jar archive of a support package. A support package should provide a utility class that reports its version information, a web-application should provide a url that does the same.
Deployment Files
Candidate deployment files should be named $project-$deploy-$version.$archive-type. Examples:
- Support Package
- eberk-test-1-0-0_0080.jar
- Web App
- rsf-signup-prod-1-0-1_0099.war
- Enterprise App
- courseweb-qa-1.0.0_0081.ear
Samples
Ant Targets and Properties for Maintaining Version Information
Version Target
The target shown below uses the ant propertyfile task to maintain build number and timestamp:
<target name="version" depends="compile"
description="Maintain build-number and build-date properties.">
<propertyfile file="${version.props}"
comment="streek build number and date">
<entry key="build-number" type="int" operation="+" pattern="0000" />
<entry key="build-date" type="date" value="now" />
</propertyfile>
</target>
Executing this target will create or modify the properties file defined by ${version.props}.
# streek build number and date
# Wed Mar 13 10:16:50 PST 2002
build-date=2002/03/13 10\:16
major=1
minor=0
rev=0
description=Initial release
build-number=0090
Jar Version Target
The target shown builds the current version string:
<target name="jar-version"
description="Builds version-build-number component of of archive file names.">
<property file="${version.props}" />
<property name="version.build"
value="${major}-${minor}-${rev}_${build-number}" />
</target>
EAR-test Target
The target shown builds the project's enterprise archive file for development deployment:
<target name="ear-test" depends="components,war-test,jar-version">
description="Builds current ear file for dev.">
<!-- other tasks omitted -->
<property name="ear.file" value="${code.name}-test-${version.build}.ear" />
<jar jarfile="${ear.file}" basedir="${build.ear.dir}" />
</target>
Java Version Reporter
package edu.berkeley.ist.ebf.util;
import java.util.Properties;
import java.io.IOException;
import java.io.StringWriter;
import java.io.PrintWriter;
import java.io.InputStream;
/**
* Version.java
* Emit project version information.
*
* Created: Tue Mar 5 12:44:47 2002
*
* @author <a href="mailto:randy@socrates.berkeley.edu">Randy Ballew</a>
* @version $Revision: 1.3 $ $Date: 2004/11/19 22:44:20 $ $Author: stevem $
*/
public class Version {
static Properties props;
private static final String PROP_FILE = "/ebf-version.properties";
/**
* Returns <code>String</code> representation of package version information.
*/
public static String getVersion() {
if (props == null)
loadProps();
StringWriter out = new StringWriter();
props.list(new PrintWriter(out));
return "e-berkeley java framework: " + out.toString();
}
// load props as resource on classpath
private static void loadProps() {
InputStream is;
props = new Properties();
Class clazz = edu.berkeley.ist.ebf.util.Version.class;
is = clazz.getResourceAsStream(PROP_FILE);
if (is == null) {
throw new RuntimeException("Couldn't find: " + PROP_FILE
+ " on CLASSPATH");
}
try {
props.load(is);
is.close();
}catch (IOException ioe) {
ioe.printStackTrace();
}
}
// never instantiate this class
private Version (){
}
/**
* command-line query
*/
public static void main(String[] argv) {
System.out.println(getVersion());
}
}// Version


