This is a refinement of my ".trunk" patch.
It includes a test in sanity.sh for a
revision number "2.1" to make sure
that works.
Plus corrected misc. comments and docs
that I'd gotten not quite right.
There are some strange behaviors I found
in my sanity.sh test cases but they don't
seem to be specific to code I've added, I
think that strangeness has been there all
along.
Applies to the current development CVS,
except with Larry Jones' 6-19-2000 changes to
main.c, server.c, and root.c backed out as
I couldn't make those work with client
server CVS. (The "backing-out" is not
included in my patch though)
The patch is available here:
http://www.geocities.com/dotslashstar/branch_patch.html
and enclosed:
-- steve
__________________________________________________
Do You Yahoo!?
Send instant messages with Yahoo! Messenger.
http://im.yahoo.com/
Index: NEWS
===================================================================
RCS file: /home2/cvsroot/ccvs/NEWS,v
retrieving revision 1.79
diff -c -r1.79 NEWS
*** NEWS 2000/05/05 14:48:37 1.79
--- NEWS 2000/06/20 05:10:04
***************
*** 1,5 ****
--- 1,8 ----
Changes since 1.10:
+ * New ".trunk" pseudo-branch-tag added which acts just like a branch
+ tag, but means the trunk.
+
* The "cvs history" command output format has changed -- the date
now includes the year and is given is ISO 8601 format (yyyy-mm-dd).
Index: doc/ChangeLog
===================================================================
RCS file: /home2/cvsroot/ccvs/doc/ChangeLog,v
retrieving revision 1.622
diff -c -r1.622 ChangeLog
*** ChangeLog 2000/06/14 17:41:56 1.622
--- ChangeLog 2000/06/20 05:10:20
***************
*** 1,3 ****
--- 1,7 ----
+ 2000-06-18 Stephen Cameron <[EMAIL PROTECTED]>
+
+ * cvs.texinfo: Document new ".trunk" pseudo branch tag.
+
2000-04-03 Pavel Roskin <[EMAIL PROTECTED]>
* cvs.texinfo (Telling CVS to notify you): Remove backslashes
Index: doc/cvs.texinfo
===================================================================
RCS file: /home2/cvsroot/ccvs/doc/cvs.texinfo,v
retrieving revision 1.489
diff -c -r1.489 cvs.texinfo
*** cvs.texinfo 2000/06/14 17:41:56 1.489
--- cvs.texinfo 2000/06/20 05:11:15
***************
*** 3258,3264 ****
as internal numbers that @sc{cvs} maintains, and tags
provide a better way to distinguish between things like
release 1 versus release 2 of your product
! (@pxref{Tags}). However, if you want to set the
numeric revisions, the @samp{-r} option to @code{cvs
commit} can do that. The @samp{-r} option implies the
@samp{-f} option, in the sense that it causes the
--- 3258,3273 ----
as internal numbers that @sc{cvs} maintains, and tags
provide a better way to distinguish between things like
release 1 versus release 2 of your product
! (@pxref{Tags}).
!
! In fact, let's just go ahead and say right now that you are
! STRONGLY advised against using @samp{cvs commit -r}
! to manually set revision numbers. It is STRONGLY recommended that
! you just allow CVS to assign revision numbers however it likes.
! You should use tags instead of trying to assign some meaning to
! revision numbers.
!
! However, if, with that caution in mind, you still want to set the
numeric revisions, the @samp{-r} option to @code{cvs
commit} can do that. The @samp{-r} option implies the
@samp{-f} option, in the sense that it causes the
***************
*** 3313,3331 ****
@cindex Name, symbolic (tag)
@cindex HEAD, as reserved tag name
@cindex BASE, as reserved tag name
You can use the @code{tag} command to give a symbolic name to a
certain revision of a file. You can use the @samp{-v} flag to the
@code{status} command to see all tags that a file has, and
which revision numbers they represent. Tag names must
start with an uppercase or lowercase letter and can
contain uppercase and lowercase letters, digits,
! @samp{-}, and @samp{_}. The two tag names @code{BASE}
! and @code{HEAD} are reserved for use by @sc{cvs}. It
is expected that future names which are special to
@sc{cvs} will be specially named, for example by
starting with @samp{.}, rather than being named analogously to
@code{BASE} and @code{HEAD}, to avoid conflicts with
! actual tag names.
@c Including a character such as % or = has also been
@c suggested as the naming convention for future
@c special tag names. Starting with . is nice because
--- 3322,3342 ----
@cindex Name, symbolic (tag)
@cindex HEAD, as reserved tag name
@cindex BASE, as reserved tag name
+ @cindex .trunk, as reserved tag name
You can use the @code{tag} command to give a symbolic name to a
certain revision of a file. You can use the @samp{-v} flag to the
@code{status} command to see all tags that a file has, and
which revision numbers they represent. Tag names must
start with an uppercase or lowercase letter and can
contain uppercase and lowercase letters, digits,
! @samp{-}, and @samp{_}. The three tag names @code{BASE},
! @code{HEAD}, and @code{.trunk} are reserved for use by @sc{cvs}. It
is expected that future names which are special to
@sc{cvs} will be specially named, for example by
starting with @samp{.}, rather than being named analogously to
@code{BASE} and @code{HEAD}, to avoid conflicts with
! actual tag names. (The previous sentence is the reason `.trunk'
! begins with a dot, since it predates `.trunk'.
@c Including a character such as % or = has also been
@c suggested as the naming convention for future
@c special tag names. Starting with . is nice because
***************
*** 3630,3636 ****
If you specify the @samp{-r} option to @code{cvs rtag},
then @sc{cvs} tags the files which have been removed,
and thereby avoids this problem. For example, one
! might specify @code{-r HEAD} to tag the head.
On the subject of adding and removing files, the
@code{cvs rtag} command has a @samp{-a} option which
--- 3641,3648 ----
If you specify the @samp{-r} option to @code{cvs rtag},
then @sc{cvs} tags the files which have been removed,
and thereby avoids this problem. For example, one
! might specify @code{-r HEAD} to tag the head, though
! you may prefer the pseudo branch tag @code{-r .trunk}.
On the subject of adding and removing files, the
@code{cvs rtag} command has a @samp{-a} option which
***************
*** 3692,3698 ****
you delete them with @samp{cvs update -A}. The
@samp{-A} option retrieves the version of the file from
the head of the trunk, and forgets any sticky tags,
! dates, or options.
@cindex Sticky date
The most common use of sticky tags is to identify which
--- 3704,3714 ----
you delete them with @samp{cvs update -A}. The
@samp{-A} option retrieves the version of the file from
the head of the trunk, and forgets any sticky tags,
! dates, or options. (Note, `-A' clears ALL sticky tags,
! including -kb, etc., which you may not want, if for
! example you simply want to switch your working directory
! to the trunk. For this purpose, you may want to use
! the special `.trunk' branch tag name for the trunk.)
@cindex Sticky date
The most common use of sticky tags is to identify which
***************
*** 8073,8078 ****
--- 8089,8095 ----
@item -r @var{tag}
@cindex HEAD, special tag
@cindex BASE, special tag
+ @cindex .trunk, special tag
Use the revision specified by the @var{tag} argument instead of the
default @dfn{head} revision. As well as arbitrary tags defined
with the @code{tag} or @code{rtag} command, two special tags are
***************
*** 8102,8107 ****
--- 8119,8129 ----
@c same for "diff" as for everyone else), test cases
@c written (similar to the ones in "head"), new tests
@c cases written for things like default branches, &c.
+ @c
+ @c Hmm. I've made ".trunk", which works as ".thead"
+ @c above, but additionally works like a branch tag
+ @c for the trunk, that is, you can commit changes to it.
+ @c
The tag specification is sticky when you use this
@c option
***************
*** 8208,8213 ****
--- 8230,8238 ----
@c the optional argument). Note that -bHEAD does not
@c work, as of 17 Sep 1997, but probably will once "cvs
@c admin" is internal to CVS.
+ @c
+ @c Hmm, I wonder if ".trunk" works with "cvs admin"?
+ @c
@cindex Comment leader
@item -c@var{string}
***************
*** 8819,8825 ****
either a branch, or a revision on the main trunk that
is higher than any existing revision number
(@pxref{Assigning revisions}). You
! cannot commit to a specific revision on a branch.
@c FIXME: Need xref for branch case.
@end table
--- 8844,8863 ----
either a branch, or a revision on the main trunk that
is higher than any existing revision number
(@pxref{Assigning revisions}). You
! cannot commit to a specific revision on a branch. Note,
! `.trunk' is valid as a branch tag for the `-r' option, and
! will commit the file as the newest revision on the trunk.
! @c
! @c However, if the file in the working directory has a
! @c sticky tag other than .trunk, the sticky tag will not
! @c be changed, and even if the file differs from the repository
! @c revision, it will be marked 'up-to-date',
! @c and a subsequent 'cvs commit' will not commit those changes.
! @c no doubt this is a bug, though I'm not sure what the right
! @c fix, is, either change the sticky tag, or leave the file's
! @c status as 'locally-modified'.
! @c
!
@c FIXME: Need xref for branch case.
@end table
***************
*** 9010,9015 ****
--- 9048,9069 ----
One or both @samp{-r} options can be replaced by a
@samp{-D @var{date}} option, described above.
+
+ CAUTION: the special tag `HEAD' is interpreted by
+ the `cvs diff' command in a different way than it
+ is interpreted by any other cvs command. `cvs diff'
+ takes `-r HEAD' to mean the following, as nearly as
+ I can tell:
+
+ For `cvs diff', `HEAD' means the most recent revision
+ on the `current branch' (taking into account whatever
+ sticky tags are active in your working directory) unless
+ a particular file has not had a revision committed to the
+ branch, in which case the head revision of the trunk is
+ taken. This is clearly wrong. You should use either
+ `.trunk' or the branch tag name rather than `HEAD'.
+ (The `.trunk' tag acts as a branch tag name for the trunk.)
+
@end table
@c Conceptually, this is a disaster. There are 3
Index: src/ChangeLog
===================================================================
RCS file: /home2/cvsroot/ccvs/src/ChangeLog,v
retrieving revision 1.1917
diff -c -r1.1917 ChangeLog
*** ChangeLog 2000/06/19 18:55:57 1.1917
--- ChangeLog 2000/06/20 05:11:32
***************
*** 1,3 ****
--- 1,26 ----
+
+ 2000-06-19 Stephen Cameron <[EMAIL PROTECTED]>
+
+ * checkout.c (checkout): Add ".trunk" pseudo branch tag feature
+ * commit.c (classify_file_internal): Ditto
+ (check_fileproc): Ditto
+ (remove_file): Ditto
+ * cvs.h: add definition of TAG_TRUNK (".trunk") plus comments
+ * diff.c: (diff_fileproc): Handle ".trunk" pseudo branch tag.
+ (diff_file_nodiff): Ditto
+ * entriex.c (WriteTag): modified to magically treat ".trunk" as
+ a branch tag.
+ * log.c (cvslog): Modified to handle ".trunk" pseudo branch tag.
+ * rcs.c (RCS_tag2rev):
+ (RCS_gettag): Modified to reject ".trunk" reserved tag
+ (RCS_settag): Ditto
+ (RCS_trunk): New function
+ * rcs.h (RCS_trunk): New function prototype
+ * sanity.sh: New suite of tests for ".trunk", called
+ "btrunktag"
+ * status.c (status_fileproc): handle ".trunk" pseudo branch tag
+ * tag.c (tag_check_valid): handle ".trunk" pseudo branch tag
+
2000-06-19 Larry Jones <[EMAIL PROTECTED]>
* main.c (main): Plug memory leaks.
Index: src/checkout.c
===================================================================
RCS file: /home2/cvsroot/ccvs/src/checkout.c,v
retrieving revision 1.89
diff -c -r1.89 checkout.c
*** checkout.c 2000/06/15 15:33:30 1.89
--- checkout.c 2000/06/20 05:11:36
***************
*** 197,203 ****
break;
case 'r':
tag = optarg;
! checkout_prune_dirs = 1;
break;
case 'D':
date = Make_Date (optarg);
--- 197,204 ----
break;
case 'r':
tag = optarg;
! if (strcmp(optarg, TAG_TRUNK) != 0)
! checkout_prune_dirs = 1;
break;
case 'D':
date = Make_Date (optarg);
Index: src/commit.c
===================================================================
RCS file: /home2/cvsroot/ccvs/src/commit.c,v
retrieving revision 1.161
diff -c -r1.161 commit.c
*** commit.c 2000/06/12 21:47:32 1.161
--- commit.c 2000/06/20 05:11:42
***************
*** 687,696 ****
noexec = quiet = really_quiet = 1;
/* handle specified numeric revision specially */
! if (saved_tag && isdigit ((unsigned char) *saved_tag))
{
/* If the tag is for the trunk, make sure we're at the head */
! if (numdots (saved_tag) < 2)
{
status = Classify_File (finfo, (char *) NULL, (char *) NULL,
(char *) NULL, 1, aflag, vers, 0);
--- 687,697 ----
noexec = quiet = really_quiet = 1;
/* handle specified numeric revision specially */
! if (saved_tag && (isdigit ((unsigned char) *saved_tag) ||
! strcmp(saved_tag, TAG_TRUNK) == 0))
{
/* If the tag is for the trunk, make sure we're at the head */
! if (numdots (saved_tag) < 2 || strcmp(saved_tag, TAG_TRUNK) == 0 )
{
status = Classify_File (finfo, (char *) NULL, (char *) NULL,
(char *) NULL, 1, aflag, vers, 0);
***************
*** 746,751 ****
--- 747,753 ----
else
status = Classify_File (finfo, saved_tag, (char *) NULL, (char *) NULL,
1, 0, vers, 0);
+
noexec = save_noexec;
quiet = save_quiet;
really_quiet = save_really_quiet;
***************
*** 819,828 ****
* some quick sanity checks; if no numeric -r option specified:
* - can't have a sticky date
* - can't have a sticky tag that is not a branch
* Also,
* - if status is T_REMOVED, can't have a numeric tag
* - if status is T_ADDED, rcs file must not exist unless on
! * a branch
* - if status is T_ADDED, can't have a non-trunk numeric rev
* - if status is T_MODIFIED and a Conflict marker exists, don't
* allow the commit if timestamp is identical or if we find
--- 821,831 ----
* some quick sanity checks; if no numeric -r option specified:
* - can't have a sticky date
* - can't have a sticky tag that is not a branch
+ * (except if it's TAG_TRUNK)
* Also,
* - if status is T_REMOVED, can't have a numeric tag
* - if status is T_ADDED, rcs file must not exist unless on
! * a branch (and count TAG_TRUNK as a branch)
* - if status is T_ADDED, can't have a non-trunk numeric rev
* - if status is T_MODIFIED and a Conflict marker exists, don't
* allow the commit if timestamp is identical or if we find
***************
*** 839,844 ****
--- 842,848 ----
return (1);
}
if (status == T_MODIFIED && vers->tag &&
+ strcmp(vers->tag, TAG_TRUNK)!=0 &&
!RCS_isbranch (finfo->rcs, vers->tag))
{
error (0, 0,
***************
*** 917,923 ****
}
if (status == T_ADDED)
{
! if (vers->tag == NULL)
{
char *rcs;
--- 921,927 ----
}
if (status == T_ADDED)
{
! if (vers->tag == NULL || strcmp(vers->tag, TAG_TRUNK) == 0)
{
char *rcs;
***************
*** 988,994 ****
li = ((struct logfile_info *)
xmalloc (sizeof (struct logfile_info)));
li->type = status;
! li->tag = xstrdup (vers->tag);
li->rev_old = xstrdup (vers->vn_rcs);
li->rev_new = NULL;
p->data = (char *) li;
--- 992,1003 ----
li = ((struct logfile_info *)
xmalloc (sizeof (struct logfile_info)));
li->type = status;
!
! if (vers->tag != NULL && strcmp(vers->tag, TAG_TRUNK) == 0)
! li->tag = NULL;
! else
! li->tag = xstrdup (vers->tag);
!
li->rev_old = xstrdup (vers->vn_rcs);
li->rev_new = NULL;
p->data = (char *) li;
***************
*** 1000,1013 ****
p->delproc = ci_delproc;
ci = (struct commit_info *) xmalloc (sizeof (struct commit_info));
ci->status = status;
! if (vers->tag)
if (isdigit ((unsigned char) *vers->tag))
ci->rev = xstrdup (vers->tag);
else
ci->rev = RCS_whatbranch (finfo->rcs, vers->tag);
else
ci->rev = (char *) NULL;
! ci->tag = xstrdup (vers->tag);
ci->options = xstrdup(vers->options);
p->data = (char *) ci;
(void) addnode (cilist, p);
--- 1009,1028 ----
p->delproc = ci_delproc;
ci = (struct commit_info *) xmalloc (sizeof (struct commit_info));
ci->status = status;
!
! if (vers->tag && strcmp(vers->tag, TAG_TRUNK)!=0)
if (isdigit ((unsigned char) *vers->tag))
ci->rev = xstrdup (vers->tag);
else
ci->rev = RCS_whatbranch (finfo->rcs, vers->tag);
else
ci->rev = (char *) NULL;
!
! if (vers->tag && strcmp(vers->tag, TAG_TRUNK) == 0)
! ci->tag = (char *) NULL;
! else
! ci->tag = xstrdup (vers->tag);
!
ci->options = xstrdup(vers->options);
p->data = (char *) ci;
(void) addnode (cilist, p);
***************
*** 1639,1645 ****
error (1, 0, "internal error: no parsed RCS file");
branch = 0;
! if (tag && !(branch = RCS_nodeisbranch (finfo->rcs, tag)))
{
/* a symbolic tag is specified; just remove the tag from the file */
if ((retcode = RCS_deltag (finfo->rcs, tag)) != 0)
--- 1654,1661 ----
error (1, 0, "internal error: no parsed RCS file");
branch = 0;
! if (tag && strcmp(tag, TAG_TRUNK)!=0 &&
! !(branch = RCS_nodeisbranch (finfo->rcs, tag)))
{
/* a symbolic tag is specified; just remove the tag from the file */
if ((retcode = RCS_deltag (finfo->rcs, tag)) != 0)
Index: src/cvs.h
===================================================================
RCS file: /home2/cvsroot/ccvs/src/cvs.h,v
retrieving revision 1.202
diff -c -r1.202 cvs.h
*** cvs.h 2000/06/14 19:38:15 1.202
--- cvs.h 2000/06/20 05:11:46
***************
*** 245,256 ****
#endif /* USE_VMS_FILENAMES */
/*
! * Special tags. -rHEAD refers to the head of an RCS file, regardless of any
! * sticky tags. -rBASE refers to the current revision the user has checked
! * out This mimics the behaviour of RCS.
*/
#define TAG_HEAD "HEAD"
#define TAG_BASE "BASE"
/* Environment variable used by CVS */
#define CVSREAD_ENV "CVSREAD" /* make files read-only */
--- 245,278 ----
#endif /* USE_VMS_FILENAMES */
/*
! * Special tags.
! * -rHEAD refers to the tip revision on the trunk, _except_ for
! * "cvs diff". "cvs diff" interprets -rHEAD to mean the tip
! * revision of the current branch, however, that behavior is
! * broken, because if the file has not been branched, that is,
! * the revision on the branch is the same one that's on the trunk
! * then the tip revision of the trunk is reported. Also, it's
! * not clear (to me) what happens in the instance of a sticky
! * non-branch tag what -rHEAD is supposed to mean. So, -rHEAD
! * is probably a lost cause, unless you redefine what it means.
! *
! * -rBASE refers to the current revision the user has checked
! * out This mimics the behaviour of RCS.
! *
! * -r.trunk refers to the head revision on the trunk.
! * (necessary for this to exist so that the trunk is not anonymous.)
! * "cvs commit" and "cvs status" have been hacked to believe ".trunk"
! * is a "branch tag", even though, really, it's not.
! * This is more like how I think -rHEAD probably should have
! * always worked. I chose ".trunk" as the name for various
! * reasons, (lowercase is easier to type, nobody currently has
! * any real tag names that begin with dots.)
! *
*/
+
#define TAG_HEAD "HEAD"
#define TAG_BASE "BASE"
+ #define TAG_TRUNK ".trunk"
/* Environment variable used by CVS */
#define CVSREAD_ENV "CVSREAD" /* make files read-only */
Index: src/diff.c
===================================================================
RCS file: /home2/cvsroot/ccvs/src/diff.c,v
retrieving revision 1.83
diff -c -r1.83 diff.c
*** diff.c 1999/04/15 00:12:26 1.83
--- diff.c 2000/06/20 05:11:49
***************
*** 461,466 ****
--- 461,477 ----
if (head != NULL)
free (head);
}
+ else /* special handling for TAG_TRUNK */
+ if (diff_rev1 && strcmp (diff_rev1, TAG_TRUNK) == 0)
+ {
+ char *trunk =
+ (vers->vn_rcs == NULL
+ ? NULL
+ : RCS_trunk (vers->srcfile));
+ exists = trunk != NULL;
+ if (trunk != NULL)
+ free (trunk);
+ }
else
{
Vers_TS *xvers;
***************
*** 843,855 ****
use_rev1 = ((vers->vn_rcs == NULL || vers->srcfile == NULL)
? NULL
: RCS_branch_head (vers->srcfile, vers->vn_rcs));
! else
! {
! xvers = Version_TS (finfo, NULL, diff_rev1, diff_date1, 1, 0);
! if (xvers->vn_rcs != NULL)
! use_rev1 = xstrdup (xvers->vn_rcs);
! freevers_ts (&xvers);
! }
}
if (diff_rev2 || diff_date2)
{
--- 854,874 ----
use_rev1 = ((vers->vn_rcs == NULL || vers->srcfile == NULL)
? NULL
: RCS_branch_head (vers->srcfile, vers->vn_rcs));
! else
! {
! /* special handling for TAG_TRUNK */
! if (diff_rev1 && strcmp (diff_rev1, TAG_TRUNK) == 0)
! use_rev1 = ((vers->vn_rcs == NULL || vers->srcfile == NULL)
! ? NULL
! : RCS_trunk (vers->srcfile));
! else
! {
! xvers = Version_TS (finfo, NULL, diff_rev1, diff_date1, 1, 0);
! if (xvers->vn_rcs != NULL)
! use_rev1 = xstrdup (xvers->vn_rcs);
! freevers_ts (&xvers);
! }
! }
}
if (diff_rev2 || diff_date2)
{
***************
*** 859,869 ****
? NULL
: RCS_branch_head (vers->srcfile, vers->vn_rcs));
else
! {
! xvers = Version_TS (finfo, NULL, diff_rev2, diff_date2, 1, 0);
! if (xvers->vn_rcs != NULL)
! use_rev2 = xstrdup (xvers->vn_rcs);
! freevers_ts (&xvers);
}
if (use_rev1 == NULL)
--- 878,896 ----
? NULL
: RCS_branch_head (vers->srcfile, vers->vn_rcs));
else
! {
! /* special handling for TAG_TRUNK */
! if (diff_rev2 && strcmp (diff_rev2, TAG_TRUNK) == 0)
! use_rev2 = ((vers->vn_rcs == NULL || vers->srcfile == NULL)
! ? NULL
! : RCS_trunk (vers->srcfile));
! else
! {
! xvers = Version_TS (finfo, NULL, diff_rev2, diff_date2, 1, 0);
! if (xvers->vn_rcs != NULL)
! use_rev2 = xstrdup (xvers->vn_rcs);
! freevers_ts (&xvers);
! }
}
if (use_rev1 == NULL)
Index: src/entries.c
===================================================================
RCS file: /home2/cvsroot/ccvs/src/entries.c,v
retrieving revision 1.45
diff -c -r1.45 entries.c
*** entries.c 1999/09/29 19:24:15 1.45
--- entries.c 2000/06/20 05:11:56
***************
*** 662,667 ****
--- 662,674 ----
fout = open_file (tmp, "w+");
if (tag)
{
+ /* Let's imagine that the magic TAG_TRUNK
+ tag is a branch tag, even though it's really not.
+ this is so that "cvs add" will allow us to proceed */
+
+ if (strcmp(tag, TAG_TRUNK)==0)
+ nonbranch=0;
+
if (nonbranch)
{
if (fprintf (fout, "N%s\n", tag) < 0)
Index: src/log.c
===================================================================
RCS file: /home2/cvsroot/ccvs/src/log.c,v
retrieving revision 1.61
diff -c -r1.61 log.c
*** log.c 2000/06/13 21:30:44 1.61
--- log.c 2000/06/20 05:11:56
***************
*** 232,237 ****
--- 232,239 ----
break;
case 'r':
*prl = log_parse_revlist (optarg);
+ if (optarg != NULL && strcmp(optarg, TAG_TRUNK)==0)
+ log_data.default_branch = 1;
prl = &(*prl)->next;
break;
case 's':
Index: src/rcs.c
===================================================================
RCS file: /home2/cvsroot/ccvs/src/rcs.c,v
retrieving revision 1.235
diff -c -r1.235 rcs.c
*** rcs.c 2000/06/16 18:34:52 1.235
--- rcs.c 2000/06/20 05:12:23
***************
*** 2198,2203 ****
--- 2198,2207 ----
if (tag && STREQ (tag, TAG_HEAD))
return (RCS_head (rcs));
+ /* If tag is "TRUNK", special case to get the trunk RCS revision */
+ if (tag && STREQ (tag, TAG_TRUNK))
+ return (RCS_trunk (rcs));
+
/* If valid tag let translate_symtag say yea or nay. */
rev = translate_symtag (rcs, tag);
***************
*** 2248,2253 ****
--- 2252,2261 ----
#endif
return (RCS_head (rcs));
+ /* If tag is "TRUNK", special case to get trunk RCS revision */
+ if (tag && (STREQ (tag, TAG_TRUNK) ))
+ return (RCS_trunk (rcs));
+
if (!isdigit ((unsigned char) tag[0]))
{
char *version;
***************
*** 2793,2798 ****
--- 2801,2822 ----
}
/*
+ * Get the "trunk" of the RCS file.
+ * or, the real head.
+ * Returns NULL or a newly malloc'd string.
+ */
+
+ char *
+ RCS_trunk (rcs)
+ RCSNode *rcs;
+ {
+ /* make sure we have something to look at... */
+ assert (rcs != NULL);
+
+ return (xstrdup (rcs->head));
+ }
+
+ /*
* Get the head of the RCS file. If branch is set, this is the head of the
* branch, otherwise the real head.
* Returns NULL or a newly malloc'd string.
***************
*** 5561,5568 ****
/* FIXME: This check should be moved to RCS_check_tag. There is no
reason for it to be here. */
! if (STREQ (tag, TAG_BASE)
! || STREQ (tag, TAG_HEAD))
{
/* Print the name of the tag might be considered redundant
with the caller, which also prints it. Perhaps this helps
--- 5585,5593 ----
/* FIXME: This check should be moved to RCS_check_tag. There is no
reason for it to be here. */
! if ( STREQ (tag, TAG_BASE)
! || STREQ (tag, TAG_HEAD)
! || STREQ (tag, TAG_TRUNK))
{
/* Print the name of the tag might be considered redundant
with the caller, which also prints it. Perhaps this helps
Index: src/rcs.h
===================================================================
RCS file: /home2/cvsroot/ccvs/src/rcs.h,v
retrieving revision 1.55
diff -c -r1.55 rcs.h
*** rcs.h 2000/06/12 21:47:32 1.55
--- rcs.h 2000/06/20 05:12:24
***************
*** 202,207 ****
--- 202,208 ----
int RCS_nodeisbranch PROTO((RCSNode *rcs, const char *tag));
char *RCS_whatbranch PROTO((RCSNode *rcs, const char *tag));
char *RCS_head PROTO((RCSNode * rcs));
+ char *RCS_trunk PROTO((RCSNode * rcs));
int RCS_datecmp PROTO((char *date1, char *date2));
time_t RCS_getrevtime PROTO((RCSNode * rcs, char *rev, char *date, int fudge));
List *RCS_symbols PROTO((RCSNode *rcs));
Index: src/sanity.sh
===================================================================
RCS file: /home2/cvsroot/ccvs/src/sanity.sh,v
retrieving revision 1.608
diff -c -r1.608 sanity.sh
*** sanity.sh 2000/06/14 20:40:53 1.608
--- sanity.sh 2000/06/20 05:13:16
***************
*** 670,675 ****
--- 670,678 ----
# Multiple root directories and low-level protocol tests.
tests="${tests} multiroot multiroot2 multiroot3 multiroot4"
tests="${tests} rmroot reposmv pserver server server2 client"
+ # ".trunck" pseudo branch tag
+ tests="${tests} btrunktag"
+
else
tests="$*"
fi
***************
*** 796,802 ****
"${PROG} [a-z]*: nothing known about ssfile
${PROG} "'\[[a-z]* aborted\]: correct the above errors first!'
cd ../..
! dotest basica-5 "${testcvs} -q ci -m add-it" \
"RCS file: ${TESTDIR}/cvsroot/first-dir/sdir/ssdir/ssfile,v
done
Checking in sdir/ssdir/ssfile;
--- 799,805 ----
"${PROG} [a-z]*: nothing known about ssfile
${PROG} "'\[[a-z]* aborted\]: correct the above errors first!'
cd ../..
! dotest basica-5 "${testcvs} -q ci -m add-it" \
"RCS file: ${TESTDIR}/cvsroot/first-dir/sdir/ssdir/ssfile,v
done
Checking in sdir/ssdir/ssfile;
***************
*** 20538,20543 ****
--- 20541,20910 ----
rm ${TESTDIR}/serveme
CVS_SERVER=${testcvs}; export CVS_SERVER
fi # skip the whole thing for local
+ ;;
+ btrunktag)
+
+ # test operations with "-r .trunk"
+
+ mkdir 1; cd 1
+ dotest trunkbtag1 "${testcvs} -q co -l -r .trunk ." ''
+ mkdir my-dir
+ dotest btrunktag2 "${testcvs} add my-dir" \
+ "Directory ${TESTDIR}/cvsroot/my-dir added to the repository
+ --> Using per-directory sticky tag "'`.'"trunk'"
+ cd ..
+ rm -r 1
+
+ dotest btrunktag3 "${testcvs} co -r .trunk my-dir" \
+ "${PROG} [a-z]*: Updating my-dir"
+
+ dotest btrunktag3 "${testcvs} co my-dir" \
+ "${PROG} [a-z]*: Updating my-dir"
+ cd my-dir
+
+ # add a file
+
+ echo xyz > xyz
+ dotest btrunktag4 "${testcvs} add xyz" \
+ "${PROG} [a-z]*: "'scheduling file `xyz'\'' for addition on branch `.trunk'\'"
+ ${PROG}"' [a-z]*: use '\''cvs commit'\'' to add this file permanently'
+
+ # commit the file
+
+ dotest btrunktag5 "${testcvs} commit -m addxyz xyz" \
+ "RCS file: ${TESTDIR}/cvsroot/my-dir/xyz,v
+ done
+ Checking in xyz;
+ ${TESTDIR}/cvsroot/my-dir/xyz,v <-- xyz
+ initial revision: 1.1
+ done"
+ # status the file
+ # Running "cvs status" and matching output is too
+ # error-prone, too likely to falsely fail. Instead, we'll
+ # just grep the Entries lines: (I found this out the hard way.)
+
+ dotest btrunktag6 "grep xyz ./CVS/Entries" \
+ "/xyz/1.1/[A-Za-z0-9 :]*//T.trunk"
+
+ # edit the file and commit again
+ echo xyz >> xyz
+ dotest btrunktag7 "${testcvs} commit -m editxyz xyz" \
+ "Checking in xyz;
+ ${TESTDIR}/cvsroot/my-dir/xyz,v <-- xyz
+ new revision: 1.2; previous revision: 1.1
+ done"
+
+ # create a branch, commit some changes to the branch,
+ # commit some more changes to the trunk, check out a
+ # specific revision that is neither the head of the branch
+ # nor the trunk, and do a cvs rdiff between the head of
+ # the branch and the head of the trunk.A
+ # (that is, test some unique functionality provided by ".trunk")
+ # (well, ok, -r1 would work in this case.)
+
+ dotest btrunktag8 "${testcvs} tag stickytag" \
+ "${PROG} [a-z]*: Tagging .
+ T xyz"
+ dotest btrunktag9 "${testcvs} tag -r stickytag -b mybranch" \
+ "${PROG} [a-z]*: Tagging .
+ T xyz"
+ dotest btrunktag9a "${testcvs} -q update -r mybranch" ""
+ echo mybranch >> xyz
+ dotest btrunktag10 "${testcvs} commit -m branchedit" \
+ "${PROG} [a-z]*: Examining .
+ Checking in xyz;
+ ${TESTDIR}/cvsroot/my-dir/xyz,v <-- xyz
+ new revision: 1.2.2.1; previous revision: 1.2
+ done"
+ dotest btrunktag11 "${testcvs} update -r .trunk" \
+ "${PROG} [a-z]*: Updating .
+ [UP] xyz"
+ echo trunkedit >> xyz
+ dotest btrunktag12 "${testcvs} commit -m trunkedit" \
+ "${PROG} [a-z]*: Examining .
+ Checking in xyz;
+ ${TESTDIR}/cvsroot/my-dir/xyz,v <-- xyz
+ new revision: 1.3; previous revision: 1.2
+ done"
+ dotest btrunktag13 "${testcvs} update -r stickytag" \
+ "${PROG} [a-z]*: Updating .
+ [UP] xyz"
+ # try cvs rdiff
+
+ dotest btrunktag14a \
+ "${testcvs} rdiff -s -r mybranch -r .trunk my-dir" \
+ "${PROG} [a-z]*: Diffing my-dir
+ File my-dir/xyz changed from revision 1\.2\.2\.1 to 1\.3"
+
+ # try cvs diff
+
+ dotest_fail btrunktag14b "${testcvs} diff -u -r mybranch -r .trunk" \
+ "${PROG} [a-z]*: Diffing .
+ Index: xyz
+ ===================================================================
+ RCS file: ${TESTDIR}/cvsroot/my-dir/xyz,v
+ retrieving revision 1\.2\.2\.1
+ retrieving revision 1\.3
+ diff -u -r1\.2\.2\.1 -r1\.3
+ --- xyz [0-9/]* [0-9:]* 1\.2\.2\.1
+ ${PLUS}${PLUS}${PLUS} xyz [0-9/]* [0-9:]* 1\.3
+ @@ -1,3 ${PLUS}1,3 @@
+ xyz
+ xyz
+ -mybranch
+ ${PLUS}trunkedit"
+
+ # make sure cvs diff works with just one -r
+
+ dotest_fail btrunktag14a "${testcvs} diff -u -r .trunk" \
+ "${PROG} [a-z]*: Diffing \.
+ Index: xyz
+ ===================================================================
+ RCS file: ${TESTDIR}/cvsroot/my-dir/xyz,v
+ retrieving revision 1\.3
+ retrieving revision 1\.2
+ diff -u -r1\.3 -r1\.2
+ --- xyz [0-9/]* [0-9:]* 1\.3
+ +++ xyz [0-9/]* [0-9:]* 1\.2
+ @@ -1,3 ${PLUS}1,2 @@
+ xyz
+ xyz
+ -trunkedit"
+
+ # make sure cvs log works
+
+ dotest btrunktag15 "${testcvs} log -r.trunk" \
+ "${PROG} [a-z]*: Logging .
+
+ RCS file: ${TESTDIR}/cvsroot/my-dir/xyz,v
+ Working file: xyz
+ head: 1\.3
+ branch:
+ locks: strict
+ access list:
+ symbolic names:
+ mybranch: 1\.2\.0\.2
+ stickytag: 1\.2
+ keyword substitution: kv
+ total revisions: 4; selected revisions: 3
+ description:
+ ----------------------------
+ revision 1\.3
+ date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
+ trunkedit
+ ----------------------------
+ revision 1\.2
+ date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
+ branches: 1\.2\.2;
+ editxyz
+ ----------------------------
+ revision 1\.1
+ date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+ addxyz
+ ============================================================================="
+
+ # try cvs update with -j options involving .trunk
+
+ dotest btrunktag16 "${testcvs} update -j mybranch -j .trunk" \
+ "${PROG} [a-z]*: Updating \.
+ RCS file: ${TESTDIR}/cvsroot/my-dir/xyz,v
+ retrieving revision 1\.2\.2\.1
+ retrieving revision 1\.3
+ Merging differences between 1\.2\.2\.1 and 1\.3 into xyz
+ rcsmerge: warning: conflicts during merge"
+
+ # undo the conflicted merge,
+
+ rm xyz
+
+ # note, discrepancy here between client-server CVS
+ # and local CVS, "xyz was lost" message printed only
+ # by local-CVS but not by client-server CVS.
+ # This is not a ".trunk" related problem though.
+ #
+
+ if [ "$remote" = "yes" ]
+ then
+ dotest btrunktag17 "${testcvs} -q update" \
+ "[UP] xyz"
+ else
+ dotest btrunktag17 "${testcvs} -q update" \
+ "${PROG} [a-z]*: warning: xyz was lost
+ [UP] xyz"
+ fi
+
+ # try cvs annotate
+ dotest btrunktag18 "${testcvs} annotate -r .trunk xyz" \
+ "Annotations for xyz
+ \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+ 1\.1 (${username} [0-9]*-[A-Za-z]*-[0-9]*): xyz
+ 1\.2 (${username} [0-9]*-[A-Za-z]*-[0-9]*): xyz
+ 1\.3 (${username} [0-9]*-[A-Za-z]*-[0-9]*): trunkedit"
+
+ # try cvs update -A
+
+ dotest btrunktag19 "${testcvs} update -A" \
+ "${PROG} [a-z]*: Updating \.
+ [UP] xyz"
+
+ # status the file (just grep the Entries lines)
+
+ dotest btrunktag20 "grep xyz ./CVS/Entries" \
+ "/xyz/1\.3/[A-Za-z ]*[0-9]* [0-9:]* [0-9]*//"
+
+ # try switching working directory back: cvs update -r .trunk
+ dotest btrunktag21 "${testcvs} update -r .trunk" \
+ "${PROG} [a-z]*: Updating \."
+
+ # status the file (just grep the Entries lines)
+
+ dotest btrunktag22 "grep xyz ./CVS/Entries" \
+ "/xyz/1\.3/[A-Za-z ]*[0-9]* [0-9:]* [0-9]*//T.trunk"
+
+ # try cvs remove
+ rm xyz
+ dotest btrunktag23 "${testcvs} remove xyz" \
+ "${PROG} [a-z]*: scheduling "\`"xyz"\'" for removal
+ ${PROG} [a-z]*: use "\'"cvs commit"\'" to remove this file permanently"
+
+ # commit the removal
+ dotest btrunktag24 "${testcvs} commit -m removexyz" \
+ "${PROG} [a-z]*: Examining \.
+ Removing xyz;
+ ${TESTDIR}/cvsroot/my-dir/xyz,v <-- xyz
+ new revision: delete; previous revision: 1\.3
+ done"
+
+ # update working directory to the branch
+ dotest btrunktag25 "${testcvs} update -r mybranch" \
+ "${PROG} [a-z]*: Updating \.
+ [UP] xyz"
+
+ # merge in the trunk just to see if the file disappears.
+
+ dotest btrunktag26 "${testcvs} update -j stickytag -j .trunk" \
+ "${PROG} [a-z]*: Updating \.
+ ${PROG} [a-z]*: scheduling xyz for removal"
+
+ # reverse the merge, file would come back
+ # except we just "cvs removed" it with the prior merge
+ # so that's a conflict, (is the file removed, or isn't it?)
+ # At least I guess that's the logic. The file remains
+ # in the removed state and a commit will remove it.
+ # this behavior is identical if two branches are used
+ # instead of one branch and ".trunk", therefore ".trunk"
+ # is working perfectly.
+
+ dotest btrunktag27 "${testcvs} update -j .trunk -j stickytag" \
+ "${PROG} [a-z]*: Updating \.
+ R xyz
+ ${PROG} [a-z]*: file xyz exists, but has been added in revision stickytag"
+
+ # commit, just to see what happens
+
+ dotest btrunktag28 "${testcvs} commit -m removesticky" \
+ "${PROG} [a-z]*: Examining \.
+ Removing xyz;
+ ${TESTDIR}/cvsroot/my-dir/Attic/xyz,v <-- xyz
+ new revision: delete; previous revision: 1\.2\.2\.1
+ done"
+
+ # try the reverse merge again, to see that the file comes back
+
+ dotest btrunktag29 "${testcvs} update -j .trunk -j stickytag" \
+ "${PROG} [a-z]*: Updating \.
+ [UP] xyz"
+
+ # try to commit it directly to the trunk instead of to branch
+ dotest btrunktag30 "${testcvs} commit -r .trunk -m totrunk xyz" \
+ "Checking in xyz;
+ ${TESTDIR}/cvsroot/my-dir/xyz,v <-- xyz
+ new revision: 1\.5; previous revision: 1\.4
+ done"
+
+ # at this point, the file still has the sticky branch tag and
+ # it's status is "up-to-date..." not sure if that's right...
+ # It might be a bug. My gut feeling is it should be
+ # "newly added?"? I strongly suspect exactly the same behavior
+ # would occur with two branches instead of ".trunk" and a
+ # branch, but I haven't tried that case.
+
+ # let's see what happens with another commit.
+
+ dotest btrunktag31 "${testcvs} commit -m tobranch" \
+ "${PROG} [a-z]*: Examining ."
+
+ # Hmm, the file didn't get added... That doesn't seem
+ # consistent. I think that's a bug. Had I done
+ # this commit before I'd done the "commit -r .trunk",
+ # this file would have gone onto the branch.
+ # The "commit -r different-branch" probably should either leave
+ # the file's status alone, or else change the sticky tag to
+ # the new branch, I think.
+ #
+
+ # try to remove the ".trunk" tag. The message could be
+ # better, but it's not wrong in any way that's harmful.
+
+ dotest_fail btrunktag32 "${testcvs} tag -d .trunk xyz" \
+ "${PROG} .*: tag "\`"\.trunk"\'" must start with a letter"
+
+ # note, this, above, is *not* what happens if you try to remove
+ # HEAD. In that case, cvs actually tries to
+ # remove a tag called "HEAD", but can't find it, naturally.
+ # Perhaps that's a bug, that it doesn't catch that you're
+ # trying to remove the special HEAD tag. BASE is almost
+ # certainly in the same boat.
+ #
+ # I'm going to go ahead and leave the following test in here
+ # to remind someone to look into this later, though
+ # it probably belongs someplace else.
+
+ dotest_fail btrunktag33 "${testcvs} tag -d HEAD xyz" \
+ "${PROG} [a-z]*: failed to remove tag HEAD from ${TESTDIR}/cvsroot/my-dir/xyz,v"
+
+ # test the case of ".trunk" with revision
+ # numbers such as 2.1
+
+ # update to the trunk, odd behavior on the client/server front
+
+ if [ "$remote" != "yes" ]
+ then
+ dotest btrunktag34 "${testcvs} update -r .trunk" \
+ "${PROG} [a-z]*: Updating \.
+ [UP] xyz"
+ else
+ dotest btrunktag34 "${testcvs} update -r .trunk" \
+ "${PROG} [a-z]*: Updating \.
+ [UP] xyz
+ ${PROG} [a-z]*: invalid change text in \./xyz
+ ${PROG} [a-z]*: refetching unpatchable files
+ U xyz"
+ # Now, what the heck is *that* about?
+ fi
+
+ echo "revision 2.1" >> xyz
+ dotest btrunktag35 "${testcvs} commit -r2.1 -m twopointone" \
+ "${PROG} [a-z]*: Examining \.
+ Checking in xyz;
+ ${TESTDIR}/cvsroot/my-dir/xyz,v <-- xyz
+ new revision: 2\.1; previous revision: 1\.5
+ done"
+
+ dotest btrunktag36 "${testcvs} rdiff -r stickytag \
+ -r .trunk my-dir" \
+ "${PROG} [a-z]*: Diffing my-dir
+ Index: my-dir/xyz
+ diff -c my-dir/xyz:1\.2 my-dir/xyz:2\.1
+ \*\*\* my-dir/xyz:1\.2 [A-Za-z ]*[0-9]* [0-9:]* [0-9]*
+ --- my-dir/xyz [A-Za-z ]*[0-9]* [0-9:]* [0-9]*
+ \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+ \*\*\* 1,2 \*\*\*\*
+ --- 1,3 ----
+ xyz
+ xyz
+ ${PLUS} revision 2\.1"
+
;;
*)
Index: src/status.c
===================================================================
RCS file: /home2/cvsroot/ccvs/src/status.c,v
retrieving revision 1.45
diff -c -r1.45 status.c
*** status.c 1999/06/01 21:36:33 1.45
--- status.c 2000/06/20 05:13:35
***************
*** 256,261 ****
--- 256,264 ----
if (RCS_nodeisbranch (finfo->rcs, edata->tag))
branch = RCS_whatbranch(finfo->rcs, edata->tag);
+ if ( strcmp(edata->tag, TAG_TRUNK) == 0)
+ branch = xstrdup(TAG_TRUNK);
+
cvs_output (" Sticky Tag:\t\t", 0);
cvs_output (edata->tag, 0);
cvs_output (" (", 0);
Index: src/tag.c
===================================================================
RCS file: /home2/cvsroot/ccvs/src/tag.c,v
retrieving revision 1.86
diff -c -r1.86 tag.c
*** tag.c 2000/06/14 19:32:51 1.86
--- tag.c 2000/06/20 05:13:36
***************
*** 778,784 ****
/* Special tags are always valid. */
if (strcmp (name, TAG_BASE) == 0
! || strcmp (name, TAG_HEAD) == 0)
return;
/* FIXME: This routine doesn't seem to do any locking whatsoever
--- 778,785 ----
/* Special tags are always valid. */
if (strcmp (name, TAG_BASE) == 0
! || strcmp (name, TAG_HEAD) == 0
! || strcmp (name, TAG_TRUNK) == 0)
return;
/* FIXME: This routine doesn't seem to do any locking whatsoever