[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: CVS diff and unknown files.

From: Paul Sander
Subject: Re: CVS diff and unknown files.
Date: Fri, 28 Jan 2005 00:11:45 -0800

On Jan 27, 2005, at 1:07 AM, address@hidden wrote:

Paul Sander <address@hidden> writes:
What "register adds in the repo" nonsense are you talking about? The
proposal I made simply requires a contact with the server to run the
add-time triggers; it does NOT require add-time modifications of the
repository by the CVS server itself. If the triggers drop turds in the
repository, then that's a different matter. Also remember that my
proposal includes a way to shut off the add-time triggers as a client
configuration, deferring them to commit time to accommodate users like

Just to understand your point better, do you propose 'cvs add -c
new_file' and 'cvs ci new_file' run exactly the same set of triggers?
Different sets?

I think the consensus in the last iteration of the topic was that, if add-time triggers were implemented, they would run as a client-side option at add-time and and be obligatory at commit time, preceding commit-time triggers. Doubling the overhead was the only way we came up with at the time that guaranteed that the add-time triggers fired at least once prior to the first commit of a new file.

Another point that I would like to make, however, is that CVS can
become more feature-rich, support multiple policies, and have a
simpler user interface (in most use cases, at least) all at the same
time. The problem is that most of us here are too close to the
implementation to take a fresh view of the problem.

In the core CVS program the "cvs add" and "cvs remove" operations
must be fixed to be equivalent to "vi file.c" -- i.e. operations
which _ONLY_ affect the local working directory and which _NEVER_
contact the server.

See above. If there are no add-time triggers, then I can live with
what you say. On the other hand, some shops REQUIRE add-time triggers,
and if add-time triggers are used then contacting the server is
REQUIRED to make them run.

Sorry, add-time with respect to what? Add-time w.r.t. to working copy is
entirely different from the add-time w.r.t. repository. Do you realize
currently there is no command but 'cvs ci' meaning "add this file to the
repository"? Add time w.r.t. repository currently happens when you 'cvs
commit' the new file. Do you propose to change this?

What I mean by "add-time" is the moment in which the user invokes the "cvs add" command. The canonical example of such a trigger is one that enforces naming conventions, but there are other reasons to control what the user can add. (Some shops don't want users creating directories, for example, and require the CM team to do it for them.)

When "cvs add" runs, I don't care whether or not the CVS server modifies the repository. Some people seem to think that running "cvs add" while disconnected is a useful thing to do. (I take the attitude that client/server applications shouldn't be expected to run without a working network, so I'd never run any CVS command when I was unable to connect to the server.) However, since triggers enforce policy and must not be defeatable, e.g. by changing one's path or bypassing a wrapper or hacking the client machine, they're best implemented as a server feature. It's for that reason, assuming add-time triggers are implemented, they require a connection to the server.

In fact the semantics of proposed 'cvs add -c' is: "add this file to the
working copy and check if the repository will allow me to commit this
new file if I decide to". In this semantic only the latter part has
anything to do with the repository, and it is "commit", not "add",
that's why I suggested 'cvs commit' would be more logical place to check
for such things.

Certain conditions that "will allow me to commit this new file if I decide to" can be checked at the time the user invokes the "cvs add" command. The rationale is that if a failure condition can be detected at add-time then any conditions deriving from those creating the failure condition can be halted, thus avoiding costly recovery action at the time when the first commit actually fails.

For example, suppose a mixed Windows/Unix shop requires all files to have upper-case 8.3 file names. A new programmer splits a header file and creates a new foo.h. He adds the file, then proceeds to modify all of the source files to include the new foo.h. Then he updates all of the dependencies in his makefiles. He builds and tests on Unix. He types "cvs commit", types a very detailed log of his actions, and finally punches the screen. This person might have saved a day's work, his equipment, and his knuckles if only "cvs add" had said "Sorry, this new file violates our naming policy, try renaming it to FOO.H instead."

To get your semantics, it seems you need a new operation with the
semantics "add the file to the working copy and to the repository, but
don't give it to anybody on 'cvs update' yet, until I latter commit the
addition". Do you propose exactly this? How could it be done without
write access to the repository?

The semantics I want are to validate the addition of a new artifact. I frankly don't care if "cvs add" is implemented as you describe in that last paragraph or if it's implemented Greg's way. No matter which method records the new file, the client must still contact the server to run the add-time trigger.

I had hoped that this was clear in the last go-round, but apparently

For me it is not, sorry. Let me give yet another example. Suppose I've
created a new_file today and have checked it's ok using proposed 'cvs
add -c new_file' command. Two days later what I've checked could already
be wrong (policy change, another user added the same file, etc.). So
there are two questions:

1. How do I repeat my check later? By just repeating 'cvs add -c
   new_file'? This would produce warnings "new_file has already been
   added" that is not a good thing for an operation intended to make
   checks, I'm afraid.

2. Should 'cvs -n ci new_file' run the same triggers 'cvs add -c
   new_file' runs? If exactly the same, then why the duplication?

My vision is that the user would run "cvs ci new_file" without the -n option. It would run the add-time triggers (for the first commit) and then the commit-time triggers. The reason for the duplication is partly to catch possible changes in policy between add-time and commit-time, and partly to avoid abuses by those who unplug their computers as part of their procedure to add new files (which includes those who insist that running "cvs add" while disconnected is a reasonable thing to do).

Policy goes above -- it is not hard-coded in the core functionality.

Agreed. But the tool must be sufficiently flexible to allow robust
implementations of policies. Sometimes triggers are the right way (and
wrapper scripts are not), and we've identified one area here where CVS
is not sufficiently flexible.

That's why I insist CVS should have sane set of elementary operations
that could be then combined in different ways. I have no objection
against "compound" CVS commands that do multiple things (preferably
making them atomic), but existing of corresponding elementary commands
is a must, I believe. Designing tools in a different manner results in a
lack of flexibility, or at least my experience suggests it does.

Indeed. To me, the ideal implementation would be a collection of very primitive operations glued together by a scripting language, and have the command line interface invoke scripts. I don't believe that the existing CVS command line offers enough flexibility, in a number of ways. And an implementation like the one I describe here cannot be built without trashing most of the existing code. But that's a different discussion...

On Jan 25, 2005, at 9:29 AM, address@hidden wrote:

Besides, concerning informing the user about problems ASAP, I find
myself using 'cvs add' and 'cvs remove' as *late* as possible (as
close to the commit as possible) due to the oddities in CVS
behavior described below. Consider the following use-case where
the intent of tagging is to mark the repository state just before
committing of a set of changes that includes adding and/or
removing of some files:

$ cd working_copy
$ echo a > a
$ cvs add a
cvs server: scheduling file `a' for addition
cvs server: use 'cvs commit' to add this file permanently
[... time passes ... and now I'm ready to commit...]
$ cvs update
$ cvs tag -F before-my-changes
cvs server: nothing known about a
cvs [server aborted]: correct the above errors first!

Oops! Need to remove file back to be able to tag the repository!

Doesn't error "nothing known about a" look funny by the way? Shouldn't
'cvs update' show "N" meaning "nothing known" instead of "A" as the
status of the file then :)

No, CVS shouldn't say anything about the unknown file. The tag is
being applied to the base revisions of the files in the working
directory. A newly added, but uncommitted, file is simply like any
other changed file in the working directory and the '-F' should
ignore it just as it ignores the changes to files that are already
in the repository.

I.e. that is a bug, pure and simple.

I consider this to be a bug as well.

But consider this: "All I want to do is tag my files before I commit them, and don't concern me with the detail". Okay, which versions do
you want tagged, the ones that appear in your workspace when you did
the update, or the ones that will appear in the repository when you

That's a nonsensical question.  Tags can only be applied to revisions
that are already in the repository. Tags applied with "cvs tag" always
begin with the base revisions that the working directory was created

Remember, I take a user-centric view of the world when I discuss CVS.
It's frequently said to users that "tags apply to the versions in your
workspace" when "cvs tag" is used. But after the user has edited a
file, there are suddenly two possible versions to which a tag might be
applied. You and I know that the version that gets the tag is really
the one that's listed in the Entries file, but the user may expect the
"cvs tag" to create a side-effect in his workspace that causes the
versions created by a later commit to be tagged.

In this case, the user needs to be educated. But on the other hand,
having an atomic commit/tag operation would be useful if it existed...

Well, to tell the truth, all this tagging I do would be not an issue
should CVS support changesets. The tagging in my use-cases is in fact an attempt to somehow mark a changeset to be able to retrieve it later (in a
form of diff between two tags).

I took a different approach. If you're interested, search the archives for "submit/assemble" for discussion of another successful change control system built on CVS. Mine doesn't depend on tags at all.

The tag command should be changed to do what you want and expect,
not to force you into some bogus sequence of commands just to
satisfy the tool.

The "cvs tag" and "cvs rtag" commands can already do exactly what he
wants, and what he expects -- and the ordering of commands is not
"bogus", but rather a clear and obvious progression of steps. Things
have to be done in the proper order. You can't commit changes you
haven't made yet, for example.

As I recall, the user wanted to perform the following steps:

cvs update
cvs rm foo
cvs tag bar
cvs commit

More exactly,

1. rm -f foo
2. cvs rm foo
3. cvs update
4. cvs tag bar1
5. cvs commit
6. cvs tag bar2

Unfortunately, this leaves foo without tag bar1 that results in missing
removal of the file foo when I later 'cvs diff' between bar1 and bar2. I
consider this to be a mis-feature.


1. rm -f foo
3. cvs update
4. cvs tag bar1
2. cvs rm foo
5. cvs commit
6. cvs tag bar2

doesn't work as (3) re-creates 'foo'.

The problem was that "cvs tag" was complaining that it could not tag
the foo file. This is because CVS didn't remember what version it had
after the rm.

No, it does remember. The CVS/Entries file still contains an entry for
foo along with the version. And it doesn't stop the entire tagging in
this case, -- it just refrains to apply the tag bar1 to the foo and
warns about it. I still believe this is a mis-feature.

Interesting. The behavior that I remember is that CVS edits the entry in the Entries file, replacing the version number with a flag to indicate that the file was removed. If that's not in fact the case, I'll declare dam brainage and defer to your more recent experience.

In this case, the user is expecting one of two things: Not tag foo at

That's exactly what CVS does. I believe this is a mis-feature.

or apply the tag to the version of foo that was left in the workspace
by the last update.

That's what it should do, unless -c option is given, I believe. And if
-c option is given, it should probably abort operation, not just warn
about the problem. At least that would be consistent with the current -c
behavior and documentation.

In both cases, the current behavior of CVS (to complain and exit)

It complains and exists in the case of a new file has been 'cvs add'ed,
not in the case when a file has been 'cvs rm'ed. Exiting on 'cvs add'ed
file when no -c option is given is simply a bug, I think.

I think we're all in agreement that the behavior that you describe as bugs really are bugs. What you describe as correct behavior is reasonable to me.

Paul Sander       | "To do two things at once is to do neither"
address@hidden | Publilius Syrus, Roman philosopher, 100 B.C.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]