File: chapter-8.texi

package info (click to toggle)
cvsbook 1.21-9
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 672 kB
  • ctags: 24
  • sloc: makefile: 103; python: 52; lisp: 24
file content (1056 lines) | stat: -rw-r--r-- 44,916 bytes parent folder | download | duplicates (3)
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
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
@c ---------------------------------------------------------
@node Tips And Troubleshooting
@unnumbered Tips And Troubleshooting

I've said in earlier chapters that CVS is not "black box" software.
Black boxes don't let you peek inside; they don't give you internal
access so that you can fix (or break) things.  The premise is that the
black box usually doesn't need to be fixed.  Most of the time, the
software should work perfectly, so users don't need internal access.
But when black boxes do fail, they tend to fail completely.  Any problem
at all is a showstopper, because there aren't many options for repair.

CVS is more like a perfectly transparent box -- except without the box.
Its moving parts are exposed directly to the environment, not
hermetically sealed off, and bits of that environment (unexpected file
permissions, interrupted commands, competing processes, whatever) can
sometimes get inside the mechanism and gum up the gears.  But even
though CVS does not always work perfectly, it rarely fails completely,
either.  It has the advantage of graceful degradation; the degree to
which it doesn't work is usually proportional to the number and severity
of problems in its environment.  If you know enough about what CVS is
trying to do -- and how it's trying to do it -- you'll know what to do
when things go wrong.

Although I can't list all of the problems that you might encounter, I've
included some of the more common ones here.  This chapter is divided
into two sections: The first describes those parts of the environment to
which CVS is most sensitive (mainly repository permissions and the
working copy administrative area), and the second describes some of the
most frequently encountered problems and their solutions.  By seeing how
to handle these common situations, you will get a feeling for how to
approach any unexpected problem in CVS.

@menu
* The Usual Suspects::                       Things that often cause trouble.
* General Troubleshooting Tips::             General diagnostic techniques.
* Some Real Life Problems (With Solutions):: A compendium of actual problems.
@end menu

@c ---------------------------------------------------------------
@node The Usual Suspects
@section The Usual Suspects

As a CVS administrator (read "field doctor"), you will find that 90
percent of your users' problems are caused by inconsistent working
copies, and the other 90 percent by incorrect repository permissions.
Therefore, before looking at any specific situations, I'll give a quick
overview of the working copy administrative area and review a few
important things about repository permissions.

@menu
* The Working Copy Administrative Area::
* Repository Permissions::
@end menu

@c ----------------------------------------------------------------
@node The Working Copy Administrative Area
@subsection The Working Copy Administrative Area

You've already seen the basics of working copy structure in @ref{An
Overview of CVS}; in this section, we'll go into a bit more detail.
Most of the details concern the files in the CVS/ administrative
subdirectories.  You already know about Entries, Root, and Repository,
but the CVS/ subdirectory can also contain other files, depending on the
circumstances.  I'll describe those other files here, partly so they
don't surprise you when you encounter them, and partly so you can fix
them if they ever cause trouble.

@heading @file{CVS/Entries.Log}

Sometimes, a file named @file{CVS/Entries.Log} will mysteriously appear.
The sole purpose of this file is to temporarily cache minor changes to
CVS/Entries, until some operation significant enough to be worth
rewriting the entire Entries file comes along.  CVS has no ability to
edit the Entries file in place; it must read the entire file in and
write it back out to make any change.  To avoid this effort, CVS
sometimes records small changes in Entries.Log, until the next time it
needs to rewrite Entries.

The format of Entries.Log is like Entries, except for an extra letter at
the beginning of each line. @code{A} means that the line is to be added
to the main Entries file, and @code{R} means it is to be removed.

For the most part, you can ignore Entries.Log; it's rare that a human
has to understand the information it contains.  However, if you're
reading over an Entries file to debug some problem in a working copy,
you should also examine Entries.Log.

@heading @file{CVS/Entries.Backup}

The CVS/Entries.Backup file is where CVS actually writes out a new
Entries file, before renaming it to @file{Entries} (similar to the way
it writes to temporary RCS files in the repository and then moves them
to their proper name when they're complete).  Because it becomes Entries
when it's complete, you'll rarely see an Entries.Backup file; if you do
see one, it probably means CVS got interrupted in the middle of some
operation.

@heading @file{CVS/Entries.Static}

If the CVS/Entries.Static file exists, it means that the entire
directory has not been fetched from the repository.  (When CVS knows a
working directory is in an incomplete state, it will not bring
additional files into that directory.)

The Entries.Static file is present during checkouts and updates and
removed immediately when the operation is complete.  If you see
Entries.Static, it means that CVS was interrupted, and its presence
prevents CVS from creating any new files in the working copy.  (Often,
running @w{@code{cvs update -d}} solves the problem and removes
Entries.Static.)

The absence of Entries.Static does not necessarily imply that the
working copy contains all of the project's files.  Whenever a new
directory is created in the project's repository, and someone updates
their working copy without passing the -d flag to update, the new
directory will not be created in the working copy.  Locally, CVS is
unaware that there is a new directory in the repository, so it goes
ahead and removes the Entries.Static file when the update is complete,
even though the new directory is not present in the working copy.

@heading @file{CVS/Tag}

If the CVS/Tag file is present, it names a tag associated, in some
sense, with the directory.  I say "in some sense" because, as you know,
CVS does not actually keep any revision history for directories and,
strictly speaking, cannot attach tags to them.  Tags are attached to
regular files only or, more accurately, to particular revisions in
regular files.

However, if every file in a directory is on a particular tag, CVS likes
to think of the entire directory as being on the tag, too.  For example,
if you were to check out a working copy on a particular branch:

@example
floss$ cvs co -r Bugfix_Branch_1
@end example

and then add a file inside it, you'd want the new file's initial
revision to be on that branch, too.  For similar reasons, CVS also needs
to know if the directory has a nonbranch sticky tag or date set on it.

Tag files contain one line.  The first character on the line is a
single-letter code telling what kind of tag it is, and the rest of the
line is the tag's name.  Currently, CVS uses only these three
single-letter codes:

@itemize

@item
T -- A branch tag

@item
N -- A nonbranch (regular) tag

@item
D -- A sticky date, which occurs if a command such as

@example
floss$ cvs checkout -D 1999-05-15 myproj
@end example

or

@example
floss$ cvs update -D 1999-05-15 myproj
@end example

is run.

@end itemize

(If you see some other single-letter code, it just means that CVS has
added a new tag type since this chapter was written.)

You should not remove the Tag file manually; instead, use @w{@code{cvs
update -A}}.

@heading Rarities

There are a few other files you may occasionally find in a CVS/ subdirectory:

@itemize
@item CVS/Checkin.prog, CVS/Update.prog
@item CVS/Notify, CVS/Notify.tmp
@item CVS/Base/, CVS/Baserev, CVS/Baserev.tmp
@item CVS/Template
@end itemize

These files are usually not the cause of problems, so I'm just listing
them (see @ref{CVS Reference} for their full descriptions).

@c -------------------------------------------------------------------
@heading Portability And Future Extension

As features are added to CVS, new files (not listed here) may appear in
working copy administrative areas.  As new files are added, they'll
probably be documented in the Cederqvist manual, in the node
@cite{Working Directory Storage}.  You can also start looking in
src/cvs.h in the source distribution, if you prefer to learn from code.

Finally, note that all CVS/* files -- present and future -- use whatever
line-ending convention is appropriate for the working copy's local
system (for example, LF for Unix or CRLF for Windows).  This means that
if you transport a working copy from one kind of machine to the other,
CVS won't be able to handle it (but then, you'd have other problems,
because the revision-controlled files themselves would have the wrong
line-end conventions for their new location).

@c --------------------------------------------------------
@node Repository Permissions
@subsection Repository Permissions

CVS does not require any particular repository permission scheme -- it
can handle a wide variety of permission arrangements.  However, to avoid
getting confusing behaviors, you should make sure your repository setup
meets at least the following criteria:

@itemize 

@item
If a user wants any kind of access at all -- even read-only access -- to
a given subdirectory of the repository, she usually needs file
system-level write permission to that subdirectory.  This is necessary
because CVS creates temporary lock files in the repository to ensure
data consistency.  Even read-only operations (such as checkout or
update) create locks, to signal that they need the data to stay in one
state until they're done.

As noted in @ref{Repository Administration}, you can get around this
writeability requirement by setting the LockDir parameter in
CVSROOT/config, like this:

@example
LockDir=/usr/local/cvslocks
@end example

Of course, then you would need to make sure the directory
/usr/local/cvslocks is writeable by all CVS users.  Either way, most CVS
operations, including read-only ones, are going to require a writeable
directory somewhere.  By default, that directory is the project's
repository; if you're very security conscious, you can change it to be
somewhere else.

@item
Make sure the CVSROOT/history file is world-writeable (if it exists at
all).  If the history file exists, most CVS operations attempt to append
a record to it; if the attempt fails, the operation exits with an error.

Unfortunately (and inexplicably), the history file is not born
world-writeable when you create a new repository with cvs init.  At
least with the current version of CVS, you should explicitly change its
permissions after you create a new repository (or just remove it, if you
want to disable history logging entirely).

(This problem may go away -- I just now submitted a patch to the CVS
maintainers that makes the history file world-writeable when you
initialize a new repository.  So perhaps if you get a more recent
version of CVS than the one available now (September 1999), it won't be
a problem for you.)

@item
For security purposes, you almost certainly want to make sure that most
CVS users do not have Unix-level write access to the CVSROOT directory
in the repository.  If someone has checkin access to CVSROOT, they can
edit commitinfo, loginfo, or any of the other trigger files to invoke a
program of their choice -- they could even commit a new program if the
one they want isn't on the system already.  Therefore, you should assume
that anyone who has commit access to CVSROOT is able to run arbitrary
commands on the system.

@end itemize

@c -------------------------------------------------------
@node General Troubleshooting Tips
@section General Troubleshooting Tips

The bulk of this chapter is organized into a series of questions and
answers, similar to an Internet FAQ (Frequently Asked Questions)
document.  These are all based on actual CVS experiences.  But before we
look at individual cases, let's take a moment to consider CVS
troubleshooting from a more general point of view.

The first step in solving a CVS problem is usually to determine whether
it's a working copy or repository problem.  The best technique for doing
that, not surprisingly, is to see if the problem occurs in working
copies other than the one where it was first noticed.  If it does, it's
likely a repository issue; otherwise, it's probably just a local issue.

Working copy problems tend to be encountered more frequently, not
because working copies are somehow less reliable than repositories, but
because each repository usually has many working copies.  Although most
working copy knots can be untied with enough patience, you may
occasionally find it more time-efficient simply to delete the working
copy and check it out again.

Of course, if checking out again takes too long, or there is
considerable uncommitted state in the working copy that you don't want
to lose, or if you just want to know what's wrong, it's worth digging
around to find the cause of the problem.  When you start digging around,
one of the first places to look is in the CVS/ subdirectories.  Check
the file contents and the file permissions.  Very occasionally, the
permissions can mysteriously become read-only or even unreadable.  (I
suspect this is caused by users accidentally mistyping Unix commands
rather than any mistake on CVS's part.)

Repository problems are almost always caused by incorrect file and
directory permissions.  If you suspect a problem may be due to bad
repository permissions, first find out the effective repository user ID
of the person who's having the trouble.  For all local and most remote
users, this is either their regular username or the username they
specified when they checked out their working copy.  If they're using
the pserver method with user-aliasing (see the section @ref{Anonymous
Access} in @ref{Repository Administration}), the effective user ID is
the one on the right in the CVSROOT/passwd file.  Failure to discover
this early on can cause you to waste a lot of time debugging the wrong
thing.

And now, without further ado...

@c ---------------------------------------------------------------
@node Some Real Life Problems (With Solutions)
@section Some Real Life Problems (With Solutions)

All of these situations are ones I've encountered in my real-life
adventures as a CVS troubleshooter (plus a few items that are not really
problems, just questions that I've heard asked so often that they may as
well be answered here).  The list is meant to be fairly comprehensive,
and it may repeat material you've seen in earlier chapters.

The situations are listed according to how frequently they seem to
arise, with the most common ones first.

@menu
* CVS says it is waiting for a lock; what does that mean?::
* CVS claims a file is failing Up-To-Date check; what do I do?::
* The pserver access method is not working::
* The pserver access method is STILL not working::
* My commits seem to happen in pieces instead of atomically::
* CVS keeps changing file permissions; why does it do that?::
* CVS on Windows complains it cannot find my .cvspass file; why?::
* My working copy is on several different branches; help?::
* When I do export -d I sometimes miss recent commits::
* I get an error about val-tags; what should I do?::
* I am having problems with sticky tags; how do I get rid of them?::
* Checkouts/updates exit with error saying cannot expand modules::
* I cannot seem to turn off watches::
* My binary files are messed up::
* CVS is not doing line-end conversion correctly::
* I need to remove a subdirectory in my project; how do I do it?::
* Can I copy .cvspass files or portions of them?::
* I just committed some files with the wrong log message::
* I need to move files around without losing revision history::
* How can I get a list of all tags in a project?::
* How can I get a list of all projects in a repository?::
* Some commands fail remotely but not locally; how should I debug?::
* I do not see my problem covered in this chapter::
* I think I have discovered a bug in CVS; what do I do?::
* I have implemented a new feature for CVS; to whom do I send it?::
* How can I keep up with changes to CVS?::
@end menu

@c ---------------------------------------------------------------------
@node CVS says it is waiting for a lock; what does that mean?
@subsection CVS says it is waiting for a lock; what does that mean?

If you see a message like this

@example
cvs update: [22:58:26] waiting for qsmith's lock in /usr/local/newrepos/myproj
@end example

it means you're trying to access a subdirectory of the repository that
is locked by some other CVS process at the moment.  A process is being
run in that directory so it may not be in a consistent state for other
CVS processes to use.

However, if the wait message persists for a long time, it probably means
that a CVS process failed to clean up after itself, for whatever reason.
It can happen when CVS dies suddenly and unexpectedly, say, due to a
power failure on the repository machine.

The solution is to remove the lock files by hand from the repository
subdirectory in question.  Go into that part of the repository and look
for files named @file{#cvs.lock} or that begin with @file{#cvs.wfl} or
@file{#cvs.rfl}.  Compare the file's timestamps with the start times of
any currently running CVS processes.  If the files could not possibly
have been created by any of those processes, it's safe to delete them.
The waiting CVS processes eventually notice when the lock files are gone
-- this should take about 30 seconds -- and allow the requested
operation to proceed.

See the node @cite{Locks} in the Cederqvist manual for more details.

@c ---------------------------------------------------------------------
@node CVS claims a file is failing Up-To-Date check; what do I do?
@subsection CVS claims a file is failing Up-To-Date check; what do I do?

Don't panic -- it just means that the file has changed in the repository
since the last time you checked it out or updated it.

Run @w{@code{cvs update}} on the file to merge in the changes from the
repository.  If the received changes conflict with your local changes,
edit the file to resolve the conflict.  Then try your commit again -- it
will succeed, barring the possibility that someone committed yet another
revision while you were busy merging the last changes.

@c ---------------------------------------------------------------------
@node The pserver access method is not working
@subsection The pserver access method is not working

The most common, less obvious cause of this problem is that you forgot
to list the repository using an @code{--allow-root} option in your inetd
configuration file.

Recall this example /etc/inetd.conf line from @ref{Repository
Administration}:

@example
cvspserver stream tcp nowait root /usr/local/bin/cvs cvs \
          --allow-root=/usr/local/newrepos pserver
@end example

(In the actual file, this is all one long line, with no backslash.)

The @code{--allow-root=/usr/local/newrepos} portion is a security
measure, to make sure that people can't use CVS to get pserver access to
repositories that are not supposed to be served remotely.  Any
repository intended to be accessible via pserver must be mentioned in an
@code{--allow-root}.  You can have as many different @code{--allow-root}
options as you need for all of your system's repositories (or anyway, as
many as you want until you bump up against your inetd's argument limit).

See @ref{Repository Administration} for more details on setting up the
password-authenticating server.

@c ---------------------------------------------------------------------
@node The pserver access method is STILL not working
@subsection The pserver access method is STILL not working

Okay, if the problem is not a missing @code{--allow-root}, here are a
few other possibilities:

@itemize

@item
The user has no entry in the CVSROOT/passwd file, and the CVSROOT/config
file has SystemAuth=no so CVS will not fall back on the system password
file (or SystemAuth=yes, but the system password file has no entry for
this user either).

@item
The user has an entry in the CVSROOT/passwd file, but there is no user
by that name on the system, and the CVSROOT/passwd entry does not map
the user to any valid system username.

@item
The password is wrong (but CVS is usually pretty good about informing
the user of this, so that's probably not the answer).

@item
Everything is set up correctly with the passwd files and in
/etc/inetd.conf, but you forgot an entry like this in /etc/services:

@example
cvspserver      2401/tcp
@end example

so inetd is not even listening on that port to pass connections off to
CVS.

@end itemize

@c ---------------------------------------------------------------------
@node My commits seem to happen in pieces instead of atomically
@subsection My commits seem to happen in pieces instead of atomically

That's because CVS commits happen in pieces, not atomically. :-)

More specifically, CVS operations happen directory by directory.  When
you do a commit (or an update, or anything else, for that matter)
spanning multiple directories, CVS locks each corresponding repository
directory in turn while it performs the operation for that directory.

For small- to medium-sized projects, this is rarely a problem -- CVS
manages to do its thing in each directory so quickly that you never
notice the nonatomicity.  Unfortunately, in large projects, scenarios
like the following can occur (imagine this taking place in a project
with at least two deep, many-filed subdirectories, A and B):

@enumerate

@item
User qsmith starts a commit, involving files from both subdirectories.
CVS commits the files in B first (perhaps because qsmith specified the
directories on the command line in that order).

@item
User jrandom starts a cvs update.  The update, for whatever reason,
starts with working copy directory A (CVS makes no guarantees about the
order in which it processes directories or files, if left to its own
devices).  Note that there is no locking contention, because qsmith is
not active in A yet.

@item
Then, qsmith's commit finishes B, moves on to A, and finishes A.

@item
Finally, jrandom's update moves on to B and finishes it.

@end enumerate

Clearly, when this is all over, jrandom's working copy reflects qsmith's
changes to B but not A.  Even though qsmith intended the changes to be
committed as a single unit, it didn't happen that way.  Now jrandom's
working copy is in a state that qsmith never anticipated.

The solution, of course, is for jrandom to do another cvs update to
fetch the uncaught changes from qsmith's commit.  However, that assumes
that jrandom has some way of finding out in the first place that he only
got part of qsmith's changes.

There's no easy answer to this quandary.  You simply have to hope that
the inconsistent state of the working copy will somehow become apparent
(maybe the software won't build, or jrandom and qsmith will have a
conversation that's confusing until they realize what must have
happened).

CVS's failure to provide @emph{atomic} transaction guarantees is widely
considered a bug.  The only reason that locks are not made at the top
level of the repository is that this would result in intolerably
frequent lock contentions for large projects with many developers.
Therefore, CVS has chosen the lesser of two evils, reducing the
contention frequency but allowing the possibility of interleaved reads
and writes.  Someday, someone may modify CVS (say, speeding up
repository operations) so that it doesn't have to choose between two
evils; until then, we're stuck with nonatomic actions.

For more information, see the node @cite{Concurrency} in the Cederqvist
manual.

@c ---------------------------------------------------------------------
@node CVS keeps changing file permissions; why does it do that?
@subsection CVS keeps changing file permissions; why does it do that?

In general, CVS doesn't do a very good job of preserving permissions on
files.  When you import a project and then check it out, there is no
guarantee that the file permissions in the new working copy will be the
same as when the project was imported.  More likely, the working copy
files will be created with the same standard permissions that you
normally get on newly created files.

However, there is at least one exception.  If you want to store
executable shell scripts in the project, you can keep them executable in
all working copies by making the corresponding repository file
executable:

@example
floss$ ls -l /usr/local/newrepos/someproj
total 6
-r--r--r--   1 jrandom  users         630 Aug 17 01:10 README.txt,v
-r-xr-xr-x   1 jrandom  users        1041 Aug 17 01:10 scrub.pl,v*
-r--r--r--   1 jrandom  users         750 Aug 17 01:10 hello.c,v
@end example

Notice that although the file is executable, it is still read-only, as
all repository files should be (remember that CVS works by making a
temporary copy of the RCS file, doing everything in the copy, and then
replacing the original with the copy when ready).

When you import or add an executable file, CVS preserves the executable
bits, so if the permissions were correct from the start, you have
nothing to worry about.  However, if you accidentally add the file
before making it executable, you must go into the repository and
manually set the RCS file to be executable.

The repository permissions always dominate.  If the file is
nonexecutable in the repository, but executable in the working copy, the
working copy file will also be nonexecutable after you do an update.
Having your files' permissions silently change can be extremely
frustrating.  If this happens, first check the repository and see if you
can solve it by setting the appropriate permissions on the corresponding
RCS files.

A feature called @code{PreservePermissions} has recently been added to
CVS that may alleviate some of these problems.  However, using this
feature can cause other unexpected results (which is why I'm not
recommending it unconditionally here).  Make sure you read the nodes
@cite{config} and @cite{Special Files} in the Cederqvist before putting
@code{PreservePermissions=yes} in CVSROOT/config.

@c ---------------------------------------------------------------------
@node CVS on Windows complains it cannot find my .cvspass file; why?
@subsection CVS on Windows complains it cannot find my .cvspass file; why?

For pserver connections, CVS on the client side tries to find the
.cvspass file in your home directory.  Windows machines don't have a
natural "home" directory, so CVS consults the environment variable
@code{%HOME%}.  However, you have to be very careful about how you set
HOME.  This will work:

@example
set HOME=C:
@end example

This will not:

@example
set HOME=C:\
@end example

That extra backslash is enough to confuse CVS, and it will be unable to
open @file{C:\\.cvspass}.

So, the quick and permanent solution is to put

@example
set HOME=C:
@end example

into your autoexec.bat and reboot.  CVS pserver should work fine after
that.

@c ---------------------------------------------------------------------
@node My working copy is on several different branches; help?
@subsection My working copy is on several different branches; help?

You mean different subdirectories of your working copy somehow got on
different branches?  You probably ran updates with the -r flag, but from
places other than the top level of the working copy.

No big deal.  If you want to return to the trunk, just run this

@example
cvs update -r HEAD
@end example

or this

@example
cvs update -A
@end example

from the top directory.  Or, if you want to put the whole working copy
on one of the branches, do this:

@example
cvs update -r Branch_Name
@end example

There's nothing necessarily wrong with having one or two subdirectories
of your working copy on a different branch than the rest of it, if you
need to do some temporary work on that branch just in those locations.
However, it's usually a good idea to switch them back when you're done
-- life is much less confusing when your whole working copy is on the
same line of development.

@c ------------------------------------------------------------------------
@node When I do export -d I sometimes miss recent commits
@subsection When I do export -d I sometimes miss recent commits

This is due to a clock difference between the repository and local
machines.  You can solve it by resetting one or both of the clocks, or
specifying a different date as the argument to -D.  It's perfectly
acceptable to specify a date in the future (such as -D tomorrow), if
that's what it takes to compensate for the time difference.

@c ---------------------------------------------------------------------
@node I get an error about val-tags; what should I do?
@subsection I get an error about val-tags; what should I do?

If you see an error like this:

@example
cvs [export aborted]: cannot write /usr/local/myproj/CVSROOT/val-tags: \
   Operation not permitted
@end example

it means the user CVS is running as does not have permission to write to
the CVSROOT/val-tags file.  This file stores valid tag names, to give
CVS a fast way to determine what tags are valid.  Unfortunately, CVS
sometimes modifies this file even for operations that are read-only with
respect to the repository, such as checking out a project.

This is a bug in CVS and may be fixed by the time you read this.  Until
then, the solution is either to make val-tags world-writeable or,
failing that, to remove it or change its ownership to the user running
the CVS operation.  (You'd think just changing the permissions would be
enough, but on several occasions I've had to change the ownership, too.)

@c ---------------------------------------------------------------------
@node I am having problems with sticky tags; how do I get rid of them?
@subsection I am having problems with sticky tags; how do I get rid of them?

Various CVS operations cause the working copy to have a @dfn{sticky
tag}, meaning a single tag that corresponds to each revision for each
file (in the case of a branch, the sticky tag is applied to any new
files added in the working copy).  You get a sticky tagged working area
whenever you check out or update by tag or date, for example:

@example
floss$ cvs update -r Tag_Name
@end example

or

@example
floss$ cvs checkout -D '1999-08-16'
@end example

If a date or a nonbranch tag name is used, the working copy will be a
frozen snapshot of that moment in the project's history -- so naturally
you will not be able to commit any changes from it.

To remove a sticky tag, run update with the -A flag

@example
floss$ cvs update -A
@end example

which clears all the sticky tags and updates each file to its most
recent trunk revision.

@c ---------------------------------------------------------------------
@node Checkouts/updates exit with error saying cannot expand modules
@subsection Checkouts/updates exit with error saying cannot expand modules

This is just a case of a bad error message in CVS; probably someone will
get around to fixing it sooner or later, but meanwhile it may bite you.
The error message looks something like this:

@example
floss$ cvs co -d bwf-misc user-space/bwf/writings/misc 
cvs server: cannot find module `user-space/bwf/writings/misc' - ignored
cvs [checkout aborted]: cannot expand modules
@end example

CVS appears to be saying that there's something wrong with the
CVSROOT/modules file.  However, what's really going on is a permission
problem in the repository.  The directory I'm trying to check out isn't
readable, or one of its parents isn't readable.  In this case, it was a
parent:

@example
floss$ ls -ld /usr/local/cvs/user-space/bwf

drwx------  19 bwf      users        1024 Aug 17 01:24 bwf/
@end example

Don't let that egregiously wrong error message fool you -- this is a
repository permission problem.

@c ---------------------------------------------------------------------
@node I cannot seem to turn off watches
@subsection I cannot seem to turn off watches

You probably did

@example
floss$ cvs watch remove
@end example

on all the files, but forgot to also do:

@example
floss$ cvs watch off
@end example

A hint for diagnosing watch problems: Sometimes it can be immensely
clarifying to just go into the repository and examine the CVS/fileattr
files directly.  See @ref{Repository Administration} for more
information about them.

@c ---------------------------------------------------------------------
@node My binary files are messed up
@subsection My binary files are messed up

Did you remember to use -kb when you added them?  If not, CVS may have
performed line-end conversion or RCS keyword substitution on them.  The
easiest solution is usually to mark them as binary

@example
floss$ cvs admin -kb foo.gif
@end example

and then commit a fixed version of the file.  CVS will not corrupt the
new commit or any of the commits thereafter, because it now knows the
file is binary.

@c ---------------------------------------------------------------------
@node CVS is not doing line-end conversion correctly
@subsection CVS is not doing line-end conversion correctly

If you're running the CVS client on a non-Unix platform and are not
getting the line-end conventions that you want in some working copy
files, it's usually because they were accidentally added with -kb when
they shouldn't have been.  This can be fixed in the repository with,
believe it or not, the command:

@example
floss$ cvs admin -kkv FILE
@end example

The -kkv means to do normal keyword substitution and implies normal
line-end conversions as well.  (Internally, CVS is a bit confused about
the difference between keyword substitution and line-end conversion.
This confusion is reflected in the way the -k options can control both
parameters.)

Unfortunately, that admin command only fixes the file in the repository
-- your working copy still thinks the file is binary.  You can hand edit
the CVS/Entries line for that file, removing the -kb, but that won't
solve the problem for any other working copies out there.

@c ---------------------------------------------------------------------
@node I need to remove a subdirectory in my project; how do I do it?
@subsection I need to remove a subdirectory in my project; how do I do it?

Well, you can't exactly remove the subdirectory, but you can remove all
of the files in it (first remove them, then cvs remove them, and then
commit).  Once the directory is empty, people can have it automatically
pruned out of their working copies by passing the -P flag to update.

@c ---------------------------------------------------------------------
@node Can I copy .cvspass files or portions of them?
@subsection Can I copy .cvspass files or portions of them?

Yes, you can.  You can copy @file{.cvspass} files from machine to
machine, and you can even copy individual lines from one .cvspass file
to another.  For high-latency servers, this may be faster than running
cvs login from each working copy machine.

Remember that if you transport a .cvspass file between two machines with
different line-ending conventions, it probably won't work (of course,
you can probably do the line-end conversion manually without too much
trouble).

@c ---------------------------------------------------------------------
@node I just committed some files with the wrong log message
@subsection I just committed some files with the wrong log message

You don't need to hand-edit anything in the repository to solve this.
Just run admin with the -m flag.  Remember to have no space between -m
and its argument, and to quote the replacement log message as you would
a normal one:

@example
floss$ cvs admin -m1.17:'I take back what I said about the customer.' hello.c
@end example

@c ---------------------------------------------------------------------
@node I need to move files around without losing revision history
@subsection I need to move files around without losing revision history

In the repository, copy (don't move) the RCS files to the desired new
location in the project.  They must remain in their old locations as
well.  Then, in a working copy, do:

@example
floss$ rm oldfile1 oldfile2 ...
floss$ cvs remove oldfile1 oldfile2 ...
floss$ cvs commit -m removed from here oldfile1 oldfile2 ...
@end example

When people do updates after that, CVS correctly removes the old files
and brings the new files into the working copies just as though they had
been added to the repository in the usual way (except that they'll be at
unusually high revision numbers for supposedly new files).

@c ---------------------------------------------------------------------
@node How can I get a list of all tags in a project?
@subsection How can I get a list of all tags in a project?

Currently, there is no convenient way to do this in CVS.  The lack is
sorely felt by all users, and I believe work is under way to make this
feature available.  By the time you read this, a @w{@code{cvs tags}}
command or something similar may be available.

Until then, there are workarounds.  You can run cvs log -h and read the
sections of the output following the header @code{symbolic names:}.  Or,
if you happen to be on the repository machine, you can just look at the
beginnings of some of the RCS files directly in the repository.  All of
the tags (branches and nonbranches) are listed in the @code{symbols}
field:

@example
floss$ head /usr/local/newrepos/hello.c,v
head	2.0;
access;
symbols
	Release_1_0:1.22
	Exotic_Greetings-2:1.21
	merged-Exotic_Greetings-1:1.21
	Exotic_Greetings-1:1.21
	merged-Exotic_Greetings:1.21
	Exotic_Greetings-branch:1.21.0.2
	Root-of-Exotic_Greetings:1.21
	start:1.1.1.1
	jrandom:1.1.1;
locks; strict;
comment	@@ * @@;
@end example

@c ---------------------------------------------------------------------
@node How can I get a list of all projects in a repository?
@subsection How can I get a list of all projects in a repository?

As with getting a list of tags, this is not implemented in the most
current version of CVS, but it's highly likely that it will be
implemented soon.  I imagine the command will be called cvs list with a
short form of cvs ls, and it probably will both parse the modules file
and list the repository subdirectories.

In the meantime, examining the CVSROOT/modules file (either directly or
by running cvs checkout -c) is probably your best bet.  However, if no
one has explicitly made a module for a particular project, it won't show
up there.

@c ---------------------------------------------------------------------
@node Some commands fail remotely but not locally; how should I debug?
@subsection Some commands fail remotely but not locally; how should I debug?

Sometimes there's a problem in the communication between the client and
the server.  If so, it's a bug in CVS, but how would you go about
tracking down such a thing?

CVS gives you a way to watch the protocol between the client and server.
Before you run the command on the local (working copy) machine, set the
environment variable @code{CVS_CLIENT_LOG}.  Here's how in Bourne shell
syntax:

@example
floss$ CVS_CLIENT_LOG=clog; export CVS_CLIENT_LOG
@end example

Once that variable is set, CVS will record all communications between
client and server in two files whose names are based on the variable's
value:

@example
floss$ ls
CVS/        README.txt    a-subdir/    b-subdir/    foo.gif     hello.c
floss$ cvs update
? clog.in
? clog.out
cvs server: Updating .
cvs server: Updating a-subdir
cvs server: Updating a-subdir/subsubdir
cvs server: Updating b-subdir
floss$ ls
CVS/              a-subdir/    clog.in     foo.gif
README.txt        b-subdir/    clog.out    hello.c
floss$ 
@end example

The @file{clog.in} file contains everything that the client sent into
the server, and @file{clog.out} contains everything the server sent back
out to the client.  Here are the contents of clog.out, to give you a
sense of what the protocol looks like:

@example
Valid-requests Root Valid-responses valid-requests Repository           \
Directory Max-dotdot Static-directory Sticky Checkin-prog Update-prog   \
Entry Kopt Checkin-time Modified Is-modified UseUnchanged Unchanged     \
Notify Questionable Case Argument Argumentx Global_option Gzip-stream   \
wrapper-sendme-rcsOptions Set expand-modules ci co update diff log add  \
remove update-patches gzip-file-contents status rdiff tag rtag import   \
admin export history release watch-on watch-off watch-add watch-remove  \
watchers editors init annotate noop
ok
M ? clog.in
M ? clog.out
E cvs server: Updating .
E cvs server: Updating a-subdir
E cvs server: Updating a-subdir/subsubdir
E cvs server: Updating b-subdir
ok
@end example

The clog.in file is even more complex, because it has to send revision
numbers and other per-file information to the server.

There isn't space here to document the client/server protocol, but you
can read the @code{cvsclient} Info pages that were distributed with CVS
for a complete description.  You may be able to figure out a good deal
of it just from reading the raw protocol itself.  Although you probably
won't find yourself using client logging until you've eliminated all of
the other possible causes of a problem, it is an invaluable tool for
finding out what's really going on between the client and server.

@c ---------------------------------------------------------------------
@node I do not see my problem covered in this chapter
@subsection I do not see my problem covered in this chapter

Email an accurate and complete description of your problem to
@email{info-cvs@@gnu.org}, the CVS discussion list.  Its members are
located in many different time zones, and I've usually gotten a response
within an hour or two of sending a question.  Please join the list by
sending email to @email{info-cvs-request@@gnu.org}, so you can help
answer questions, too.

@c ---------------------------------------------------------------------
@node I think I have discovered a bug in CVS; what do I do?
@subsection I think I have discovered a bug in CVS; what do I do?

CVS is far from perfect -- if you've already tried reading the manual
and posting a question on the mailing list, and you still think you're
looking at a bug, then you probably are.

Send as complete a description of the bug as you can to
@email{bug-cvs@@gnu.org} (you can also subscribe to that list; just use
@email{bug-cvs-request@@gnu.org} instead).  Be sure to include the
version number of CVS (both client and server versions, if applicable),
and a recipe for reproducing the bug.

If you have written a patch to fix the bug, include it and mention on
the subject line of your message that you have a patch.  The maintainers
will be very grateful.

(Further details about these procedures are outlined in the node
@cite{BUGS} in the Cederqvist manual and the file HACKING in the source
distribution.)

@c ---------------------------------------------------------------------
@node I have implemented a new feature for CVS; to whom do I send it?
@subsection I have implemented a new feature for CVS; to whom do I send it?

Same as with a bug: Send the patch to @email{bug-cvs@@gnu.org}.  Make
sure you've read over the HACKING file first, though.

@c ---------------------------------------------------------------------
@node How can I keep up with changes to CVS?
@subsection How can I keep up with changes to CVS?

The troubleshooting techniques and known bugs described in this chapter
are accurate as of (approximately) CVS Version 1.10.7.  Things move fast
in the CVS world, however.  While I was writing the last few chapters,
the unofficial mantle of CVS maintainership passed from Cyclic Software
to SourceGear, Inc (@uref{http://www.sourcegear.com}), which purchased
Cyclic.  SourceGear has publicly announced its intention to take an
active role in CVS maintainer-ship and has received Cyclic's approval,
which is more or less enough to make it the "lead maintainer" of CVS as
of right now.  (The @uref{http://www.cyclic.com} address will continue
to work, however, so all of the URLs given previously in this book
should remain valid.)

SourceGear is, at this very moment, busy organizing and cleaning up
various patches that have been floating around, with the intention of
incorporating many of them into CVS.  Some of these patches will
probably fix bugs listed previously, and others may afford new
troubleshooting tools to CVS users.

The best way to stay up to date with what's going on is to read the NEWS
file in your CVS distribution, watch the mailing lists, and look for
changes to the Cederqvist manual and the online version of this book
(@uref{http://cvsbook.red-bean.com}).