Here's the latest update to my ".trunk" patch.

(Several people seem to prefer ".main" or various
other strings to ".trunk", which is ok by me...,
that's only a #define)

Anyway, this one makes "cvs admin -l.trunk foo" and
"cvs admin -u.trunk foo" work.

It also includes sanity.sh tests for other "cvs admin" options
and ".trunk".  Though I'm no expert with "cvs admin", I rarely use it, as I
expect is the case with most people.

I also think I found one of the "corner cases" Greg Woods has vaguely
referred to around the area of "cvs commit -r" updating trunk
revisions: "cvs log -r.trunk" (or "cvs log -b"
for that matter) doesn't seem to work quite right if the trunk
contains foo version 1.1 and foo version 2.1.  Only version 2.1
will show up by "cvs log -b" or "cvs log -r.trunk"  For the latter,
it is certainly a bug, for "cvs log -b" I'm not sure, maybe it
was made that way on purpose.  This also gave me insight into
finding other such corner cases, places where strrchr() is used,
looking for a dot (".") are prime stomping grounds for such
corner cases.  Not that I've started looking too hard for them
yet.

Attached is the latest ".trunk" patch against the current (6/27/2000)
development version of CVS.  It passes "make check" and "make
remotecheck" for me on linux.

(ftp.geociites.com was acting weird this morning, so I couldn't
put it on the web)

I grant permission to distribute this patch under
the terms of the GNU Public License

-- steve



__________________________________________________
Do You Yahoo!?
Get Yahoo! Mail - Free email you can access from anywhere!
http://mail.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/27 05:26:00
***************
*** 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/27 05:26:23
***************
*** 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/27 05:27:55
***************
*** 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.1921
diff -c -r1.1921 ChangeLog
*** ChangeLog   2000/06/24 04:55:29     1.1921
--- ChangeLog   2000/06/27 05:28:26
***************
*** 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-23  Larry Jones  <[EMAIL PROTECTED]>
  
        * client.c (send_dirent_proc): Don't allocate ignlist if you're
Index: src/admin.c
===================================================================
RCS file: /home2/cvsroot/ccvs/src/admin.c,v
retrieving revision 1.64
diff -c -r1.64 admin.c
*** admin.c     2000/06/13 21:30:44     1.64
--- admin.c     2000/06/27 05:28:30
***************
*** 801,810 ****
                break;
  
            case 'l':
!               status |= RCS_lock (rcs, arg[2] ? arg + 2 : NULL, 0);
                break;
            case 'u':
!               status |= RCS_unlock (rcs, arg[2] ? arg + 2 : NULL, 0);
                break;
            default: assert(0); /* can't happen */
        }
--- 801,826 ----
                break;
  
            case 'l':
!               {
!                       char *rev;
! 
!                       rev = arg[2] ? arg + 2 : NULL;
!
!                       if (rev && strcmp(rev, TAG_TRUNK)==0)
!                               rev = NULL;
!                       status |= RCS_lock (rcs, rev, 0);
!               }
                break;
            case 'u':
!               {
!                       char *rev;
! 
!                       rev = arg[2] ? arg + 2 : NULL;
!
!                       if (rev && strcmp(rev, TAG_TRUNK)==0)
!                               rev = NULL;
!                       status |= RCS_unlock (rcs, rev, 0);
!               }
                break;
            default: assert(0); /* can't happen */
        }
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/27 05:28: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.162
diff -c -r1.162 commit.c
*** commit.c    2000/06/21 22:28:36     1.162
--- commit.c    2000/06/27 05:28:50
***************
*** 694,703 ****
      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);
--- 694,704 ----
      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);
***************
*** 753,758 ****
--- 754,760 ----
      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;
***************
*** 826,835 ****
             * 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
--- 828,838 ----
             * 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
***************
*** 846,851 ****
--- 849,855 ----
                    return (1);
                }
                if (status == T_MODIFIED && vers->tag &&
+                   strcmp(vers->tag, TAG_TRUNK)!=0 &&
                    !RCS_isbranch (finfo->rcs, vers->tag))
                {
                    error (0, 0,
***************
*** 924,930 ****
            }
            if (status == T_ADDED)
            {
!               if (vers->tag == NULL)
                {
                    char *rcs;
  
--- 928,934 ----
            }
            if (status == T_ADDED)
            {
!               if (vers->tag == NULL || strcmp(vers->tag, TAG_TRUNK) == 0)
                {
                    char *rcs;
  
***************
*** 995,1001 ****
            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;
--- 999,1010 ----
            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;
***************
*** 1007,1020 ****
            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);
--- 1016,1035 ----
            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);
***************
*** 1646,1652 ****
        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)
--- 1661,1668 ----
        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/27 05:28:53
***************
*** 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/27 05:28:59
***************
*** 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/27 05:29:04
***************
*** 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.62
diff -c -r1.62 log.c
*** log.c       2000/06/21 22:28:37     1.62
--- log.c       2000/06/27 05:29:11
***************
*** 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/27 05:29:52
***************
*** 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/27 05:29:54
***************
*** 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/27 05:32:06
***************
*** 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,20972 ----
            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"
+ 
+         # try a few things with "cvs admin" and ".trunk"
+ 
+         dotest_fail btrunktag40 "${testcvs} admin -o ::.trunk xyz" \
+ "RCS file: ${TESTDIR}/cvsroot/my-dir/xyz,v
+ deleting revision 1\.5
+ deleting revision 1\.4
+ deleting revision 1\.3
+ ${PROG} [a-z]*: ${TESTDIR}/cvsroot/my-dir/xyz,v: can't remove branch point 1\.2
+ ${PROG} [a-z]*: cannot modify RCS file for .xyz'"
+ 
+         dotest btrunktag41 "${testcvs} admin -o 1.2::.trunk xyz" \
+ "RCS file: /tmp/cvs-sanity/cvsroot/my-dir/xyz,v
+ deleting revision 1\.5
+ deleting revision 1\.4
+ deleting revision 1\.3
+ done"
+         dotest_fail btrunktag42 "${testcvs} admin -o 1.2:.trunk xyz" \
+ "RCS file: ${TESTDIR}/cvsroot/my-dir/xyz,v
+ deleting revision 2\.1
+ ${PROG} [a-z]*: ${TESTDIR}/cvsroot/my-dir/xyz,v: can't remove branch point 1\.2
+ ${PROG} [a-z]*: cannot modify RCS file for .xyz'"
+ 
+         dotest btrunktag43 "${testcvs} admin -sStab:2.1 xyz" \
+ "RCS file: ${TESTDIR}/cvsroot/my-dir/xyz,v
+ done"
+ 
+         dotest btrunktag44 "${testcvs} admin -m.trunk:this_is_a_test xyz" \
+ "RCS file: /tmp/cvs-sanity/cvsroot/my-dir/xyz,v
+ done"
+ 
+         # NOTE, the following may be one of the broken corner
+           # cases around "cvs commit -r" updating revision numbers
+           # manually.  It could be argued that revisions 1.1 and 1.2
+         # should be printed by this "cvs log", Right now, 
+         # "cvs log -r.trunk" is the same as "cvs log -b"
+         dotest btrunktag45 "${testcvs} log -N -r.trunk xyz" \
+ "
+ RCS file: ${TESTDIR}/cvsroot/my-dir/xyz,v
+ Working file: xyz
+ head: 2\.1
+ branch:
+ locks: strict
+ access list:
+ keyword substitution: kv
+ total revisions: 5;   selected revisions: 1
+ description:
+ ----------------------------
+ revision 2\.1
+ date: [0-9/]* [0-9:]*;  author: ${username};  state: Stab;  lines: ${PLUS}1 -0
+ this_is_a_test
+ ============================================================================="
+ 
+         dotest btrunktag46 "${testcvs} admin -l.trunk xyz" \
+ "RCS file: ${TESTDIR}/cvsroot/my-dir/xyz,v
+ 2.1 locked
+ done"
+         dotest btrunktag46 "${testcvs} admin -u.trunk xyz" \
+ "RCS file: ${TESTDIR}/cvsroot/my-dir/xyz,v
+ 2.1 unlocked
+ done"
+ 
+         
          ;;
  
        *)
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/27 05:32:08
***************
*** 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/27 05:32:12
***************
*** 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

Reply via email to