Update, Commit (with a merge)

Meanwhile, Harry has been coding as well. He heard somebody say that it’s best to compile with all the warnings turned on, so he decides to give it a try.

lottery harry$ gcc -std=c99 -Wall -Wextra -Werror lottery.c 
cc1: warnings being treated as errors
lottery.c:5: warning: unused parameter 'white_balls'
lottery.c:5: warning: unused parameter 'power_ball'

I say! The code has some warnings. The calculate_result() function isn’t using its parameters. Harry looks at the situation and realises the problem immediately: That function should be checking its arguments for validity! The power ball can be from 1 to 39 inclusive. The white balls can be 1 to 59 inclusive. So he implements the error checking.

int calculate_result(int white_balls[5], int power_ball)
{
    for (int i=0; i<5; i++)
    {
        if (
             (white_balls[i] < 1)
             || (white_balls[i] > 59)
           )
        {
            return -1;
        }
    }

    if (
         (power_ball < 1)
         || (power_ball > 39)
       )
    {
        return -1;
    }

    return 0;
}

Grand. Let’s see if it compiles.

lottery harry$ gcc -std=c99 -Wall -Wextra -Werror lottery.c

lottery harry$ ls -l
total 32
-rwxr-xr-x  1 harry  staff  8904 Apr  6 13:23 a.out
-rw-r--r--  1 harry  staff   843 Apr  6 13:21 lottery.c

Quite. But Harry decides to diff before committing, just for good measure.

lottery harry$ svn diff
Index: lottery.c
===================================================================
--- lottery.c   (revision 1)
+++ lottery.c   (working copy)
@@ -4,6 +4,25 @@
 
 int calculate_result(int white_balls[5], int power_ball)
 {
+    for (int i=0; i<5; i++)
+    {
+        if (
+             (white_balls[i] < 1)
+             || (white_balls[i] > 59)
+           )
+        {
+            return -1;
+        }
+    }
+
+    if (
+         (power_ball < 1)
+         || (power_ball > 39)
+       )
+    {
+        return -1;
+    }
+
     return 0;
 }

Good show. Time to commit the change.

But Sally has been working at the same time and she had her change ready to commit first.

lottery sally$ svn commit -m "change order of the command line args to be \
                              more like what the user will expect"
Sending        lottery.c
Transmitting file data .
Committed revision 2.

Just after Sally commits her changes, Harry tries to commit his.

lottery harry$ svn commit -m "fix some warnings"
Sending        lottery.c
Transmitting file data .svn: Commit failed (details follow):
svn: File '/lottery.c' is out of date

What’s all this then? Subversion is not allowing Harry to commit his change because it was based on a no-longer-current revision of lottery.c.

This behavior on the part of Subversion is typical for a second generation VCS. The model is sometimes called “edit-merge-commit”, because it often requires the user to do a merge before they are allowed to commit.

Harry uses update to make his working copy current.

lottery harry$ svn update
G    lottery.c
Updated to revision 2.

In this case, the update went fine, and Harry is able to go forward without much trouble. But if things go badly, his working copy becomes a mixture of his changes all stirred up with the changes being merged in from the repository. If he has trouble with the merge, it will be difficult for him to back out and try again without losing his own work. This issue is a major problem with the way second generation tools handle merging.

Everything seems to be ship-shape and Bristol fashion. The 'G' next to lottery.c means that the file has been merged. Harry wants to see what happened.

lottery harry$ svn diff
Index: lottery.c
===================================================================
--- lottery.c   (revision 2)
+++ lottery.c   (working copy)
@@ -4,6 +4,25 @@
 
 int calculate_result(int white_balls[5], int power_ball)
 {
+    for (int i=0; i<5; i++)
+    {
+        if (
+             (white_balls[i] < 1)
+             || (white_balls[i] > 59)
+           )
+        {
+            return -1;
+        }
+    }
+
+    if (
+         (power_ball < 1)
+         || (power_ball > 39)
+       )
+    {
+        return -1;
+    }
+
     return 0;
 }

Interesting. Diff still shows only Harry’s changes. But the baseline version of lottery.c now shows “(revision 2)”, whereas in the previous diff it showed “(revision 1)”. Harry decides to peek inside the file and discovers that main() has some new code in it. That must have come from Sally (who else?), and apparently Subversion was able to merge Sally’s changes directly into Harry’s modified copy of the file without any conflicts. Smashing! Still, what was the purpose of these changes?

lottery harry$ svn log
------------------------------------------------------------------------
r2 | sally | 2011-04-06 13:26:47 -0500 (Wed, 06 Apr 2011) | 1 line

change order of the command line args to be more like what the user will expect
------------------------------------------------------------------------
r1 | harry | 2011-04-06 12:32:46 -0500 (Wed, 06 Apr 2011) | 1 line

initial implementation
------------------------------------------------------------------------

Ah. Very well then. So Harry tries the commit once again.

lottery harry$ svn commit -m "fix some warnings"
Sending        lottery.c
Transmitting file data .
Committed revision 3.