summaryrefslogtreecommitdiffstats
path: root/developer-doc/phb/cvs-examples.docbook
blob: da29be8e5f2be53e3c0e049b1924f5eba160c2fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
<appendix id="cvs-examples">
<title>CVS examples</title>
<para>
It is not the intention of this document to give a complete introduction to
&cvs;. Nevertheless, a few examples should give a quick overview on the basic
operations to be performed by the developer.
</para>

<para>
It is assumed, that the developer is registered with the &app; project and
has read/write access to the repository. Also, it is assumed, that the
necessary environment variables are setup, so that &cvs; knows how to access
the repository. Details about the settings can be found on the <ulink
url="http://www.sourceforge.net/">SourceForge.net</ulink> web-site.
</para>

<para>
Throughout the next sections, the examples given use the &cvs; command line
interface. The options are abbreviated. The operations described here are also
accessible through various GUI clients available for &cvs;.  Also, I usually
use the -q (quiet) option to suppress some messages issued by &cvs;. If you
omit the -q option, the output differs from the one shown here, even though
the result of the operation is the same.
</para>

<section id="cvs-checkout">
<title>Checking out from the repository</title>
<para>
The very first operation is to fill the sandbox. This is done using the
<command>checkout</command> operation. The first time the repository is
checked-out, it's location must be specified. This is done using the
<command>-d</command> option. In the example below,
you must replace <emphasis>username</emphasis> with your real username at
SourcForge.net.

</para>

<example>
<title>Filling the sandbox for the first time</title>
<screen>

  <prompt>thb:~&gt; </prompt><userinput>cvs -d &cvs-user;@&cvs-host;:&cvs-dir; co &cvs-module;</userinput>


</screen>
<para>
During the checkout process, &cvs; lists all filenames on the users screen
and stores information about the repository's
location and all the files checked out in the sandbox. Therefor, you do not
need to specify the repository location during following &cvs; operations
anymore.
</para>

<para>
For the &app; project, a directory named <command>kmymoney2</command> is
created in your current working directory.
</para>
</example>

<para>
The above example fills the sandbox with the HEAD revision of all files.
This stage is sometimes referred to as the <quote>latest-and-greatest</quote>
and is the latest development stage.
</para>

<note>
<para>
If you plan to keep two or more branches of the project on your machine,
please see the chapter <emphasis>
<link linkend="multiple-branches">Keeping different
branches on the same machine</link></emphasis> for details.
</para>
</note>

<para>
If for some reason, you need to checkout a version of the project that is
different from the development stage (e.g. you want to fix a bug in a
stable version), you can fill an empty sandbox by supplying the version-tag
as parameter to the checkout command.
</para>

<example>
<title>Filling the sandbox for the first time with a specific version</title>
<screen>

  <prompt>thb:~&gt; </prompt><userinput>cvs -d &cvs-user;@&cvs-host;:&cvs-dir; co -r <emphasis>version-tag</emphasis> &cvs-module;</userinput>


</screen>
<para>
This will store the version labelled with the tag
<emphasis>version-tag</emphasis> in your sandbox. In case
<emphasis>version-tag</emphasis> is a branch-tag, you are able to modify
the files and check-in changes later on. In case,
<emphasis>version-tag</emphasis> is a standard tag, checkin operations will
be rejected by &cvs;.
</para>

<para>
As in the previous example, the directory kmymoney2 is created as the
sandbox.
</para>
</example>
</section>

<section id="cvs-checkin">
<title>Checking in to the repository</title>
<para>
Once the sandbox is filled, changes to the project will be 
applied by the developer. As soon as the developer is confident with the
changes, he is about to promote these changes to the other developers. He
does that by checking the changes back into the repository.
</para>

<para>
Checking changes back into the repository should start by performing an
update procedure as described in <link linkend="cvs-update">the next
section</link>. This may seem strange, but updateing your sandbox will
transfer changes performed by other developers in the meantime to your
sandbox. It is good practice to re-compile the project if you notice that
updateing the sandbox changes it's contents. This assures that the project
is still compilable when you check-in your changes.
</para>

<para>
The next step is to identify the changes you really want to promote. This
can be performed by the <command>diff</command> operation supported by
&cvs;.
</para>

<example>
<title>Promote changes to the repository</title>
<para>
For the following example, I assume a single file that has been changed in
the sandbox (~/kmymoney2/kmymoney2/knewbankdlg.cpp) and that the current
directory is ~/kmymoney2/kmymoney2. Also, it is assumed, that the file
README has been updated by another person in the repository. Since the
README file has no influence on the compile process, we omit recompiling in
this example.
</para>

<para>
The part of the original file that has been changed is shown here to
understand the output of the <userinput>cvs diff</userinput>
command shown below. The beginning of
the file is not included here as it is not changed.
</para>

<programlisting role="C++">

void KNewBankDlg::okClicked()
{
  if (nameEdit->text().isEmpty()) {
    KMessageBox::information(this, i18n("The institution name field is empty.  Please enter the name."), i18n("Adding New Institution"));
    nameEdit->setFocus();
    return;
  }

  m_name = nameEdit->text();
  m_city = cityEdit->text();
  m_street = streetEdit->text();
  m_postcode = postcodeEdit->text();
  m_telephone = telephoneEdit->text();
  m_managerName = managerEdit->text();
  m_sortCode = sortCodeEdit->text();
  accept();
}


</programlisting>

<para>
The changed version of the method is included here.
</para>

<screen>

void KNewBankDlg::okClicked()
{
  if (nameEdit->text().isEmpty()) {
    KMessageBox::information(this, i18n("The institution name field is empty.  Please enter the name."), i18n("Adding New Institution"));
    nameEdit->setFocus();

  } else {
    m_name = nameEdit->text();
    m_city = cityEdit->text();
    m_street = streetEdit->text();
    m_postcode = postcodeEdit->text();
    m_telephone = telephoneEdit->text();
    m_managerName = managerEdit->text();
    m_sortCode = sortCodeEdit->text();
    accept();
  }
}


</screen>

<para>
Now as the file has been changed, the changes should be promoted to the
repository. As explained above, the process starts with checking for
changes made by other people.
</para>
 
<screen>

  <prompt>thb:~&gt; </prompt><userinput>cvs -q upd</userinput>
  U README
  M knewbankdlg.cpp
  <prompt>thb:~&gt; </prompt>


</screen>

<para>
The above shown output has the following meaning: 
the file <command>README</command> is udpated (U) from the repository
to the sandbox because
it has been changed by someone else in the meantime. The contents of the file
in the sandbox will be replaced by the contents of the file in the
repository, because it has not been altered in the sandbox.
The file <command>knewbankdlg.cpp</command> has been modified (M) in the
sandbox and needs to be returned to the repository.
</para>

<para>
<anchor id="cvs-source-changes"/>
As the next step, one should check what has been changed in the file
<command>knewbankdlg.cpp</command>. This is done using the following command:
</para>

<screen>

  <prompt>thb:~&gt; </prompt><userinput>cvs -q diff knewbankdlg.cpp</userinput>
  74,75d73
  &lt;     return;
  &lt;   }
  77,84c75,84
  &lt;   m_name = nameEdit->text();
  &lt;   m_city = cityEdit->text();
  &lt;   m_street = streetEdit->text();
  &lt;   m_postcode = postcodeEdit->text();
  &lt;   m_telephone = telephoneEdit->text();
  &lt;   m_managerName = managerEdit->text();
  &lt;   m_sortCode = sortCodeEdit->text();
  &lt;   accept();
  ---
  >   } else {
  >     m_name = nameEdit->text();
  >     m_city = cityEdit->text();
  >     m_street = streetEdit->text();
  >     m_postcode = postcodeEdit->text();
  >     m_telephone = telephoneEdit->text();
  >     m_managerName = managerEdit->text();
  >     m_sortCode = sortCodeEdit->text();
  >     accept();
  >   }
  <prompt>thb:~&gt; </prompt>


</screen>
</example>

<para>
The output shows the changes between the current and the original revision
of the file. If this is what needs to be changed then the next step can be
started, which is checking the changes back into the repository.
</para>
<screen>

  <prompt>thb:~&gt; </prompt><userinput>cvs -q ci -m "Avoid return in the middle of a function" knewbankdlg.cpp</userinput>
  Checking in knewbankdlg.cpp;
  kmymoney2/kmymoney2/knewbankdlg.cpp,v  &lt;--  knewbankdlg.cpp
  new revision: 1.10; previous revision: 1.9
  done
  <prompt>thb:~&gt; </prompt>


</screen>


<note>
<para>
If the option -m and the descriptive text is omitted on the command line,
&cvs; starts an editor where the developer has to enter a descriptive text
about the changes and save that file. Performing checkin operations that
way is meaningful, if the description is longer or covers more than one file.
</para>
</note>

<para>
At this point, the changes are stored in the repository. An automatic mail
is generated and send to the kmymoney2-developer mailing list 
<email>[email protected]</email>. This mail
informs all other developers about your changes and is an indication for
them to <link linkend="cvs-update">update</link> their sandboxes. The
contents of the mail looks something like this:
</para>

<screen>

  From: Thomas Baumgart &lt;[email protected]>
  To: [email protected]
  Date: Sat, 24 Nov 2001 12:23:00 -0800
  Subject: [Kmymoney2-developer] CVS update:
 
  Update of /cvsroot/kmymoney2/kmymoney2/kmymoney2
  In directory usw-pr-cvs1:/tmp/cvs-serv6662

  Modified Files:
           knewbankdlg.cpp
  Log Message:
  Avoid return in the middle of a function
  _______________________________________________
  Kmymoney2-developer mailing list
  [email protected]
  https://lists.sourceforge.net/lists/listinfo/kmymoney2-developer



</screen>

<para>
While you checkin your changes, you should maintain the file
<command>kmymoney2/ChangeLog</command>. You could probably use the same
comments that you use for checkin in your changes or a more general note
for many changes. That depends on your changes. Once all your changes are
checked in, you also checkin <command>kmymoney2/ChangeLog</command>. 
</para>
</section>

<section id="cvs-update">
<title>Updateing changes performed by other developers</title>
<para>
In case you noticed that other developers changed the repository -
fortunately you will be noticed by a mail to the developer mailing list if
that is the case - you should get those changes to your sandbox. This is
accomplished using the <command>update</command> command of &cvs;.
</para>

<example>
<title>Updating the sandbox</title>
<para>
To update the local sandbox the following command is used. As most other
&cvs; commands, it operates recursively from the current working directory in
the sandbox.
</para>

<screen>

  <prompt>thb:~&gt; </prompt><userinput>cvs -q upd</userinput>
  U README
  M knewbankdlg.cpp
  <prompt>thb:~&gt; </prompt>


</screen>

<para>
The above shown output has the following meaning:
the file <command>README</command> is udpated (U) from the repository to
the sandbox because
it has been changed by someone else in the meantime. The contents of the
file
in the sandbox will be replaced by the contents of the file in the
repository, because it has not been altered in the sandbox.
The file <command>knewbankdlg.cpp</command> has been modified (M) in the
sandbox and needs to be returned to the repository.
</para>

<para>
If you run the same command again, the output will change, as the file
<command>README</command> is now up-to-date.
</para>

<screen>

  <prompt>thb:~&gt; </prompt><userinput>cvs -q upd</userinput>
  M knewbankdlg.cpp
  <prompt>thb:~&gt; </prompt>


</screen>


</example>

<para>
Sometimes it is useful to get an overview of what the status of certain
files in the repository is without modifying the sandbox (updating). This
can be accomplished by using the -n option to the update command.
</para>

<example>
<title>Checking the status of files in the sandbox</title>
<screen>

  <prompt>thb:~&gt; </prompt><userinput>cvs -nq upd</userinput>
  U README
  M knewbankdlg.cpp
  <prompt>thb:~&gt; </prompt>


</screen>

<para>
The status of the files is the same as explained above, but the file
<command>README</command>
will <emphasis>not</emphasis> be updated. It remains unchanged in the
sandbox. If you run this command again, the output remains.
</para>
</example>

</section>

<section id="dismissing-changes">
<title>Dismissing changes</title>
<para>
It happens, that a developer tries to modify the source to gain a certain
functionality and then wants to discard the changes. This is no problem at
all with &cvs;. All the developer needs to do is to remove the file in the
sandbox and run the <command>update</command> command of &cvs;. This will
transfer the original version of the file in question to the sandbox.
</para>

<para>
Let's assume, that the changes made to <command>knewbankdlg.cpp</command>
as outlined in <link linkend="cvs-source-changes">a previous chapter</link> should
be dismissed. The following commands perform this operation:
</para>

<example>
<title>Reverting changes made to the sandbox</title>
<screen>

  <prompt>thb:~&gt; </prompt><userinput>cvs -q upd</userinput>
  M knewbankdlg.cpp
  <prompt>thb:~&gt; </prompt><userinput>rm knewbankdlg.cpp</userinput>
  <prompt>thb:~&gt; </prompt><userinput>cvs -q upd</userinput>
  U knewbankdlg.cpp
  <prompt>thb:~&gt; </prompt><userinput>cvs -q upd</userinput>
  <prompt>thb:~&gt; </prompt>


</screen>
</example>

</section>

<section id="multiple-branches">
<title>Keeping different branches on the same machine</title>
<para>
Whenever a configuration manager of the project decides to create a new
stable release, the developers face a problem: they are not allowed to add
new features to the software, only bug-fixes can be checked into the
repository. Until the configuration manager opens the sources for further
development, the developers are stuck.
</para>

<para>
To avoid this dilemma, the configuration manager creates a branch off the
main development line when he creates the new stable release. Fixes will be
made to the release-branch, new developments will be made to the main
branch. This eliminates two problems: the configuration manager does not
have to lock the current stage and the developers can continue with the
implementation of features planned for the next release. Nevertheless, the
stable version can be changed (fixes can be applied) and those fixes can be
transferred to the main development branch so that they do not show up in
future releases of the software.
</para>

<para>
Since in our project the developers will work on both, bug fixes and new
development at the same time, it is convenient to have two sandboxes on the
development machine. For the following examples, I have two subdirectories
in my $HOME for the project. One is for the release and the other for the
develepment branch. I name them <command>stable</command> for the release
branch and
<command>devel</command> for the development branch.
</para>

<para><command>The development branch</command></para>
<para>
The development branch is the same as you use it today. Just move it from
it's current location to $HOME/devel. I kept it directly in my $HOME
directory so I did it as follows:

<example>
<title>Keeping stable and development branch on one machine</title>
<screen>

  <prompt>thb:~&gt; </prompt><userinput>md devel</userinput>
  <prompt>thb:~&gt; </prompt><userinput>md stable</userinput>
  <prompt>thb:~&gt; </prompt><userinput>mv kmymoney2 devel</userinput>
  <prompt>thb:~&gt; </prompt>


</screen>
</example>
Now the development sources are found in ~/devel/kmymoney2/. It is
important to move all the CVS directories as well. If you start from
scratch, then you just follow the instructions on how to checkout the
project and do that in the <command>devel</command> subdirectory. See the
chapter <emphasis>
<link linkend="cvs-checkout">Checking out from the repository</link>
</emphasis> for an example.
</para>

<para><command>The release branch</command></para>
<para>
As soon as a release branch has been created by the configuration manager,
you should get it to the stable directory. You do this by checking it out
with the tag that has been assigned. The conventions have been defined in
the chapter about <link linkend="version-mgmt">Version management</link>.
For this example, I assume that a release branch for version 0.4 exists in
the repository.

<footnote>
<para>Guess when I wrote this chapter ;-)</para>
</footnote>
</para>

<example>
<title>Checking out the stable branch for the first time</title>
<screen>

  <prompt>thb:~&gt; </prompt><userinput>cd stable</userinput>
  <prompt>thb:~/stable&gt; </prompt><userinput>cvs -d &cvs-user;@&cvs-host;:&cvs-dir; \ <footnote>
<para>
The back-slash is inserted here to break the line for readability. For real usage, the command has to be entered on a single line. 
</para>
</footnote>
                co -r <emphasis>rel-0-4-branch</emphasis> &cvs-module;</userinput>
  <prompt>thb:~/stable&gt; </prompt>


</screen>
</example>

<para>
At this point it is important to use the <emphasis>branch-tag</emphasis> to
be able to modifiy the files and check them back into the repository. If
you are in the subdirectory containing the release-branch and you perform a
<command>cvs update</command>, you will only get those changes, that were
made on the branch. Also, changes are checked back into the release branch
and do <emphasis>NOT</emphasis> show up on the development branch.
</para>

<note>
<para>
If you want to keep more than one stable branch on your development
machine, you can add the version number to the stable directory (e.g.
stable-0.4, etc.)
</para>
</note>
</section>

<section id="promoting-changes">
<title>Promoting bug-fixes to the main branch</title>
<para>
Usually, changes made to the release-branch fix a problem. In many cases the
problem still exists in the development branch. Therefor, it is
necessary to promote the changes made on the release branch back to the 
development branch. 
</para>

<para>
In most cases, it is very easy to promote the changes. The developer must
be very careful though, as the fix might not be applicable in it's form to
the development branch anymore as things might have changed drastically due
to new features.
<footnote>
<para>
This is one of the reasons, why I suggest to apply the fix to the release
branch and promote it to the developer branch, as the fix as it works on
the release branch might
break things and broken software is definitly something we do not want
 to happen on the stable branch.
</para>
</footnote>
</para>

<para>
In this example, I assume changes were made to the single file README.
<footnote>
<para>
Fortunately, the error found was a documentation problem ;-)
</para>
</footnote>

A complex fix
could cover many files. The procedure described in the following is then
required for each of them seperately. Further on, I assume that the change
has been checked in and that the revision was 1.14.2.1 before the fix and
is now 1.14.2.2.
</para>

<example>
<title>Promoting a change from the release to the development branch</title>
<screen>

  <prompt>thb:~&gt; </prompt><userinput>cd devel/kmymoney2</userinput>
  <prompt>thb:~/devel/kmymoney2&gt; </prompt><userinput>cvs -q upd -j 1.14.2.1 -j 1.14.2.2 README</userinput>
  <prompt>thb:~/devel/kmymoney2&gt; </prompt><userinput>vi README</userinput>
  <prompt>thb:~/devel/kmymoney2&gt; </prompt><userinput>cvs ci -m "Included fix #493920" README</userinput>
  <prompt>thb:~/devel/kmymoney2&gt; </prompt>


</screen>
</example>

<para>
First, I go into the devel directory. Then I promote the changes to the
README file in the development branch from the repository, verify the
changes made (and possibly correct them) and checkin the changes to the
development branch. That's it!
<footnote>
<para>
 Of course, a fix to a source code file would
be followed by a visual inspection (that's where <command>vi</command> or
<command>tdevelop</command> come into play) and a compile run with further
testing before the change is checked back into the repository.
</para>
</footnote>

</para>

<note>
<para>
It's important to perform this procedure for every file affected by the fix
seperatly, as the revision numbers usually differ significantly between
the files. Also, I suggest to fix each problem seperately. This reduces
further problems while promoting the changes back to the development
branch (e.g. one can leave out a fix completely if it does not apply at all
to the development branch). 
</para>
<para>
If the fix is very simple, it can certainly be promoted manually to the
development directory tree by merely re-typing it.
</para>
</note>
</section>

<section id="create-stable-example">
<title>Creating a new stable release</title>
<para>
The procedure that needs to be followed is defined in a <link
linkend="create-stable-procedure">previous chapter</link>.
On the first glimpse, it seems rather complecated but it is not.
</para>

<para>
If you follow the procedure as it has been defined, you will understand the
commands in our example. I assume to have a current unstable version of
0.3.x which will result in the stable version 0.4 and the next development
version of 0.5.x. Further on, I assume, that I already differentiate
between development and release directories. Also, the version number
maintained with KDevelop is setup correctly (0.4.pre1) and all files are
checked into the repository.
</para>

<example>
<title>Creating a new stable branch</title>

<screen>

  <prompt>thb:~&gt; </prompt><userinput>cd devel/kmymoney2</userinput>
  <prompt>thb:~/devel/kmymoney2&gt; </prompt><userinput>cvs tag rel-0-4-pre1</userinput>
  <prompt>thb:~/devel/kmymoney2&gt; </prompt><userinput>cvs tag -b rel-0-4-branch</userinput>

  Now modify the version number in KDevelop to 0.5.0, regenerate the files and
  checkin the changes as usual.

  <prompt>thb:~/devel/kmymoney2&gt; </prompt><userinput>cvs tag rel-0-5-base</userinput>
  <prompt>thb:~/devel/kmymoney2&gt; </prompt>


</screen>
</example>

<tip>
<para>
Because I know, that I will need the branch sooner or later to fix some
problems, I continue to check it out into the stable directory. See <link
linkend="multiple-branches">Keeping different branches on the same
machine</link> for details.
</para>
</tip>

</section>
</appendix>