= OpenSAF Developer's Guide = {{{ #!comment Original author: John Wright }}} {{{ #!numberedsections [[PageOutline]] = Introduction = The OpenSAF project uses the [http://www.selenic.com/mercurial/ Mercurial] distributed revision control system. This document aims to introduce developers to the concepts of distributed revision control, and to clarify the branching and tagging conventions specific to the OpenSAF project. I will assume that the reader is familiar with the basic concepts of revision control, perhaps with a tool such as Subversion. Where the concepts differ, I will provide examples to illustrate them. This document is not meant to be a reference for Mercurial. For a very good introduction to Mercurial (and to the concepts of distributed revision control), please read Bryan O'Sullivan's book ''[http://hgbook.red-bean.com Distributed revision control with Mercurial]''. = Getting started = == Required software == {{{ #!comment FIXME: Build dependencies for OpenSAF? }}} You can download Mercurial from [http://www.selenic.com/mercurial/]. It is also packaged in many Linux distributions. == Setting a user name for Mercurial == A username is recorded with each commit to a Mercurial repository. The value of the username is free-form, but it is typically in the form `John Doe `. To set this, either set the `HGUSER` environment variable, or set it in the file `.hgrc` in your home directory. For example, mine has these contents: {{{ [ui] username = John Wright }}} == Checking out the source == With distributed revision control systems like Mercurial, your working copy of the source actually contains the full revision history of the project, rather than just the most recent revision. This, as well as some smart merging algorithms, allows you to make changes and commit them without being online. When you're ready for your changes to go public, you push them to an appropriate location. Each OpenSAF developer with SSH access has a web directory set up with a CGI script for simple publishing of Mercurial repositories. The most common way to create a branch with Mercurial is with the `hg clone` command. These branches could be short-lived---for example, a temporary clone to pull in changes from an external repository and make sure they merge cleanly---or long-lived---such as a branch for updates to a previously released version. Since cloning is "cheap" in Mercurial---it is fast, and the clone can last for as short or as long a time as you like---you will see it used very frequently. I will often use the terms "branch," "clone," and "repository" interchangeably in this document. (Note, recent versions of Mercurial have support for multiple "named branches in the same repository, with a `branch` command for dealing with them. This document does not make use of this feature, so this shouldn't cause any ambiguity. For more information, see [http://hgbook.red-bean.com/hgbookch8.html#x12-1660008.6 Chapter 8, Section 6] of ''Distributed revision control with Mercurial''.) Note that "master repository" term used throughout this document equals the "trunk" term used in [https://devel.opensaf.org/wiki/Technical_Development_Process OpenSAF Development Process]. To get a copy of the master repository, use the `hg clone` command. The first argument to `clone` is the URL or filesystem path to the repository, and the second (optional) argument is the destination directory. Without a second argument, Mercurial uses the last part of the URL as the destination directory. So, to put a copy of hg:opensaf in a directory called `opensaf` in the current working directory, execute the following command: {{{ ~/opensaf$ hg clone http://devel.opensaf.org/hg/opensaf destination directory: opensaf requesting all changes adding changesets adding manifests adding file changes added 3 changesets with 2368 changes to 2367 files 2367 files updated, 0 files merged, 0 files removed, 0 files unresolved }}} = Working on OpenSAF = == Making a simple change == It's often handy to have a "pristine" copy of the master repository, so let's clone the copy we just made: {{{ ~/opensaf$ hg clone opensaf opensaf-scratch 2367 files updated, 0 files merged, 0 files removed, 0 files unresolved }}} Now, suppose we need to add a file to the project. After creating the file, we just use `hg add`: {{{ ~/opensaf$ cd opensaf-scratch ~/opensaf/opensaf-scratch$ echo "bar" > foo ~/opensaf/opensaf-scratch$ hg add foo }}} Before committing a change, it's good to see what we have changed: {{{ ~/opensaf/opensaf-scratch$ hg status A foo ~/opensaf/opensaf-scratch$ hg diff diff -r cb8e59469658 foo --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/foo Mon Jan 07 14:45:37 2008 -0700 @@ -0,0 +1,1 @@ +bar }}} The output from the `status` command indicates that we have added a file, and the `diff` command outputs a unified diff representation of the changes. Now we're ready to commit: {{{ ~/opensaf/opensaf-scratch$ hg commit -m 'Added the foo file' ~/opensaf/opensaf-scratch$ hg log changeset: 3:b67adc860aba tag: tip user: John Wright date: Mon Jan 07 14:46:16 2008 -0700 summary: Added the foo file changeset: 2:cb8e59469658 user: John Wright date: Mon Jan 07 14:37:03 2008 -0700 summary: Naming scheme changed: 1.0-5 => 1.0.5 . Update .hgtags to reflect. changeset: 1:88cd878f6f8c user: john.wright@hp.com date: Thu Jan 03 12:57:51 2008 -0700 summary: Added tag 1.0-5 for changeset 1c7624641cfa changeset: 0:1c7624641cfa tag: 1.0.5 user: john.wright@hp.com date: Thu Jan 03 11:47:11 2008 -0700 summary: Initial import of OpenSAF source }}} We can view just the `tip` revision (the latest changeset in the repository) and get some more information: {{{ ~/opensaf/opensaf-scratch$ hg tip -v --patch changeset: 3:b67adc860aba tag: tip user: John Wright date: Mon Jan 07 14:46:16 2008 -0700 files: foo description: Added the foo file diff -r cb8e59469658 -r b67adc860aba foo --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/foo Mon Jan 07 14:46:16 2008 -0700 @@ -0,0 +1,1 @@ +bar }}} As you can see, if you are familiar with Subversion, Mercurial's commands are pretty similar. If you need help with a particular command, you can use the `help` command: {{{ ~/opensaf/opensaf-scratch$ hg help log hg log [OPTION]... [FILE] show revision history of entire repository or files Print the revision history of the specified files or the entire project. File history is shown without following rename or copy history of files. Use -f/--follow with a file name to follow history across renames and copies. --follow without a file name will only show ancestors or descendants of the starting revision. --follow-first only follows the first parent of merge revisions. If no revision range is specified, the default is tip:0 unless --follow is set, in which case the working directory parent is used as the starting revision. By default this command outputs: changeset id and hash, tags, non-trivial parents, user, date and time, and a summary for each commit. When the -v/--verbose switch is used, the list of changed files and full commit message is shown. NOTE: log -p may generate unexpected diff output for merge changesets, as it will compare the merge changeset against its first parent only. Also, the files: list will only reflect files that are different from BOTH parents. aliases: history options: -f --follow follow changeset history, or file history across copies and renames --follow-first only follow the first parent of merge changesets -d --date show revs matching date spec -C --copies show copied files -k --keyword do case-insensitive search for a keyword -l --limit limit number of changes displayed -r --rev show the specified revision or range --removed include revs where files were removed -M --no-merges do not show merges --style display using template map file -m --only-merges show only merges -p --patch show patch -P --prune do not display revision or any of its ancestors --template display with template -I --include include names matching the given patterns -X --exclude exclude names matching the given patterns use "hg -v help log" to show global options }}} == Publishing your changes == #publishing So that other people can view and pull from our repository, we need to push it to a publicly accessible location. In order to facilitate web-based browsing of a repository and fast operations over HTTP, Mercurial uses a CGI script (`hgweb.cgi` or `hgwebdir.cgi`) for hosting repositories. The webserver on `devel.opensaf.org` is configured so that any repository pushed to a user's `public_html/hg` directory will be accessible to browse and to pull from via `http://devel.opensaf.org/~user/hg/repo`. Suppose we wish to publish the changes we just made. First, we need to initialize a repository on `devel`. One way is to use the `init` command: {{{ ~/opensaf/opensaf-scratch$ ssh devel.opensaf.org hg init \ public_html/hg/opensaf-scratch }}} However, since the OpenSAF Mercurial repository is pretty large, it would be better to make a clone of the master repository and then push our much smaller changes to it. Since the repository might have changed since we cloned our copy, we need to clone it at the `tip` revision of our clone. {{{ ~/opensaf/opensaf-scratch$ cd ../opensaf ~/opensaf/opensaf$ hg tip changeset: 2:cb8e59469658 tag: tip user: John Wright date: Mon Jan 07 14:37:03 2008 -0700 summary: Naming scheme changed: 1.0-5 => 1.0.5 . Update .hgtags to reflect. }}} In Mercurial (and other distributed revision control systems), the sequential revision number for a particular changeset will vary between repositories. To identify a changeset between repositories, we use a hexadecimal identifier (which, behind the scenes, is a hash of the changeset). Here, the last changeset we pulled was `cb8e59469658`. To clone it into `public_html/hg/opensaf-scratch`: {{{ ~/opensaf/opensaf$ ssh devel.opensaf.org hg clone -U -r cb8e59469658 \ /var/www/hg/opensaf public_html/hg/opensaf-scratch requesting all changes adding changesets adding manifests adding file changes added 3 changesets with 2368 changes to 2367 files }}} The `-U` option to the `clone` command tells Mercurial not to update the working directory. Since all we need is the `.hg` directory in the clone, this saves some time and space. Now we can push our changes: {{{ ~/opensaf/opensaf$ cd ../opensaf-scratch ~/opensaf/opensaf-scratch$ hg push \ ssh://devel.opensaf.org/public_html/hg/opensaf-scratch pushing to ssh://devel.opensaf.org/public_html/hg/opensaf-scratch searching for changes remote: adding changesets remote: adding manifests remote: adding file changes remote: added 1 changesets with 1 changes to 1 files }}} Note, the path given in the `ssh` protocol is relative to your home directory; to give an absolute path, use two slashes after the hostname, e.g. `ssh://devel.opensaf.org//var/www/hg/opensaf-staging`. == Pulling from published branches == When you clone a repository, Mercurial keeps track of where it was cloned from so that it's easy to track upstream changes. Back in our pristine clone, we can issue the `incoming` command to see what has changed in the upstream branch: {{{ ~/opensaf/opensaf-scratch$ cd ../opensaf ~/opensaf/opensaf$ hg incoming comparing with http://devel.opensaf.org/hg/opensaf searching for changes no changes found }}} Nothing has changed since we cloned the master repository. Now, suppose a developer has published some changes, and we want to review and potentially merge those changes. First, let's make another clone of our pristine repository for the merge: {{{ ~/opensaf/opensaf$ cd .. ~/opensaf$ hg clone opensaf opensaf-merge 2367 files updated, 0 files merged, 0 files removed, 0 files unresolved }}} Now, suppose the developer has published his changes to http://devel.opensaf.org/~jswright/hg/opensaf-scratch. Let's see what changes have been made to that branch: {{{ ~/opensaf$ cd opensaf-merge ~/opensaf/opensaf-merge$ hg incoming -v --patch \ http://devel.opensaf.org/~jswright/hg/opensaf-scratch comparing with http://devel.opensaf.org/~jswright/hg/opensaf-scratch searching for changes changeset: 3:b67adc860aba tag: tip user: John Wright date: Mon Jan 07 14:46:16 2008 -0700 files: foo description: Added the foo file diff -r cb8e59469658 -r b67adc860aba foo --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/foo Mon Jan 07 14:46:16 2008 -0700 @@ -0,0 +1,1 @@ +bar }}} To pull changes from another repository, use the `pull` command. {{{ ~/opensaf/opensaf-merge$ hg pull \ http://devel.opensaf.org/~jswright/hg/opensaf-scratch pulling from http://devel.opensaf.org/~jswright/hg/opensaf-scratch searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files (run 'hg update' to get a working copy) }}} Mercurial does not by default automatically update the working copy when you pull from another repository, but it helpfully reminds us that we need to run `hg update`. (You can also specify the `-u` option to `hg pull`, to automatically update the working copy.) Let's update it: {{{ ~/opensaf/opensaf-merge$ hg update 1 files updated, 0 files merged, 0 files removed, 0 files unresolved }}} Now, we could publish this repository in the same manner as we published the hg:/~jswright:opensaf-scratch repository. = Maintainer actions = Now that I have discussed some of the basics of Mercurial, we can discuss some common actions a feature maintainer or release manager might perform. Many of the examples here are pertinent to non-maintainers as well, especially since there are some real-life examples instead of just contrived ones. == Accepting changes from a developer == The preferred way for a developer to submit changes is by publishing a Mercurial branch as mentioned in [#publishing Publishing your changes] above. For these changes to make their way into the master hg:opensaf repository, a maintainer must perform the following steps: 1. Clone (or update their clone of) the hg:opensaf-staging repository 2. Pull the changes from the developer's tree into the opensaf-staging clone 3. Perform a merge (often this will be trivial) 4. Push to ssh://devel.opensaf.org/hg/www/opensaf-staging (I'll describe these steps in detail below.) After each push to the hg:opensaf-staging repository, a build is triggered on several different architectures, with some different configuration options. (See http://devel.opensaf.org/buildbot/ and the [wiki:BuildBot] page for more details.) If the build succeeds on all configurations, the change is pushed to the master hg:opensaf repository. This ensures that the master repository ("trunk") will always build. === Cloning the hg:opensaf-staging repository === Developers will typically branch from the master repository rather than the staging one, but since we will be pushing to the staging repository, we need to ensure we have all the changesets in that repository. (The only reason hg:opensaf-staging should differ from hg:opensaf is if the staging repository doesn't build, or if the push to the master repository simply hasn't happened yet.) {{{ ~/opensaf$ hg clone http://devel.opensaf.org/hg/opensaf-staging destination directory: opensaf-staging requesting all changes adding changesets adding manifests adding file changes added 29 changesets with 3975 changes to 2535 files 2496 files updated, 0 files merged, 0 files removed, 0 files unresolved }}} In the future, if you already have an clone of hg:opensaf-staging, you can simply pull and update your tree: {{{ ~/opensaf/opensaf-staging$ hg pull -u pulling from http://devel.opensaf.org/hg/opensaf-staging searching for changes no changes found }}} (In this case, there were no changes on the staging repository since I made my clone.) === Pulling changes from a developer's tree === Hans Feldt has submitted a tree with some changes to the UML simulated environment for inclusion into the master repository. He has published it at http://devel.opensaf.org/~hafe/hg/opensaf-uml (we can refer to this inside of Trac as hg:/~hafe:opensaf-uml). Our first task is to pull the changes from his branch. It's a good idea first to take a look at what would be pulled: {{{ ~/opensaf/opensaf-staging$ hg incoming http://devel.opensaf.org/~hafe/hg/opensaf-uml comparing with http://devel.opensaf.org/~hafe/hg/opensaf-uml searching for changes changeset: 29:2372d20f9445 parent: 25:6556b700c674 user: Hans Feldt date: Fri Feb 29 15:06:55 2008 +0100 summary: Updated with latest versions of kernel & busybox. 64 bit support. changeset: 30:a1a612fef365 user: Hans Feldt date: Mon Mar 03 09:39:44 2008 +0100 summary: Added lib64 in root template changeset: 31:7c91bc121b0d user: Hans Feldt date: Mon Mar 03 09:41:27 2008 +0100 summary: added mdev.conf in root template changeset: 32:ed8bc706778d user: Hans Feldt date: Mon Mar 03 16:14:03 2008 +0100 summary: Changed from make system to batch script changeset: 33:1708b7a0b970 user: Hans Feldt date: Mon Mar 03 16:18:29 2008 +0100 summary: some missing files changeset: 34:63d46a2b638e user: Hans Feldt date: Mon Mar 03 16:21:02 2008 +0100 summary: remove changeset: 35:88031930b749 user: Hans Feldt date: Mon Mar 03 16:55:24 2008 +0100 summary: fix changeset: 36:8f434f6c5a3c user: Hans Feldt date: Mon Mar 03 17:08:02 2008 +0100 summary: added missing dir changeset: 37:0c7f57042981 user: Hans Feldt date: Mon Mar 03 17:17:58 2008 +0100 summary: robuster wgets changeset: 38:1772ee36adc2 user: Hans Feldt date: Mon Mar 03 17:23:33 2008 +0100 summary: robust wgets again changeset: 39:9314051074ca user: Hans Feldt date: Mon Mar 03 18:13:39 2008 +0100 summary: Created new function and removed some changeset: 40:a488737e0428 user: Hans Feldt date: Mon Mar 03 18:16:06 2008 +0100 summary: removed sed of inittime changeset: 41:e244cc59be54 user: Hans Feldt date: Thu Mar 06 14:08:06 2008 +0100 summary: unused file removed, faster rde start, always rebuild root fs changeset: 42:88ee2aff36d3 user: Hans Feldt date: Thu Mar 06 14:55:09 2008 +0100 summary: Bad cleaning changeset: 43:44942b5499f0 user: Hans Feldt date: Thu Mar 06 20:03:13 2008 +0100 summary: extract gz and bz2 files differently changeset: 44:e835f607f17d user: Hans Feldt date: Thu Mar 06 21:35:24 2008 +0100 summary: more cleaning changeset: 45:484fc21ccffe tag: tip user: Hans Feldt date: Fri Mar 07 11:52:43 2008 +0100 summary: use default NCSSystemBOM.xml }}} (If there were fewer changesets, I would probably add the `-v` option, which will show the names of the files changed, and possibly the `--patch` option. The `--patch` option is especially useful for code review.) Now to actually pull the changes {{{ ~/opensaf/opensaf-staging$ hg pull -u http://devel.opensaf.org/~hafe/hg/opensaf-uml pulling from http://devel.opensaf.org/~hafe/hg/opensaf-uml searching for changes adding changesets adding manifests adding file changes added 17 changesets with 44 changes to 27 files (+1 heads) not updating, since new heads added (run 'hg heads' to see heads, 'hg merge' to merge) }}} Notice, Mercurial complained about there being new heads. This happens if there were changes on hg:opensaf-staging since the changeset that the developer branched at. This is usually not a problem, since Mercurial has very smart merge tracking; however, it can lead to a conflict, particularly if the same point in a particular file was edited in different ways on the divergent branches. === Merging the changes === This step is necessary if, as above, the staging repository receives new revisions after the developer branches. You can always perform these steps, though---if a merge is not needed, Mercurial simply won't do anything. First, let's see what the two heads of our repository are: {{{ ~/opensaf/opensaf-staging$ hg heads changeset: 45:484fc21ccffe tag: tip user: Hans Feldt date: Fri Mar 07 11:52:43 2008 +0100 summary: use default NCSSystemBOM.xml changeset: 28:061f43513e87 user: Mahesh date: Fri Feb 29 17:06:47 2008 +0530 summary: Fix for Ticket #10 - clean_up nis_scxb nis_snmpd_clean.sh }}} This makes sense: the first head, which happens to be the `tip` of this repository, is the `tip` of the developer branch. The other head is the `tip` of hg:opensaf-staging. As you may have guessed, the `hg merge` command will merge the divergent heads: {{{ ~/opensaf/opensaf-staging$ hg merge 22 files updated, 0 files merged, 7 files removed, 0 files unresolved (branch merge, don't forget to commit) }}} That was easy---no conflicts this time. Now, let's follow Mercurial's reminder and commit the new merge changeset: {{{ ~/opensaf/opensaf-staging$ hg commit -m "Merge changes from Hans Feldt's opensaf-uml branch" }}} Just to verify: {{{ ~/opensaf/opensaf-staging$ hg tip changeset: 46:e04ad9ac167d tag: tip parent: 28:061f43513e87 parent: 45:484fc21ccffe user: John Wright date: Mon Mar 10 20:47:14 2008 -0600 summary: Merge changes from Hans Feldt's opensaf-uml branch }}} === Pushing to hg:opensaf-staging === Now we push the repository, after taking another look at what we're actually sending up: {{{ ~/opensaf/opensaf-staging$ hg outgoing http://devel.opensaf.org/hg/opensaf-staging comparing with http://devel.opensaf.org/hg/opensaf-staging searching for changes changeset: 29:2372d20f9445 parent: 25:6556b700c674 user: Hans Feldt date: Fri Feb 29 15:06:55 2008 +0100 summary: Updated with latest versions of kernel & busybox. 64 bit support. changeset: 30:a1a612fef365 user: Hans Feldt date: Mon Mar 03 09:39:44 2008 +0100 summary: Added lib64 in root template changeset: 31:7c91bc121b0d user: Hans Feldt date: Mon Mar 03 09:41:27 2008 +0100 summary: added mdev.conf in root template changeset: 32:ed8bc706778d user: Hans Feldt date: Mon Mar 03 16:14:03 2008 +0100 summary: Changed from make system to batch script changeset: 33:1708b7a0b970 user: Hans Feldt date: Mon Mar 03 16:18:29 2008 +0100 summary: some missing files changeset: 34:63d46a2b638e user: Hans Feldt date: Mon Mar 03 16:21:02 2008 +0100 summary: remove changeset: 35:88031930b749 user: Hans Feldt date: Mon Mar 03 16:55:24 2008 +0100 summary: fix changeset: 36:8f434f6c5a3c user: Hans Feldt date: Mon Mar 03 17:08:02 2008 +0100 summary: added missing dir changeset: 37:0c7f57042981 user: Hans Feldt date: Mon Mar 03 17:17:58 2008 +0100 summary: robuster wgets changeset: 38:1772ee36adc2 user: Hans Feldt date: Mon Mar 03 17:23:33 2008 +0100 summary: robust wgets again changeset: 39:9314051074ca user: Hans Feldt date: Mon Mar 03 18:13:39 2008 +0100 summary: Created new function and removed some changeset: 40:a488737e0428 user: Hans Feldt date: Mon Mar 03 18:16:06 2008 +0100 summary: removed sed of inittime changeset: 41:e244cc59be54 user: Hans Feldt date: Thu Mar 06 14:08:06 2008 +0100 summary: unused file removed, faster rde start, always rebuild root fs changeset: 42:88ee2aff36d3 user: Hans Feldt date: Thu Mar 06 14:55:09 2008 +0100 summary: Bad cleaning changeset: 43:44942b5499f0 user: Hans Feldt date: Thu Mar 06 20:03:13 2008 +0100 summary: extract gz and bz2 files differently changeset: 44:e835f607f17d user: Hans Feldt date: Thu Mar 06 21:35:24 2008 +0100 summary: more cleaning changeset: 45:484fc21ccffe user: Hans Feldt date: Fri Mar 07 11:52:43 2008 +0100 summary: use default NCSSystemBOM.xml changeset: 46:e04ad9ac167d tag: tip parent: 28:061f43513e87 parent: 45:484fc21ccffe user: John Wright date: Mon Mar 10 20:47:14 2008 -0600 summary: Merge changes from Hans Feldt's opensaf-uml branch ~/opensaf/opensaf-staging$ hg push ssh://devel.opensaf.org//var/www/hg/opensaf-staging pushing to ssh://devel.opensaf.org//var/www/hg/opensaf-staging searching for changes remote: adding changesets remote: adding manifests remote: adding file changes remote: added 18 changesets with 44 changes to 27 files }}} Now, you should be able to verify that the changes exist on hg:opensaf-staging. == Creating a release == #creating-a-release Typically, a developer who is not a maintainer (one who doesn't have write access to the master repository) should not perform these steps. With each release of OpenSAF, for example, version 1.0.5, there is some associated changeset in the Mercurial repository. Mercurial stores this information in a file called `.hgtags`. Most of the time, you won't ever need to worry about this file---the `tag` command will create tags for you---but it occasionally shows up in merges. To see a list of tags in a repository, issue the `tags` command: {{{ ~/opensaf/opensaf-merge$ hg tags tip 3:b67adc860aba 1.0.5 0:1c7624641cfa }}} The tag for `tip` is special: it always points to the most recently added changeset. The `1.0.5` tag points to the changeset that matches the release of 1.0.5 of OpenSAF. Mercurial lets you refer to tags just like any other revision. Suppose we want to release version 1.2.1, which contains the changes currently up to `tip` of the `opensaf-staging` repository. First, we need to update our copy of the repository: {{{ ~/opensaf/opensaf-staging$ hg pull pulling from http://devel.opensaf.org/hg/opensaf-staging searching for changes adding changesets adding manifests adding file changes added 32 changesets with 108 changes to 76 files (run 'hg update' to get a working copy) ~/opensaf/opensaf-staging$ hg update 76 files updated, 0 files merged, 4 files removed, 0 files unresolved }}} We need to update the confgure.ac file to contain the new version: {{{ ~/opensaf/opensaf-staging$ sed -r -I -e 's/(AC_INIT..opensaf.,) [^,]*/\1 [1.2.1]/' configure.ac ~/opensaf/opensaf-staging$ hg diff diff -r 6b0e67b08dba configure.ac --- a/configure.ac Wed Oct 14 07:04:41 2009 -0600 +++ b/configure.ac Wed Oct 14 07:25:16 2009 -0600 @@ -15,7 +15,7 @@ # AC_PREREQ([2.59]) -AC_INIT([opensaf], [1.1.0], [devel@list.opensaf.org]) +AC_INIT([opensaf], [1.2.1], [devel@list.opensaf.org]) AC_CANONICAL_SYSTEM AC_CONFIG_SRCDIR([OpenSAFCopyRights]) AC_CONFIG_HEADER([config.h]) ~/opensaf/opensaf-staging$ hg commit \ -m "Update configure.ac file for version 1.2.1" }}} Now, let's add the tag: {{{ ~/opensaf/opensaf-staging$ hg tag 1.2.1 ~/opensaf/opensaf-staging$ hg tip -vp changeset: 93:f22c0dbb9c1b tag: tip user: John Wright date: Wed Jun 25 16:53:41 2008 -0600 files: .hgtags description: Added tag 1.2.1 for changeset d3cdb58ef131 diff -r d3cdb58ef131 -r f22c0dbb9c1b .hgtags --- a/.hgtags Wed Jun 25 16:52:42 2008 -0600 +++ b/.hgtags Wed Jun 25 16:53:41 2008 -0600 @@ -4,3 +4,4 @@ 7c21c38a8880a3444bc37471f798ab85b7a3616d 1.0.9 3319e81bd954cfced21794c82c604002e62d9c49 1.1.0 3319e81bd954cfced21794c82c604002e62d9c49 Release_2_FC +d3cdb58ef1312a87b100f71ad678cf6a8400dcda 1.2.1 }}} We can also add more "human readable" tags if we like, referring to the same changeset. For instance, if we want the changeset we just tagged as 1.2.1 to also be known as Release_2_RC1, we can do {{{ ~/opensaf/opensaf-staging$ hg tag -r 1.2.1 Release_2_RC1 ~/opensaf/opensaf-staging$ hg tip -vp changeset: 94:14da920916d3 tag: tip user: John Wright date: Wed Jun 25 16:54:25 2008 -0600 files: .hgtags description: Added tag Release_2_RC1 for changeset d3cdb58ef131 diff -r f22c0dbb9c1b -r 14da920916d3 .hgtags --- a/.hgtags Wed Jun 25 16:53:41 2008 -0600 +++ b/.hgtags Wed Jun 25 16:54:25 2008 -0600 @@ -5,3 +5,4 @@ 3319e81bd954cfced21794c82c604002e62d9c49 1.1.0 3319e81bd954cfced21794c82c604002e62d9c49 Release_2_FC d3cdb58ef1312a87b100f71ad678cf6a8400dcda 1.2.1 +d3cdb58ef1312a87b100f71ad678cf6a8400dcda Release_2_RC1 }}} (The `-r` option tells Mercurial to tag a particular revision, rather than `tip`. Note in the .hgtags file how the changeset ids before `1.2.1` and `Release_2_RC1` are identical.) Now, we need to push the changes up to the hg:opensaf-staging repository. To see what's about to be pushed: {{{ ~/opensaf/opensaf-staging$ hg outgoing \ ssh://devel.opensaf.org//var/www/hg/opensaf-staging comparing with ssh://devel.opensaf.org//var/www/hg/opensaf-staging searching for changes changeset: 92:d3cdb58ef131 tag: Release_2_RC1 tag: 1.2.1 user: John Wright date: Wed Jun 25 16:52:42 2008 -0600 summary: Update configure.ac spec files for version 1.2.1 changeset: 93:f22c0dbb9c1b user: John Wright date: Wed Jun 25 16:53:41 2008 -0600 summary: Added tag 1.2.1 for changeset d3cdb58ef131 changeset: 94:14da920916d3 tag: tip user: John Wright date: Wed Jun 25 16:54:25 2008 -0600 summary: Added tag Release_2_RC1 for changeset d3cdb58ef131 }}} To actually push, replace the `outgoing` command with `push`. Now we can make a release tarball: {{{ ~/opensaf/opensaf-staging$ ./bootstrap.sh ~/opensaf/opensaf-staging$ ./configure ~/opensaf/opensaf-staging$ make dist ~/opensaf/opensaf-staging$ tar ztvf opensaf-1.2.1.tar.gz | head -rw-r--r-- user/group 94 2008-06-25 16:52 opensaf-1.2.1/.hg_archival.txt -rw-r--r-- user/group 289 2008-06-25 16:52 opensaf-1.2.1/.hgtags -rw-r--r-- user/group 0 2008-06-25 16:52 opensaf-1.2.1/AUTHORS -rw-r--r-- user/group 26250 2008-06-25 16:52 opensaf-1.2.1/COPYING -rw-r--r-- user/group 6965 2008-06-25 16:52 opensaf-1.2.1/ChangeLog -rw-r--r-- user/group 35224 2008-06-25 16:52 opensaf-1.2.1/INSTALL -rw-r--r-- user/group 2750 2008-06-25 16:52 opensaf-1.2.1/Makefile.am -rw-r--r-- user/group 0 2008-06-25 16:52 opensaf-1.2.1/NEWS -rw-r--r-- user/group 8990 2008-06-25 16:52 opensaf-1.2.1/README -rwxr-xr-x user/group 31 2008-06-25 16:52 opensaf-1.2.1/bootstrap.sh }}} That tarball needs to be uploaded to bohr.linux.hp.com, which hosts download.opensaf.org: {{{ ~/opensaf/opensaf-staging$ scp ../opensaf-1.2.1.tar.gz \ devel.opensaf.org:/var/www/download.opensaf.org/releases }}} Now, once the changes make their way into the master hg:opensaf repository (soon, this will be automatic; for now, I manually update it about once a day, and I'll send you an email if there are new tags), don't forget to update the [wiki:downloads] page. == Checking out a previous release or revision == Sometimes it is useful to check out a previous revison in your current repository. (This is especially important with the `hg bisect` command---please see [http://hgbook.red-bean.com/hgbookch9.html#x13-1880009.5 Chapter 9, Section 5] of ''Distributed revision control with Mercurial''.) We've seen the `hg update` command before---but it can be used to check out ''any'' revision, not only the `tip`. So, back in our `opensaf-merge` repository, we can check out the revision with the `1.0.5` tag: {{{ ~/opensaf/opensaf-merge$ hg update 1.0.5 0 files updated, 0 files merged, 2 files removed, 0 files unresolved ~/opensaf/opensaf-merge$ ls AUTHORS config include Makefile.am README scripts bootstrap.sh configure.ac INSTALL mibs rpms services ChangeLog COPYING lib NEWS samples tools }}} The `update` command works with any changeset identifier: you can give it a revision number (not generally recommended, since the revision number for a particular changeset will vary between repositories), a hexadecimal identifier, or a tag. == Making updates to a previous release == If a bug is found in an earlier release of OpenSAF, and the decision is made to update that version with only the bug fix (so that users need not upgrade to the latest version with many other changes), we will use a clone of the master repository made at the tag for that release. Typically, this should be created at the release time (see the end of section on [#creating-a-release creating a release]). For a contrived example, suppose there was a missing file in the 1.0.5 release. First, let's clone the `opensaf-1.0.5` repository: {{{ ~/opensaf$ hg clone http://devel.opensaf.org/hg/opensaf-1.0.5 \ opensaf-1.0.5-bugfix requesting all changes adding changesets adding manifests adding file changes added 1 changesets with 2366 changes to 2366 files 2366 files updated, 0 files merged, 0 files removed, 0 files unresolved ~/opensaf$ cd opensaf-1.0.5-bugfix }}} Now, let's make the required fix: {{{ ~/opensaf/opensaf-1.0.5-bugfix$ echo baz > bar ~/opensaf/opensaf-1.0.5-bugfix$ hg add bar ~/opensaf/opensaf-1.0.5-bugfix$ hg commit -m 'Add a missing file, bar' ~/opensaf/opensaf-1.0.5-bugfix$ hg tip -vp changeset: 1:f391fb3ea67d tag: tip user: John Wright date: Mon Jan 07 15:21:07 2008 -0700 files: bar description: Add a missing file, bar diff -r 1c7624641cfa -r f391fb3ea67d bar --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bar Mon Jan 07 15:21:07 2008 -0700 @@ -0,0 +1,1 @@ +baz }}} Now, we publish our changes somewhere that a maintainer can pick them up: {{{ ~/opensaf/opensaf-1.0.5-bugfix$ ssh devel.opensaf.org hg clone -U \ /var/www/hg/opensaf-1.0.5 public_html/hg/opensaf-1.0.5-bugfix ~/opensaf/opensaf-1.0.5-bugfix$ hg push \ ssh://devel.opensaf.org/public_html/hg/opensaf-1.0.5-bugfix pushing to ssh://devel.opensaf.org/public_html/hg/opensaf-1.0.5-bugfix searching for changes remote: adding changesets remote: adding manifests remote: adding file changes remote: added 1 changesets with 1 changes to 1 files }}} (If a change has happened on the `opensaf-1.0.5` master repository between when you originally clone and when you `push`, Mercurial will complain and force you to `pull` and `merge` before pushing. Some documentation about that should go here---for now, please see [http://hgbook.red-bean.com/hgbookch3.html Chapter 3] of ''Distributed revision control with Mercurial''.) The repository is now available at http://devel.opensaf.org/~jswright/hg/opensaf-1.0.5-bugfix. (You can refer to this repository anywhere in Trac by using hg:/~jswright:opensaf-1.0.5-bugfix.) == Updating the master repository for a release branch == #updating-release-branch-master-repo This section is intended for maintainers with write access to the master repository for a particular release branch, but the bits about merging should be useful to anybody who wishes to pull changes from other published repositories. Suppose we wish to merge in the changes from hg:/~jswright:opensaf-1.0.5-bugfix to the hg:opensaf-1.0.5 master repository. First, let's clone the master repository: {{{ ~/opensaf$ hg clone http://devel.opensaf.org/hg/opensaf-1.0.5 destination directory: opensaf-1.0.5 requesting all changes adding changesets adding manifests adding file changes added 1 changesets with 2366 changes to 2366 files 2366 files updated, 0 files merged, 0 files removed, 0 files unresolved }}} Now, let's clone that repository to get a temporary repository for merging in the new changes: {{{ ~/opensaf$ hg clone opensaf-1.0.5 opensaf-1.0.5-merge 2366 files updated, 0 files merged, 0 files removed, 0 files unresolved }}} Now, we can pull the new changes: {{{ ~/opensaf$ cd opensaf-1.0.5-merge ~/opensaf/opensaf-1.0.5-merge$ hg incoming -vp \ http://devel.opensaf.org/~jswright/hg/opensaf-1.0.5-bugfix comparing with http://devel.opensaf.org/~jswright/hg/opensaf-1.0.5-bugfix searching for changes changeset: 1:f391fb3ea67d tag: tip user: John Wright date: Mon Jan 07 15:21:07 2008 -0700 files: bar description: Add a missing file, bar diff -r 1c7624641cfa -r f391fb3ea67d bar --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bar Mon Jan 07 15:21:07 2008 -0700 @@ -0,0 +1,1 @@ +baz ~/opensaf/opensaf-1.0.5-merge$ hg pull -u \ http://devel.opensaf.org/~jswright/hg/opensaf-1.0.5-bugfix pulling from http://devel.opensaf.org/~jswright/hg/opensaf-1.0.5-bugfix searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files 1 files updated, 0 files merged, 0 files removed, 0 files unresolved ~/opensaf/opensaf-1.0.5-merge$ hg tip changeset: 1:f391fb3ea67d tag: tip user: John Wright date: Mon Jan 07 15:21:07 2008 -0700 summary: Add a missing file, bar }}} Now, we would push the changes to the master repository: {{{ ~/opensaf/opensaf-1.0.5-merge$ hg push \ ssh://devel.opensaf.org//var/www/hg/opensaf-1.0.5 }}} I'm not showing the output, because I didn't actually run this command (these particular changes shouldn't really go there). For now, let's just push to our original clone of hg:opensaf-1.0.5, and update its working copy: {{{ ~/opensaf/opensaf-1.0.5-merge$ hg push ../opensaf-1.0.5 pushing to ../opensaf-1.0.5 searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files ~/opensaf/opensaf-1.0.5-merge$ cd ../opensaf-1.0.5 ~/opensaf/opensaf-1.0.5$ hg update 1 files updated, 0 files merged, 0 files removed, 0 files unresolved }}} == Making an update release == This section is intended for maintainers with write access to the master repository for a particular release branch. Suppose we are ready to create a 1.0.5.1 release of OpenSAF, using the `tip` of the hg:opensaf-1.0.5 repository. First, let's update our local clone of hg:opensaf-1.0.5: {{{ ~/opensaf/opensaf-1.0.5$ hg pull -u pulling from http://devel.opensaf.org/hg/opensaf-1.0.5 searching for changes no changes found }}} There were no changes this time, but it is always a good idea to make sure you have the latest updates before making a release. Now, we need to make a tag for our new release: {{{ ~/opensaf/opensaf-1.0.5$ hg tag 1.0.5.1 ~/opensaf/opensaf-1.0.5$ hg tip changeset: 2:4653c22303e8 tag: tip user: John Wright date: Mon Jan 07 15:38:59 2008 -0700 summary: Added tag 1.0.5.1 for changeset f391fb3ea67d }}} Normally, we would push these changes: {{{ ~/opensaf/opensaf-1.0.5$ hg push \ ssh://devel.opensaf.org//var/www/hg/opensaf-1.0.5 }}} Now we can create a tarball for the release: {{{ ~/opensaf/opensaf-1.0.5$ hg archive -t tgz -r 1.0.5.1 \ ../opensaf-1.0.5.1.tar.gz }}} == Forward-porting changes in release branches == Often, a bug in an older release will also apply to the current development branch. Typically, we'll merge any changes in the release branches into the main repository. Let's update our clone of the hg:opensaf repository: {{{ ~/opensaf/opensaf$ hg pull -u pulling from http://devel.opensaf.org/hg/opensaf searching for changes no changes found }}} Now, let's make a clone for merging in the 1.0.5 fixes: {{{ ~/opensaf/opensaf$ cd .. ~/opensaf$ hg clone opensaf opensaf+1.0.5-updates 2368 files updated, 0 files merged, 0 files removed, 0 files unresolved }}} Now, we can pull in the changes from the hg:opensaf-1.0.5 repository. In practice, the URL for this will be http://devel.opensaf.org/hg/opensaf-1.0.5; for now, we'll pull in from our local `opensaf-1.0.5` repository, since I didn't actually push these changes to the master repository. {{{ ~/opensaf$ cd opensaf+1.0.5-updates/ ~/opensaf/opensaf+1.0.5-updates$ hg pull ../opensaf-1.0.5 pulling from ../opensaf-1.0.5 searching for changes adding changesets adding manifests adding file changes added 2 changesets with 2 changes to 2 files (+1 heads) (run 'hg heads' to see heads, 'hg merge' to merge) ~/opensaf/opensaf+1.0.5-updates$ hg heads changeset: 6:4653c22303e8 tag: tip user: John Wright date: Mon Jan 07 15:38:59 2008 -0700 summary: Added tag 1.0.5.1 for changeset f391fb3ea67d changeset: 4:73e6fd9f4e53 user: John Wright date: Mon Jan 07 15:05:56 2008 -0700 summary: Added tag 1.0.6 for changeset b67adc860aba }}} There are two heads (changesets without any children) in the new repository. We need to merge them. {{{ ~/opensaf/opensaf+1.0.5-updates$ hg merge merging .hgtags conflicts detected in /home/jswright.local/opensaf/opensaf+1.0.5-updates/.hgtags }}} Now, Mercurial opens an editor to resolve the merge conflict. The editor has the following text in it: {{{ <<<<<<< /home/jswright.local/opensaf/opensaf+1.0.5-updates/.hgtags.orig.2484129268 1c7624641cfa9ab65635326316add7d72516f759 1.0.5 b67adc860abad8819f415abd5a8de8fcb425b306 1.0.6 ||||||| /tmp/.hgtags~base.WBTtag ======= f391fb3ea67d8dcfd8e371ed22009ead4834480b 1.0.5.1 >>>>>>> /tmp/.hgtags~other.-mJNN1 }}} We'll want all the tags visible, so let's just remove all the conflict markers and leave all the lines intact: {{{ 1c7624641cfa9ab65635326316add7d72516f759 1.0.5 b67adc860abad8819f415abd5a8de8fcb425b306 1.0.6 f391fb3ea67d8dcfd8e371ed22009ead4834480b 1.0.5.1 }}} After saving the file and exiting the editor, Mercurial gives us a little more information: {{{ 1 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) }}} It reminds us that merges aren't automatically committed. It's a good idea now to run `hg diff` to see what changed: {{{ ~/opensaf/opensaf+1.0.5-updates$ hg diff diff -r 73e6fd9f4e53 .hgtags --- a/.hgtags Mon Jan 07 15:05:56 2008 -0700 +++ b/.hgtags Mon Jan 07 15:45:12 2008 -0700 @@ -1,2 +1,3 @@ 1c7624641cfa9ab65635326316add7d72516f759 1c7624641cfa9ab65635326316add7d72516f759 1.0.5 b67adc860abad8819f415abd5a8de8fcb425b306 1.0.6 +f391fb3ea67d8dcfd8e371ed22009ead4834480b 1.0.5.1 diff -r 73e6fd9f4e53 bar --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bar Mon Jan 07 15:45:12 2008 -0700 @@ -0,0 +1,1 @@ +baz }}} Everything looks good---we see just the added tag and the new `bar` file. Now we can commit: {{{ ~/opensaf/opensaf+1.0.5-updates$ hg commit -m \ "Merge changes from the 1.0.5 branch" ~/opensaf/opensaf+1.0.5-updates$ hg tip changeset: 7:7be895547eac tag: tip parent: 4:73e6fd9f4e53 parent: 6:4653c22303e8 user: John Wright date: Mon Jan 07 15:45:48 2008 -0700 summary: Merge changes from the 1.0.5 branch }}} Normally, we'd now push these changes to the master hg:opensaf repository: {{{ ~/opensaf/opensaf+1.0.5-updates$ hg push \ ssh://devel.opensaf.org//var/www/hg/opensaf }}} Since these are contrived changes, I'll just push them to my copy of the `opensaf` repository: {{{ ~/opensaf/opensaf+1.0.5-updates$ hg push ../opensaf pushing to ../opensaf searching for changes adding changesets adding manifests adding file changes added 3 changesets with 3 changes to 2 files }}} For more information on merging, please read [http://hgbook.red-bean.com/hgbookch3.html Chapter 3] of ''Distributed revision control with Mercurial''. = Closing words = This document is a work in progress. There is much that needs to be added about working with Trac, and the existing Mercurial parts could use better examples. If you have any suggestions, please send email to me at john.wright@hp.com. Or, now that it's on the wiki, you can make changes yourself! }}}