Re: CVS & .nibs
Re: CVS & .nibs
- Subject: Re: CVS & .nibs
- From: Bill Bumgarner <email@hidden>
- Date: Tue, 26 Jun 2001 10:37:29 -0400
[Taking the liberty of cross posting because this'll probably be useful
to a number of folks on all three lists. Also, I wrote a hints/tips
email regarding CVS a few months ago-- if you are dealing with CVS on a
regular basis, I would suggest having a look for that message in the
archive.]
In versions of EOModeler prior to that shipped with WebObjects 4.5
(4.0?), you need the EOModeler bundle from Omni that preserves the CVS
directory information in a fashion similar to the Omni IB palette that
is no longer needed with OSX.
In any case, for both EOModels and NIB files, treat them as a normal
directory. As Ian suggested, add the wrapper information that treats
the objects.nib as a binary file, but treat everything else (save for
images, if you happen to have 'em in the NIB file-- not recommended) as
text.
I.e. Say I created the project FooApp-- a Cocoa application using
EOF/Java-- and I want to add it to my cvs repository. The cvs
repository's CVSROOT specification is
"borg.codefab.com:/some/path/cvsroot/".
The first thing I would do is ensure that there is a top level directory
in CVS that contains the project and any other stuff. This ensures
that you always have a single directory that you can check things out
against and get everything in the repository related to your project.
So, I start by building a directory structure something like:
FooProject/
README.txt
FooApp/
... project stuff here ...
The next step is go into the FooApp directory and make sure that every
file in the project is a file that you really want in the CVS
repository. CVS takes that attitude that once something has been added
to a repository, subsequent removal should be a fully audited event. As
such, it can be a pain to remove files/directories after the initial
import. You are far better off ensuring that the hierarchy of stuff to
be imported into CVS is clean and has a structure that you plan on
sticking with. The most painful CVS task is to restructure a project
to reflect naming changes and hierarchy changes-- you are generally
better of using 'cvs export' to export a copy of the source, then 'cvs
import' to create a new repository.
In any case, after cleaning, we use the following command to import the
source:
[localhost:~/FooProject] bbum% cvs -d localhost:/tmp/cvsroot import -m
'Importing base.' FooProject CODEFAB REL_000
bbum@localhost's password:
U FooProject/README.txt
cvs server: Importing /tmp/cvsroot/FooProject/FooApp
N FooProject/FooApp/FooAppDelegate.java
N FooProject/FooApp/main.m
cvs server: Importing /tmp/cvsroot/FooProject/FooApp/English.lproj
N FooProject/FooApp/English.lproj/InfoPlist.strings
cvs server: Importing
/tmp/cvsroot/FooProject/FooApp/English.lproj/MainMenu.nib
.........
N FooProject/FooApp/German.lproj/MainMenu.nib/info.nib
N FooProject/FooApp/German.lproj/MainMenu.nib/objects.nib
cvs server: Importing /tmp/cvsroot/FooProject/FooApp/Japanese.lproj
N FooProject/FooApp/Japanese.lproj/InfoPlist.strings
cvs server: Importing
/tmp/cvsroot/FooProject/FooApp/Japanese.lproj/MainMenu.nib
N FooProject/FooApp/Japanese.lproj/MainMenu.nib/classes.nib
N FooProject/FooApp/Japanese.lproj/MainMenu.nib/info.nib
N FooProject/FooApp/Japanese.lproj/MainMenu.nib/objects.nib
No conflicts created by this import
VERY IMPORTANT: At this point, you want to verify that things have
been correctly added to the repository and then *delete the tree of
stuff that you imported*. Yes, delete it. This will prevent you from
continuing development in that tree of stuff. A cvs import does not
make the tree you are importing into a cvs controlled workarea-- if you
DO continue working in it while other developers have checked out copies
of the repository in the normal fashion and have committed changes, you
will be facing a nasty integration issue. So:
[localhost:~] bbum% cd ~/Developer
cvs -d localhost:/tmp/cvsroot checkout FooProject
cvs server: Updating FooProject
U FooProject/README.txt
cvs server: Updating FooProject/FooApp
U FooProject/FooApp/FooAppDelegate.java
U FooProject/FooApp/main.m
..............
U FooProject/FooApp/Japanese.lproj/MainMenu.nib/classes.nib
U FooProject/FooApp/Japanese.lproj/MainMenu.nib/info.nib
U FooProject/FooApp/Japanese.lproj/MainMenu.nib/objects.nib
[localhost:~/Developer] bbum% diff -x CVS -r ~/FooProject FooProject
[localhost:~/Developer] bbum%
Good-- no differences between the imported tree and the tree checked out
from the workarea. (omit the -x CVS and you will see that there are
differences; the second tree has the all important CVS administrative
directories).
Now that it has been imported, we should assert that the appropriate
administrative flags have been set on files that should be handled as
binary:
[localhost:~/Developer] bbum% cd
FooProject/FooApp/French.lproj/MainMenu.nib/
[localhost:FooApp/French.lproj/MainMenu.nib] bbum% cvs status -v
objects.nib
===================================================================
File: objects.nib Status: Up-to-date
Working revision: 1.1.1.1
Repository revision: 1.1.1.1
/tmp/cvsroot/FooProject/FooApp/French.lproj/MainMenu.nib/objects.nib,v
Sticky Tag: (none)
Sticky Date: (none)
Sticky Options: -kb
Existing Tags:
REL_000 (revision: 1.1.1.1)
CODEFAB (branch: 1.1.1)
The Sticky Options indicate that the file is being handled as a binary
file. The working version and branching information is fallout from
doing a cvs import. As soon as you commit any file, the working
revision of that file will become "1.2" (etc). This may seem odd, but
can actually be quite helpful when tracking and modifying third part
sources. It means that you can always switch to the branch of code
containing exactly what was shipped to you, can then apply patches, and
subsequently use 'cvs update' to apply the patches on the branch to the
main trunk of development.
If the objects.nib did NOT have the -kb flag because you forgot to
modify the cvswrappers file then, you would need to:
[localhost:FooApp/German.lproj/MainMenu.nib] bbum% cvs admin -kb
objects.nib
This will add the binary flag. However, you *must* verify that the file
hasn't been corrupted by cvs keyword expansion!!!! If it has been, you
will need to:
[localhost:FooApp/German.lproj/MainMenu.nib] cp
~/FooProject/FooApp/German.lproj/MainMenu.nib/objects.nib objects.nib
[localhost:FooApp/German.lproj/MainMenu.nib] bbum% cvs commit -m 'Fixed
objects.nib because keyword expansion blew it up. Copied original.'
cvs commit: Examining .
Checking in objects.nib;
/tmp/cvsroot/FooProject/FooApp/German.lproj/MainMenu.nib/objects.nib,v <--
objects.nib
new revision: 1.2; previous revision: 1.1
done
Note: If keyword expansion HAD actually blown up any of the files in
your project, the diff command shown above would have identified the
files that had been modified.
Note2: CVS keyword expansion basically substitutes various bits of
information for things like $Id$ and $Log$. While they sound useful,
they really aren't. In particular, they pretty much guarantee that any
two revisions of a file will have differences. In particular, the $Log$
ensures that you will run into a constant stream of conflicts when
updating your workarea. There are far better ways of dealing with this
information.
Build the project and make sure it does what you expect.
Now that we have verified that the project works as checked out from the
repository-- that it is identical to our originally imported source-- go
ahead and remove the originally imported tree of goo to prevent making
the mistake of doing any kind of development work on it. At this point,
the cvs repository is your master copy. We basically ensure the cvs
repository is backed up in at least 2 locations-- one via rsync to
another host (a hot nightly backup) and one to tape. We treat
workareas as totally throwaway; they are not backed up and the
developer is encouraged to make sure they check in working code early
and often. This minimizes integration issues and, combined with testing
suites, ensures that the software continues to work as a system and not
just as individual pieces.
[localhost:~/Developer] bbum% rm -rf ~/FooProject
That'll keep me from wasting more of my life doing unnecessary code
integrations.... :-)
As you work with the project, always use 'cvs -q update -dP' to update
your workarea. Do this often; more often then needed to simply pull
changes from the repository. Not only will this reduce integration
issues, it also gives you an inventory of every file in your workarea
that isn't controlled by CVS. For example:
[localhost:~/Developer/FooProject/FooApp] bbum% cvs -q update -dP
? MyDocument.java
? German.lproj/MyDocument.nib
This indicates that I have a nib file and a java file in my workarea
that are not in CVS. To add:
[localhost:~/Developer/FooProject/FooApp] bbum% cvs add MyDocument.java
German.lproj/MyDocument.nib
? German.lproj/MyDocument.nib/classes.nib
? German.lproj/MyDocument.nib/info.nib
? German.lproj/MyDocument.nib/objects.nib
cvs server: scheduling file `MyDocument.java' for addition
Directory /tmp/cvsroot/FooProject/FooApp/German.lproj/MyDocument.nib
added to the repository
cvs server: use 'cvs commit' to add this file permanently
OK-- I added the .niib directory, and now CVS is telling me the contents
of that directory are not under CVS control. Need to add those, as well:
[localhost:~/Developer/FooProject/FooApp] bbum% cvs add
German.lproj/MyDocument.nib/*.nib
cvs server: scheduling file `German.lproj/MyDocument.nib/classes.nib'
for addition
cvs server: scheduling file `German.lproj/MyDocument.nib/info.nib' for
addition
cvs server: scheduling file `German.lproj/MyDocument.nib/objects.nib'
for addition
cvs server: use 'cvs commit' to add these files permanently
Finally, another cvs update to check the status on my workarea:
[localhost:~/Developer/FooProject/FooApp] bbum% cvs -q update -dP
bbum@localhost's password:
A MyDocument.java
A German.lproj/MyDocument.nib/classes.nib
A German.lproj/MyDocument.nib/info.nib
A German.lproj/MyDocument.nib/objects.nib
Might as well check to make sure that the objects.nib will be handled as
a binary file:
[localhost:~/Developer/FooProject/FooApp] bbum% cvs status -v
German.lproj/MyDocument.nib/objects.nib
===================================================================
File: objects.nib Status: Locally Added
Working revision: New file!
Repository revision: No revision control file
Sticky Tag: (none)
Sticky Date: (none)
Sticky Options: -kb
Yup; commit:
[localhost:~/Developer/FooProject/FooApp] bbum% cvs -q commit -m 'Added
MyDocument interface and implementation [interface in German only, for
now].'
RCS file: /tmp/cvsroot/FooProject/FooApp/MyDocument.java,v
done
Checking in MyDocument.java;
/tmp/cvsroot/FooProject/FooApp/MyDocument.java,v <-- MyDocument.java
initial revision: 1.1
done
......
Checking in German.lproj/MyDocument.nib/objects.nib;
/tmp/cvsroot/FooProject/FooApp/German.lproj/MyDocument.nib/objects.nib,v <--
objects.nib
initial revision: 1.1
done
See the other message for a bunch of hints/tips regarding "power" use of
CVS. Some final tips:
- if you cp -r a NIB file (or Save As.... from Interface Builder), ***
MAKE SURE *** you remove the CVS directory from the COPY. DO NOT SCREW
THIS UP. If you do screw it up, you are in for a bit of hell undoing
the problem. Notably, CVS really doesn't care about directories-- the
copied CVS entries will cause the contents of the .nib to effectively
overwrite the original version. Thankfully, everything is revision
controlled, so you should be able to recover the original versions. But
straightening out your workarea and the repository is not fun. If I
get a chance, I'll write up an email demonstrating exactly how much fun
it isn't.
- CVL.app is an excellent CVS GUI. Check it out; see SoftTrak at
www.stepwise.com to find the latest version. Even with a good GUI, it
is a wise idea to understand what is going on under the covers. CVL
(and others) basically drive the command line cvs by stuffing various
permutations of arguments and executing the command line binary via,
say, NSTask.
- Project Builder's SCM integration is almost very very cool. At this
point, I use it to view differences between my workarea and repository,
but I use the command line to take care of all actual read/write
operations. It will likely get better in future releases.
good luck,
b.bum
---
* if we were really starting from scratch, I would do:
bbum% cvs -t -d borg.codefab.com:/some/path/cvsroot/ init
... to initialize the repository. I could then check out the CVSROOT
directory....
[localhost:~] bbum% cvs -d borg.codefab.com:/some/path/cvsroot/
checkout CVSROOT
cvs server: Updating CVSROOT
U CVSROOT/checkoutlist
U CVSROOT/commitinfo
U CVSROOT/config
U CVSROOT/cvswrappers
.....
...and add the objects.nib specification to cvswrappers...
[localhost:~] bbum% cd CVSROOT
[localhost:~/CVSROOT] bbum% tail cvswrappers
# -k expansion mode value: b, o, kkv, &c
#
# and value is a single-quote delimited value.
# For example:
*.gif -k 'b'
*.tiff -k 'b'
*.jpeg -k 'b'
*.icns -k 'b'
objects.nib -k 'b'
*.rsrc -k 'b'
[localhost:~/CVSROOT] bbum% cvs commit -m 'Added an incomplete set of
binary specs for Cocoa development.'
cvs commit: Examining .
Checking in cvswrappers;
/some/path/cvsroot//CVSROOT/cvswrappers,v <-- cvswrappers
new revision: 1.2; previous revision: 1.1
done
cvs server: Rebuilding administrative file database
You may also want to edit the cvsignore file and make sure it contains a
reasonable set of files to ignore. Keep in mind that the ignore
behavior is different between add and import-- one of the wonderful
little quirks of CVSs ultra inconsistent design and implementation.
On Tuesday, June 26, 2001, at 01:58 AM, Stefan M. van den Oord wrote:
Thought cvswrappers sort of / kind of work and are included with OSX,
do not use them unless you absolutely have to.
Indeed today I discovered that the /Developer/Tools/cvswrappers doesn't
work
with my Linux box (which has CVS 1.11.1). I understand the explanation
about
avoiding tar-wrappers (I didn't feel to good about that anyway). But
what
exactly should be done instead? Ian suggested adding objects.nib as a
binary, but I understand that EOModels need something as well?
I would greatly appreciate it if somebody could come up with a
cvswrappers
that solves the same problems as /Developer/Tools/cvswrappers does, but
that
also works with CVS 1.11.1.
Kind regards,
Stefan
--
Stefan M. van den Oord
email@hidden