In this third part of a four-part article series on software configuration management, you'll learn how to set up and use a CVS server. We'll also start looking at the patch program. This article is excerpted from chapter three of the book Cross-Platform Development in C++, written by Syd Logan (Addison-Wesley; ISBN: 032124642X).
The patch program is considered by some to be the prime enabler behind the success of open source software. To quote Eric Raymond, ďThe patch program did more than any other single tool to enable collaborative development over the Internetóa method that would revitalize UNIX after 1990Ē (The Art of UNIX Programming, Addison-Wesley, 2003). Of course, it is hard to imagine patch taking all the credit; after all, what would development be without vi(1)? But still, there is a ring of truth in what he says.
In the open source community, at any given moment, on any given project, there are dozens, if not hundreds of developers, all working on some derivation of what is in currently on the tip (or branch) of some source code repository. All of them are working relatively blind to the changes that their counterparts are making to the same body of source code.
Integrating (and evaluating) the changes made to a shared body of source code in such an environment can be difﬁcult and error prone without a tool like patch. To see how, consider a team of three developers (A, B, and C) all working from the tip of the repository. Developer B is the team lead, and his job is to perform code reviews for Developer A and C, and integrate their changes into the source tree once an acceptable code review has been obtained. He also does development on the same body of source code, because he owns the overall architecture.
Letís say that Developer A ﬁnishes his work and is in need of a code review. To obtain the code review, Developer B needs to communicate his changes to Developer B. Iíve seen this done a few different ways over the years:
Developer A copies and pastes the changes made to the source ﬁle(s) into a text ﬁle, and sends the result to Developer B. In addition, Developer A adds comments to the text ﬁle to describe what the changes are, and where in the original source ﬁle the changes were made (or Developer A e-mails this information separately to Developer B). This is perhaps the worst method of all for conducting a code review, for two reasons:
Developer A may make a mistake and not copy and paste all the changes that were made, or miss entire source ﬁles that have modiﬁcation. The omission of a single line of change can greatly affect the ability of a code reviewer to accurately perform his task. Worse yet, if the code reviewer is responsible for integrating the changes into the repository and changes were missed, the process will surely lead to bugs.
Even if all changes are copied and pasted by Developer A, there is a chance that context will be lost or incorrectly communicated. One way to counter this problem would be for Developer A to include extra lines above and below the code that actually changed, but this is a better job for a tool like cvs diff, which can generate a patch ﬁle that contains the needed lines of context.
Developer A sends to Developer B copies of all the source ﬁles that were changed. This is better than sending a series of hand-constructed diffs, because Developer B can now take the source ﬁles and create a patch that correctly captures the changes made by Developer A, along with the context of those changes. If Developer A sends source ﬁles that are not being modiﬁed by Developer B, Developer B can simply use the diff program (not cvs diff or svn diff) to generate a patch ﬁle relative to his current working tree. If Developer A, however, sends changes that do affect ﬁles modiﬁed by Developer B, Developer B can either diff against his working tree to see the changes in the context of work he is performing, or Developer B can pull a new tree somewhere and generate a patch ﬁle from it. The actual method used is usually best determined by the code reviewer. The downsides of this method are as follows:
It is error prone. (Developer A might forget to include source ﬁles that contain change.)
It places a burden on the code reviewer to generate a patch ﬁle. The last thing you want to do on a large project is make more work for the code reviewer. Usually, a code reviewer is generally always struggling to keep up with not only his own development task, but with all the code review requests that are pouring in. Anything you can do to make his job easier will generally be appreciative (and may result in the code reviewer giving your requests a higher priority).
Developer A generates a patch ﬁle using cvn or svn diff, and sends it to the code reviewer. This is the best method because
The changes are relative to Developer Aís source tree.
cvs diff wonít miss any changes that were made, assuming that cvs diff is run at a high-enough level of the source tree. (There is one exception: new source ﬁles that have not been added to the repository, along with forgetting to pass the -N argument to cvs diff when creating a patch ﬁle [this is not a problem with svn diff, which automatically includes new source ﬁles in its diff output.])
After the code reviewer (Developer B) receives the patch from Developer A, he or she has a few options:
Simply look at the patch ﬁle, performing the code review based on its contents alone. Most of the time, this is what I do, especially if the patch ﬁle is a uniﬁed diff (as it should always be), and if the changes do not intersect any that I am making.
Apply the patch ﬁle to his local tree, build the result, and then perhaps test it. This can be helpful if Developer B would like to step through an execution of the code in a debugger, or to see that the patch builds correctly and without warnings. If Developer A has made changes to some of the source ﬁles that were modiﬁed by Developer B, Developer B can either
Pull a new tree and apply the patch to it so that his or her changes are not affected.
Use cvs diff to generate a patch ﬁle that contains his own changes, and then attempt to apply the changes from Developer A into his source tree. This allows Developer B not only to see the changes made by Developer A, but also to see them in the context of the changes that he is making. When the code review has been completed, Developer B can continue working on his changes, and check both his and Developer Bís changes in at a later time, or Developer B can have Developer A check in the changes, and then do a cvs or svn update to get in sync.
The patch program is the tool used by a code reviewer to apply changes speciﬁed in a patch ﬁle to a local copy of the repository. In essence, if both you and I have a copy of the same source tree, you can use cvs diff to generate a patch ﬁle containing changes you have made to your copy of the sources, and then I can use the patch program, along with your patch ﬁle, to apply those changes to my copy of the sources. The patch program tries very hard to do its job accurately, even if the copy of the sources the patch is being applied to have been changed in some unrelated way. The type of diff contained in the patch ﬁle affects the accuracy attained by the patch program; patch is generally more successful if it is fed a set of context diffs rather than normal diffs. The cvs diff -u3 syntax (uniﬁed diff with three lines of context) is enough to generate a patch ﬁle that gives a good result. (SVN by default generates uniﬁed diffs with three lines of context.)
Please check back for the conclusion to this article.