bug-cvs
[Top][All Lists]
Advanced

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

Patch for CVS 1.11.17 and CVS 1.12.9 that allows for actions using speci


From: Shane Turner
Subject: Patch for CVS 1.11.17 and CVS 1.12.9 that allows for actions using specific versions of CVSROOT/modules
Date: Thu, 02 Sep 2004 15:05:40 -0300
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a3) Gecko/20040817

Here at InfoInterActive, we've created a patch to allow us to better manage our modules. Our issue was that if you had to reproduce a build, there was no guarantee that the current version of a module fully encompassed what it did at the time the software was tagged. To rectify that we now tag CVSROOT/modules when we tag our software and wrote a patch that causes CVS to use a particular version of the modules file on checkout, export, etc. Now, if the CVSROOT/modules file it tagged at the time the software is built, we should now be able to re-create that build even if the module has been changed in the future.

This patch affects:
checkout
export
rdiff
rannotate
rlog
rls (for CVS 1.12.9)

I haven't yet written any new sanity tests for this patch, but I'm planning to, and I'm open to suggestions.

I'd also appreciate some peer review on the patches since I'm not positve that the way I implemented the patch is the best. Currently, non-patched clients should work seemlessly if a patched cvs is the server. If the situation is reversed and the new '-M rev' options is *not* used, then everything should be fine. If a patched client requests a particular revision of a module, then the server doesn't notice the request, so the client doesn't get the expected behaviour.

Here's an example of usage of checking out version 1.1 of the yoyo software (tag yoyo-V1_1, module yoyo):

cvs co -M yoyo-V1_1 -r yoyo-V1_1 yoyo

I have two versions of the patch. One is for CVS 1.11.17 and the other is for CVS 1.12.9. I've attached them both.

Any feedback would be appreciated.

Thanks,

Shane Turner

--
Shane Turner, Senior Software Engineer | InfoInterActive Corp. (An AOL Company)
E shane.turner@infointeractive.com     | W www.infointeractive.com
-----BEGIN GEEK CODE BLOCK-----
GCS d-(+) s: a- C++$ ULS++ P+(++) L++ E@ W+ N o? K? w O M- V !PS !PE Y+ PGP
t++@ 5+ X+ R tv b+ DI+ D+ G e++ h--- r+++ y+++ -----END GEEK CODE BLOCK-----

diff -rp cvs-1.11.17/doc/cvs.texinfo 
cvs-1.11.17-versioned-modules-only/doc/cvs.texinfo
*** cvs-1.11.17/doc/cvs.texinfo Thu May 27 17:18:34 2004
--- cvs-1.11.17-versioned-modules-only/doc/cvs.texinfo  Fri Aug 27 10:07:23 2004
*************** recent revision (instead of ignoring the
*** 3616,3621 ****
--- 3616,3629 ----
  Only tag those files that contain existing tag @var{tag}.
  @end table
  
+ In addition the @code{cvs rtag} command also supports
+ the following additional option:
+ 
+ @table @code
+ @item -M @var{rev}
+ Use @var{rev} version of CVSROOT/modules when expanding modules.
+ @end table
+ 
  The @code{cvs tag} command also allows one to specify
  files by revision or date, using the same @samp{-r},
  @samp{-D}, and @samp{-f} options.  However, this
*************** date.  An optional date is specified by 
*** 8894,8899 ****
--- 8902,8910 ----
  
  @xref{Branching and merging}.
  
+ @item -M @var{rev}
+ Use @var{rev} version of CVSROOT/modules when expanding modules.
+ 
  @item -N
  Only useful together with @samp{-d @var{dir}}.  With
  this option, @sc{cvs} will not ``shorten'' module paths
*************** files, instead of using the module name.
*** 9834,9839 ****
--- 9845,9853 ----
  @item -k @var{subst}
  Set keyword expansion mode (@pxref{Substitution modes}).
  
+ @item -M @var{tag}
+ Use @var{tag} version of CVSROOT/modules when expanding modules.
+ 
  @item -N
  Only useful together with @samp{-d @var{dir}}.
  @xref{checkout options}, for complete details on how
*************** recent revision (instead of ignoring the
*** 10476,10481 ****
--- 10490,10498 ----
  @item -l
  Local; don't descend subdirectories.
  
+ @item -M @var{rev}
+ Use @var{rev} version of CVSROOT/modules when expanding modules.
+ 
  @item -R
  Examine directories recursively.  This option is on by default.
  
*************** Use @var{kflag} keyword expansion.  See
*** 11154,11159 ****
--- 11171,11180 ----
  @item -l
  Local; run only in current working directory.  @xref{Recursive behavior}.
  
+ @item -M @var{rev}
+ Use @var{rev} version of CVSROOT/modules when expanding modules.
+ @ref{checkout options}.
+ 
  @item -N
  Don't ``shorten'' module paths if -d specified.  See
  @ref{checkout options}.
*************** Use @var{kflag} keyword expansion.  See
*** 11303,11308 ****
--- 11324,11333 ----
  @item -l
  Local; run only in current working directory.  @xref{Recursive behavior}.
  
+ @item -M @var{rev}
+ Use @var{rev} version of CVSROOT/modules when expanding modules.
+ @ref{export options}.
+ 
  @item -N
  Don't ``shorten'' module paths if -d specified.  See
  @ref{export options}.
*************** Use head revision if tag/date not found.
*** 11494,11499 ****
--- 11519,11528 ----
  @item -l
  Local; run only in current working directory.  @xref{Recursive behavior}.
  
+ @item -M @var{rev}
+ Use @var{rev} version of CVSROOT/modules when expanding modules.
+ @ref{export options}.
+ 
  @item -R
  Operate recursively (default).  @xref{Recursive behavior}.
  
*************** Only print header.  See @ref{log options
*** 11585,11590 ****
--- 11614,11622 ----
  @item -l
  Local; run only in current working directory.  See @ref{Recursive behavior}.
  
+ @item -M @var{rev}
+ Use @var{rev} version of CVSROOT/modules when expanding modules.
+ 
  @item -N
  Do not list tags.  See @ref{log options}.
  
*************** See @ref{Tagging by date/tag}.
*** 11636,11641 ****
--- 11668,11676 ----
  
  @item -l
  Local; run only in current working directory.  See @ref{Recursive behavior}.
+ 
+ @item -M @var{rev}
+ Use @var{rev} version of CVSROOT/modules when expanding modules.
  
  @item -n
  No execution of tag program.  See @ref{Common options}.
diff -rp cvs-1.11.17/doc/cvsclient.texi 
cvs-1.11.17-versioned-modules-only/doc/cvsclient.texi
*** cvs-1.11.17/doc/cvsclient.texi      Tue Feb  3 10:37:49 2004
--- cvs-1.11.17-versioned-modules-only/doc/cvsclient.texi       Fri Aug 27 
10:07:23 2004
*************** Response expected: no.
*** 1031,1042 ****
  Set a user variable @var{variable} to @var{value}.
  The @code{Root} request need not have been previously sent.
  
! @item expand-modules \n
  Response expected: yes.  Expand the modules which are specified in the
! arguments.  Returns the data in @code{Module-expansion} responses.  Note
! that the server can assume that this is checkout or export, not rtag or
! rdiff; the latter do not access the working directory and thus have no
! need to expand modules on the client side.
  
  Expand may not be the best word for what this request does.  It does not
  necessarily tell you all the files contained in a module, for example.
--- 1031,1044 ----
  Set a user variable @var{variable} to @var{value}.
  The @code{Root} request need not have been previously sent.
  
! @item expand-modules @var{text} \n
  Response expected: yes.  Expand the modules which are specified in the
! arguments using either the trunk version of the CVSROOT/modules file or,
! optionally, the version passed as a tag or revision number.  Returns the
! data in @code{Module-expansion} responses.  Note that the server can
! assume that this is checkout or export, not rtag or rdiff; the latter do
! not access the working directory and thus have no need to expand modules
! on the client side.
  
  Expand may not be the best word for what this request does.  It does not
  necessarily tell you all the files contained in a module, for example.
*************** S: ok
*** 1082,1087 ****
--- 1084,1106 ----
  and then it knows to check the @file{1dir} directory and send
  requests such as @code{Entry} and @code{Modified} for the files in that
  directory.
+ 
+ If the optional version specifier for the CVSROOT/modules file is
+ sent, for example @code{modules_tag}, then the exchange would be:
+ 
+ @example
+ C: Root /home/kingdon/zwork/cvsroot
+ . . .
+ C: Argument aliasmodule
+ C: Directory .
+ C: /home/kingdon/zwork/cvsroot
+ C: expand-modules modules_tag
+ S: Module-expansion 1dir
+ S: ok
+ @end example
+ 
+ and the specified version of the modules file would be used as the
+ reference used to expand the argument.
  
  @item ci \n
  @itemx diff \n
diff -rp cvs-1.11.17/src/annotate.c 
cvs-1.11.17-versioned-modules-only/src/annotate.c
*** cvs-1.11.17/src/annotate.c  Mon Mar 22 11:44:27 2004
--- cvs-1.11.17-versioned-modules-only/src/annotate.c   Fri Aug 27 10:07:23 2004
*************** static int rannotate_proc PROTO((int arg
*** 29,34 ****
--- 29,48 ----
                                 char *mwhere, char *mfile, int shorten,
                                 int local, char *mname, char *msg));
  
+ static const char *const rannotate_usage[] =
+ {
+     "Usage: %s %s [-lRfF] [-r rev] [-D date] [files...]\n",
+     "\t-l\tLocal directory only, no recursion.\n",
+     "\t-R\tProcess directories recursively.\n",
+     "\t-f\tUse head revision if tag/date not found.\n",
+     "\t-F\tAnnotate binary files.\n",
+     "\t-r rev\tAnnotate file as of specified revision/tag.\n",
+     "\t-D date\tAnnotate file as of specified date.\n",
+     "\t-M mrev\tUse a revision or tag of the modules file for expansion.\n",
+     "(Specify the --help global option for a list of other help options)\n",
+     NULL
+ };
+ 
  static const char *const annotate_usage[] =
  {
      "Usage: %s %s [-lRfF] [-r rev] [-D date] [files...]\n",
*************** annotate (argc, argv)
*** 53,66 ****
      int local = 0;
      int err = 0;
      int c;
  
      is_rannotate = (strcmp(cvs_cmd_name, "rannotate") == 0);
  
      if (argc == -1)
!       usage (annotate_usage);
  
      optind = 0;
!     while ((c = getopt (argc, argv, "+lr:D:fFR")) != -1)
      {
        switch (c)
        {
--- 67,95 ----
      int local = 0;
      int err = 0;
      int c;
+     char *valid_options;
+     const char *const *valid_usage;
+     /* What tag will be used to look at the modules file, if any? */
+     const char *modules_tag = NULL;
  
      is_rannotate = (strcmp(cvs_cmd_name, "rannotate") == 0);
  
+     if (is_rannotate)
+     {
+         valid_options = "+lr:D:fFRM:";
+         valid_usage = rannotate_usage;
+     }
+     else
+     {
+         valid_options = "+lr:D:fFR";
+         valid_usage = annotate_usage;
+     }
+         
      if (argc == -1)
!       usage (valid_usage);
  
      optind = 0;
!     while ((c = getopt (argc, argv, valid_options)) != -1)
      {
        switch (c)
        {
*************** annotate (argc, argv)
*** 82,90 ****
            case 'F':
                force_binary = 1;
                break;
            case '?':
            default:
!               usage (annotate_usage);
                break;
        }
      }
--- 111,122 ----
            case 'F':
                force_binary = 1;
                break;
+             case 'M':
+                 modules_tag = optarg;
+                 break;
            case '?':
            default:
!               usage (valid_usage);
                break;
        }
      }
*************** annotate (argc, argv)
*** 108,113 ****
--- 140,148 ----
        if (force_binary)
            send_arg ("-F");
        option_with_arg ("-r", tag);
+         /* Pass the modules_tag if needed.  */
+         if (modules_tag != NULL)
+             option_with_arg ("-M", modules_tag);
        if (date)
            client_senddate (date);
        send_arg ("--");
*************** annotate (argc, argv)
*** 132,138 ****
      {
        DBM *db;
        int i;
!       db = open_module ();
        for (i = 0; i < argc; i++)
        {
            err += do_module (db, argv[i], MISC, "Annotating", rannotate_proc,
--- 167,173 ----
      {
        DBM *db;
        int i;
!       db = open_module (modules_tag);
        for (i = 0; i < argc; i++)
        {
            err += do_module (db, argv[i], MISC, "Annotating", rannotate_proc,
diff -rp cvs-1.11.17/src/checkout.c 
cvs-1.11.17-versioned-modules-only/src/checkout.c
*** cvs-1.11.17/src/checkout.c  Mon Mar 22 11:44:27 2004
--- cvs-1.11.17-versioned-modules-only/src/checkout.c   Fri Aug 27 10:07:23 2004
*************** static const char *const checkout_usage[
*** 61,66 ****
--- 61,67 ----
      "\t-d dir\tCheck out into dir instead of module name.\n",
      "\t-k kopt\tUse RCS kopt -k option on checkout. (is sticky)\n",
      "\t-j rev\tMerge in changes made between current revision and rev.\n",
+     "\t-M mrev\tUse a revision or tag of the modules file for expansion.\n",
      "(Specify the --help global option for a list of other help options)\n",
      NULL
  };
*************** static const char *const export_usage[] 
*** 77,82 ****
--- 78,84 ----
      "\t-D date\tExport revisions as of date.\n",
      "\t-d dir\tExport into dir instead of module name.\n",
      "\t-k kopt\tUse RCS kopt -k option on checkout.\n",
+     "\t-M mrev\tUse a revision or tag of the modules file for expansion.\n",
      "(Specify the --help global option for a list of other help options)\n",
      NULL
  };
*************** checkout (argc, argv)
*** 111,116 ****
--- 113,120 ----
      char *where = NULL;
      char *valid_options;
      const char *const *valid_usage;
+     /* What tag will be used to look at the modules file, if any? */
+     const char *modules_tag = NULL;
  
      /* initialize static options */
      force_tag_match = 1;
*************** checkout (argc, argv)
*** 133,145 ****
      if (strcmp (cvs_cmd_name, "export") == 0)
      {
          m_type = EXPORT;
!       valid_options = "+Nnk:d:flRQqr:D:";
        valid_usage = export_usage;
      }
      else
      {
          m_type = CHECKOUT;
!       valid_options = "+ANnk:d:flRpQqcsr:D:j:P";
        valid_usage = checkout_usage;
      }
  
--- 137,149 ----
      if (strcmp (cvs_cmd_name, "export") == 0)
      {
          m_type = EXPORT;
!       valid_options = "+Nnk:d:flRQqr:D:M:";
        valid_usage = export_usage;
      }
      else
      {
          m_type = CHECKOUT;
!       valid_options = "+ANnk:d:flRpQqcsr:D:j:PM:";
        valid_usage = checkout_usage;
      }
  
*************** checkout (argc, argv)
*** 211,216 ****
--- 215,223 ----
                tag = optarg;
                checkout_prune_dirs = 1;
                break;
+             case 'M':
+                 modules_tag = optarg;
+                 break;
            case 'D':
                date = Make_Date (optarg);
                checkout_prune_dirs = 1;
*************** checkout (argc, argv)
*** 280,288 ****
        {
            /* This is done here because we need to read responses
                 from the server before we send the command checkout or
!                export files. */
  
!           client_expand_modules (argc, argv, local);
        }
  
        if (!run_module_prog)
--- 287,296 ----
        {
            /* This is done here because we need to read responses
                 from the server before we send the command checkout or
!                export files.  We need to send the modules_tag along
!                if it is set. */
  
!           client_expand_modules (argc, argv, local, modules_tag);
        }
  
        if (!run_module_prog)
*************** checkout (argc, argv)
*** 315,320 ****
--- 323,331 ----
            option_with_arg ("-j", join_rev1);
        if (join_rev2 != NULL)
            option_with_arg ("-j", join_rev2);
+         /* Pass the modules_tag if needed.  */
+         if (modules_tag != NULL)
+             option_with_arg ("-M", modules_tag);
        send_arg ("--");
  
        if (expand_modules)
*************** checkout (argc, argv)
*** 336,342 ****
  
      if (cat)
      {
!       cat_module (status);
        if (options)
        {
            free (options);
--- 347,353 ----
  
      if (cat)
      {
!       cat_module (status, modules_tag);
        if (options)
        {
            free (options);
*************** checkout (argc, argv)
*** 344,350 ****
        }
        return (0);
      }
!     db = open_module ();
  
  
      /* If we've specified something like "cvs co foo/bar baz/quux"
--- 355,361 ----
        }
        return (0);
      }
!     db = open_module (modules_tag);
  
  
      /* If we've specified something like "cvs co foo/bar baz/quux"
diff -rp cvs-1.11.17/src/client.c 
cvs-1.11.17-versioned-modules-only/src/client.c
*** cvs-1.11.17/src/client.c    Mon Apr 26 11:57:53 2004
--- cvs-1.11.17-versioned-modules-only/src/client.c     Fri Aug 27 10:07:23 2004
*************** static int module_argc;
*** 2962,2971 ****
  static char **module_argv;
  
  void
! client_expand_modules (argc, argv, local)
      int argc;
      char **argv;
      int local;
  {
      int errs;
      int i;
--- 2962,2972 ----
  static char **module_argv;
  
  void
! client_expand_modules (argc, argv, local, modules_tag)
      int argc;
      char **argv;
      int local;
+     const char *modules_tag;
  {
      int errs;
      int i;
*************** client_expand_modules (argc, argv, local
*** 2980,2986 ****
        send_arg (argv[i]);
      send_a_repository ("", current_parsed_root->directory, "");
  
!     send_to_server ("expand-modules\012", 0);
  
      errs = get_server_responses ();
      if (last_repos != NULL)
--- 2981,2993 ----
        send_arg (argv[i]);
      send_a_repository ("", current_parsed_root->directory, "");
  
!     send_to_server ("expand-modules", 0);
!     if (modules_tag != NULL)
!     {
!         send_to_server(" ", 1);
!         send_to_server(modules_tag, 0);
!     }
!     send_to_server("\012", 1);
  
      errs = get_server_responses ();
      if (last_repos != NULL)
*************** start_rsh_server (root, to_server, from_
*** 4856,4865 ****
  /* Send an argument STRING.  */
  void
  send_arg (string)
!     char *string;
  {
      char buf[1];
!     char *p = string;
  
      send_to_server ("Argument ", 0);
  
--- 4863,4872 ----
  /* Send an argument STRING.  */
  void
  send_arg (string)
!     const char *string;
  {
      char buf[1];
!     const char *p = string;
  
      send_to_server ("Argument ", 0);
  
*************** client_notify (repository, update_dir, f
*** 5906,5913 ****
   */
  void
  option_with_arg (option, arg)
!     char *option;
!     char *arg;
  {
      if (arg == NULL)
        return;
--- 5913,5920 ----
   */
  void
  option_with_arg (option, arg)
!     const char *option;
!     const char *arg;
  {
      if (arg == NULL)
        return;
diff -rp cvs-1.11.17/src/client.h 
cvs-1.11.17-versioned-modules-only/src/client.h
*** cvs-1.11.17/src/client.h    Fri Mar 19 14:27:02 2004
--- cvs-1.11.17-versioned-modules-only/src/client.h     Fri Aug 27 10:07:23 2004
*************** void read_from_server PROTO((char *buf, 
*** 83,89 ****
  
  /* Internal functions that handle client communication to server, etc.  */
  int supported_request PROTO ((char *));
! void option_with_arg PROTO((char *option, char *arg));
  
  /* Get the responses and then close the connection.  */
  extern int get_responses_and_close PROTO((void));
--- 83,89 ----
  
  /* Internal functions that handle client communication to server, etc.  */
  int supported_request PROTO ((char *));
! void option_with_arg PROTO((const char *option, const char *arg));
  
  /* Get the responses and then close the connection.  */
  extern int get_responses_and_close PROTO((void));
*************** send_files PROTO((int argc, char **argv,
*** 119,125 ****
  
  /* Send an argument to the remote server.  */
  void
! send_arg PROTO((char *string));
  
  /* Send a string of single-char options to the remote server, one by one.  */
  void
--- 119,125 ----
  
  /* Send an argument to the remote server.  */
  void
! send_arg PROTO((const char *string));
  
  /* Send a string of single-char options to the remote server, one by one.  */
  void
*************** extern struct response responses[];
*** 188,194 ****
  #ifdef CLIENT_SUPPORT
  
  extern void client_senddate PROTO((const char *date));
! extern void client_expand_modules PROTO((int argc, char **argv, int local));
  extern void client_send_expansions PROTO((int local, char *where,
                                          int build_dirs));
  extern void client_nonexpanded_setup PROTO((void));
--- 188,195 ----
  #ifdef CLIENT_SUPPORT
  
  extern void client_senddate PROTO((const char *date));
! extern void client_expand_modules PROTO((int argc, char **argv, int local,
!                                          const char *modules_tag));
  extern void client_send_expansions PROTO((int local, char *where,
                                          int build_dirs));
  extern void client_nonexpanded_setup PROTO((void));
diff -rp cvs-1.11.17/src/cvs.h cvs-1.11.17-versioned-modules-only/src/cvs.h
*** cvs-1.11.17/src/cvs.h       Wed Jun  9 11:34:54 2004
--- cvs-1.11.17-versioned-modules-only/src/cvs.h        Fri Aug 27 10:07:23 2004
*************** extern int diff_exec PROTO ((const char 
*** 432,438 ****
  
  #include "error.h"
  
! DBM *open_module PROTO((void));
  FILE *open_file PROTO((const char *, const char *));
  List *Find_Directories PROTO((char *repository, int which, List *entries));
  void Entries_Close PROTO((List *entries));
--- 432,438 ----
  
  #include "error.h"
  
! DBM *open_module PROTO((const char *tag));
  FILE *open_file PROTO((const char *, const char *));
  List *Find_Directories PROTO((char *repository, int which, List *entries));
  void Entries_Close PROTO((List *entries));
*************** void ParseTag PROTO((char **tagp, char *
*** 576,582 ****
  void WriteTag PROTO ((const char *dir, const char *tag, const char *date,
                        int nonbranch, const char *update_dir,
                        const char *repository));
! void cat_module PROTO((int status));
  void check_entries PROTO((char *dir));
  void close_module PROTO((DBM * db));
  void copy_file PROTO((const char *from, const char *to));
--- 576,582 ----
  void WriteTag PROTO ((const char *dir, const char *tag, const char *date,
                        int nonbranch, const char *update_dir,
                        const char *repository));
! void cat_module PROTO((int status, const char *tag));
  void check_entries PROTO((char *dir));
  void close_module PROTO((DBM * db));
  void copy_file PROTO((const char *from, const char *to));
diff -rp cvs-1.11.17/src/log.c cvs-1.11.17-versioned-modules-only/src/log.c
*** cvs-1.11.17/src/log.c       Mon May 10 10:37:16 2004
--- cvs-1.11.17-versioned-modules-only/src/log.c        Fri Aug 27 10:07:23 2004
*************** static int version_compare PROTO ((const
*** 145,150 ****
--- 145,180 ----
  static struct log_data log_data;
  static int is_rlog;
  
+ static const char *const rlog_usage[] =
+ {
+     "Usage: %s %s [-lRhtNb] [-r[revisions]] [-d dates] [-s states]\n",
+     "    [-w[logins]] [files...]\n",
+     "\t-l\tLocal directory only, no recursion.\n",
+     "\t-R\tOnly print name of RCS file.\n",
+     "\t-h\tOnly print header.\n",
+     "\t-t\tOnly print header and descriptive text.\n",
+     "\t-N\tDo not list tags.\n",
+     "\t-S\tDo not print name/header if no revisions selected.\n",
+     "\t-b\tOnly list revisions on the default branch.\n",
+     "\t-r[revisions]\tA comma-separated list of revisions to print:\n",
+     "\t   rev1:rev2   Between rev1 and rev2, including rev1 and rev2.\n",
+     "\t   rev1::rev2  Between rev1 and rev2, excluding rev1.\n",
+     "\t   rev:        rev and following revisions on the same branch.\n",
+     "\t   rev::       After rev on the same branch.\n",
+     "\t   :rev        rev and previous revisions on the same branch.\n",
+     "\t   ::rev       rev and previous revisions on the same branch.\n",
+     "\t   rev         Just rev.\n",
+     "\t   branch      All revisions on the branch.\n",
+     "\t   branch.     The last revision on the branch.\n",
+     "\t-d dates\tA semicolon-separated list of dates\n",
+     "\t        \t(D1<D2 for range, D for latest before).\n",
+     "\t-s states\tOnly list revisions with specified states.\n",
+     "\t-w[logins]\tOnly list revisions checked in by specified logins.\n",
+     "\t-M mrev\tUse a revision or tag of the modules file for expansion.\n",
+     "(Specify the --help global option for a list of other help options)\n",
+     NULL
+ };
+ 
  static const char *const log_usage[] =
  {
      "Usage: %s %s [-lRhtNb] [-r[revisions]] [-d dates] [-s states]\n",
*************** static const char *const log_usage[] =
*** 170,175 ****
--- 200,206 ----
      "\t        \t(D1<D2 for range, D for latest before).\n",
      "\t-s states\tOnly list revisions with specified states.\n",
      "\t-w[logins]\tOnly list revisions checked in by specified logins.\n",
+     "\t-M mrev\tUse a revision or tag of the modules file for expansion.\n",
      "(Specify the --help global option for a list of other help options)\n",
      NULL
  };
*************** cvslog (argc, argv)
*** 224,240 ****
      int err = 0;
      int local = 0;
      struct option_revlist **prl;
  
      is_rlog = (strcmp (cvs_cmd_name, "rlog") == 0);
  
      if (argc == -1)
!       usage (log_usage);
  
      memset (&log_data, 0, sizeof log_data);
      prl = &log_data.revlist;
  
      optind = 0;
!     while ((c = getopt (argc, argv, "+bd:hlNSRr::s:tw::")) != -1)
      {
        switch (c)
        {
--- 255,286 ----
      int err = 0;
      int local = 0;
      struct option_revlist **prl;
+     char *valid_options;
+     const char *const *valid_usage;
+     /* What tag will be used to look at the modules file, if any? */
+     const char *modules_tag = NULL;
  
      is_rlog = (strcmp (cvs_cmd_name, "rlog") == 0);
  
+     if (is_rlog)
+     {
+         valid_options = "+bd:M:hlNSRr::s:tw::";
+         valid_usage = rlog_usage;
+     }
+     else
+     {
+         valid_options = "+bd:hlNSRr::s:tw::";
+         valid_usage = log_usage;
+     }
+ 
      if (argc == -1)
!       usage (valid_usage);
  
      memset (&log_data, 0, sizeof log_data);
      prl = &log_data.revlist;
  
      optind = 0;
!     while ((c = getopt (argc, argv, valid_options)) != -1)
      {
        switch (c)
        {
*************** cvslog (argc, argv)
*** 275,280 ****
--- 321,329 ----
                else
                    log_parse_list (&log_data.authorlist, "@@MYSELF");
                break;
+             case 'M':
+                 modules_tag = optarg;
+                 break;
            case '?':
            default:
                usage (log_usage);
*************** cvslog (argc, argv)
*** 351,356 ****
--- 400,408 ----
            send_arg("-R");
        if (log_data.long_header)
            send_arg("-t");
+         /* Pass the modules_tag if needed.  */
+         if (modules_tag != NULL)
+             option_with_arg ("-M", modules_tag);
  
        while (log_data.revlist != NULL)
        {
*************** cvslog (argc, argv)
*** 413,419 ****
      {
        DBM *db;
        int i;
!       db = open_module ();
        for (i = 0; i < argc; i++)
        {
            err += do_module (db, argv[i], MISC, "Logging", rlog_proc,
--- 465,471 ----
      {
        DBM *db;
        int i;
!       db = open_module (modules_tag);
        for (i = 0; i < argc; i++)
        {
            err += do_module (db, argv[i], MISC, "Logging", rlog_proc,
diff -rp cvs-1.11.17/src/modules.c 
cvs-1.11.17-versioned-modules-only/src/modules.c
*** cvs-1.11.17/src/modules.c   Sun Apr 11 11:46:52 2004
--- cvs-1.11.17-versioned-modules-only/src/modules.c    Fri Aug 27 10:07:23 2004
*************** static void save_d PROTO((char *k, int k
*** 59,82 ****
   * Open the modules file, and die if the CVSROOT environment variable
   * was not set.  If the modules file does not exist, that's fine, and
   * a warning message is displayed and a NULL is returned.
   */
  DBM *
! open_module ()
  {
      char *mfile;
      DBM *retval;
  
      if (current_parsed_root == NULL)
      {
        error (0, 0, "must set the CVSROOT environment variable");
        error (1, 0, "or specify the '-d' global option");
      }
!     mfile = xmalloc (strlen (current_parsed_root->directory)
!                    + sizeof (CVSROOTADM)
!                    + sizeof (CVSROOTADM_MODULES) + 3);
!     (void) sprintf (mfile, "%s/%s/%s", current_parsed_root->directory,
!                   CVSROOTADM, CVSROOTADM_MODULES);
      retval = dbm_open (mfile, O_RDONLY, 0666);
      free (mfile);
      return retval;
  }
--- 59,179 ----
   * Open the modules file, and die if the CVSROOT environment variable
   * was not set.  If the modules file does not exist, that's fine, and
   * a warning message is displayed and a NULL is returned.
+  * If tag is not NULL, then we use the tag or revision specified by tag to
+  * checkout the modules file before reading it.  This allows versioned
+  * modules. 
   */
  DBM *
! open_module (tag)
!      const char *tag;
  {
      char *mfile;
      DBM *retval;
  
+     if(trace)
+     {
+         cvs_outerr(CLIENT_SERVER_STR, 0);
+         cvs_outerr("-> open_module(", 0);
+         cvs_outerr((tag == NULL ? "NULL" : tag), 0);
+         cvs_outerr(")\n", 0);
+     }
+ 
      if (current_parsed_root == NULL)
      {
        error (0, 0, "must set the CVSROOT environment variable");
        error (1, 0, "or specify the '-d' global option");
      }
! 
!     /* Need a special tagged version of the modules file? */
!     if (tag == NULL)
!     {
!         /* No special version.  Just read the normal file */
!         mfile = xmalloc (strlen (current_parsed_root->directory)
!                          + sizeof (CVSROOTADM)
!                          + sizeof (CVSROOTADM_MODULES) + 3);
!         (void) sprintf (mfile, "%s/%s/%s", current_parsed_root->directory,
!                  CVSROOTADM, CVSROOTADM_MODULES);
!     }
!     else
!     {
!         /* Where is the repository?
!          * What's a modifiable version of the tag?
!          */
!         char *repository = xmalloc (strlen (current_parsed_root->directory)
!                                     + sizeof(CVSROOTADM) + 2);
!         char *mutable_tag = xstrdup (tag);
!         char *rev;
!         RCSNode *rcs;
! 
!         sprintf (repository, "%s/%s", current_parsed_root->directory,
!                  CVSROOTADM);
! 
!         /* Build the string we'll gfive to dbm_open */
!         mfile = xmalloc (strlen (Tmpdir) + sizeof (CVSROOTADM_MODULES)
!                          + 1 + 1 + 17 + 1);
!         sprintf (mfile, "%s/%s.%ld", Tmpdir, CVSROOTADM_MODULES,
!                  getpid());
! 
!         if(trace)
!         {
!             cvs_outerr(CLIENT_SERVER_STR, 0);
!             cvs_outerr("-> RCS checkout of modules file from `", 0);
!             cvs_outerr(repository, 0);
!             cvs_outerr("' to '", 0);
!             cvs_outerr(mfile, 0);
!             cvs_outerr("'\n", 0);
!         }
! 
!         /* Parse the RCS file that is the modules file */
!         rcs = RCS_parse (CVSROOTADM_MODULES, repository);
! 
!         if(rcs == NULL)
!         {
!             error (1, 0, "cannot parse modules RCS file");
!         }
!         free (repository);
! 
!         /* Turn the tag into an RCS revision */
!         rev = RCS_gettag(rcs, mutable_tag, 1, (int *) NULL);
!         if(rev == NULL)
!         {
!             error (1, 0, "no version '%s' in modules file", tag);
!         }
! 
!         if(trace)
!         {
!             cvs_outerr(CLIENT_SERVER_STR, 0);
!             cvs_outerr("-> Resolved modules file tag '", 0);
!             cvs_outerr(tag, 0);
!             cvs_outerr("' to '", 0);
!             cvs_outerr(rev, 0);
!             cvs_outerr("'\n", 0);
!         }
! 
!         /* Check the modules RCS file out into a temporary file */
!         if(RCS_checkout (rcs, mfile, rev, mutable_tag,
!                          NULL, RUN_TTY, NULL, NULL) != 0)
!         {
!             /* Can't do this */
!             error (1, 0, "cannot checkout modules file with specified tag");
!         }
!         /* Don't free the RCSNode because I don't know if you should */
!         free (rev);
!         free (mutable_tag);
!     }
! 
!     /* Open the database */
      retval = dbm_open (mfile, O_RDONLY, 0666);
+ 
+     /* Unlink the temporary file now.  Even if it's not done being read, it'll
+      * go away when it's closed.
+      */
+     if(tag != NULL && unlink_file (mfile) < 0)
+     {
+         error (0, 0, "cannot unlink temporary file `%s'", mfile);
+     }
+ 
+     /* Either way, free the temporary filename */
      free (mfile);
      return retval;
  }
*************** save_d (k, ks, d, ds)
*** 943,950 ****
     non-zero, print out status information for each module. */
  
  void
! cat_module (status)
      int status;
  {
      DBM *db;
      datum key, val;
--- 1040,1048 ----
     non-zero, print out status information for each module. */
  
  void
! cat_module (status, tag)
      int status;
+     const char *tag;
  {
      DBM *db;
      datum key, val;
*************** cat_module (status)
*** 957,963 ****
      Status = status;
  
      /* Read the whole modules file into allocated records */
!     if (!(db = open_module ()))
        error (1, 0, "failed to open the modules file");
  
      for (key = dbm_firstkey (db); key.dptr != NULL; key = dbm_nextkey (db))
--- 1055,1061 ----
      Status = status;
  
      /* Read the whole modules file into allocated records */
!     if (!(db = open_module (tag)))
        error (1, 0, "failed to open the modules file");
  
      for (key = dbm_firstkey (db); key.dptr != NULL; key = dbm_nextkey (db))
diff -rp cvs-1.11.17/src/patch.c cvs-1.11.17-versioned-modules-only/src/patch.c
*** cvs-1.11.17/src/patch.c     Fri Apr  2 15:25:32 2004
--- cvs-1.11.17-versioned-modules-only/src/patch.c      Fri Aug 27 10:07:23 2004
*************** static const char *const patch_usage[] =
*** 54,59 ****
--- 54,60 ----
      "\t-D date\tDate.\n",
      "\t-r rev\tRevision - symbolic or numeric.\n",
      "\t-V vers\tUse RCS Version \"vers\" for keyword expansion.\n",
+     "\t-M mrev\tUse a revision or tag of the modules file for expansion.\n",
      "(Specify the --help global option for a list of other help options)\n",
      NULL
  };
*************** patch (argc, argv)
*** 70,81 ****
      int c;
      int err = 0;
      DBM *db;
  
      if (argc == -1)
        usage (patch_usage);
  
      optind = 0;
!     while ((c = getopt (argc, argv, "+V:k:cuftsQqlRD:r:")) != -1)
      {
        switch (c)
        {
--- 71,84 ----
      int c;
      int err = 0;
      DBM *db;
+     /* What tag will be used to look at the modules file, if any? */
+     const char *modules_tag = NULL;
  
      if (argc == -1)
        usage (patch_usage);
  
      optind = 0;
!     while ((c = getopt (argc, argv, "+V:k:cuftsQqlRD:r:M:")) != -1)
      {
        switch (c)
        {
*************** patch (argc, argv)
*** 161,166 ****
--- 164,172 ----
            case 'c':                   /* Context diff */
                unidiff = 0;
                break;
+             case 'M':
+                 modules_tag = optarg;
+                 break;
            case '?':
            default:
                usage (patch_usage);
*************** patch (argc, argv)
*** 220,225 ****
--- 226,234 ----
            client_senddate (date2);
        if (options[0] != '\0')
            send_arg (options);
+         /* Pass the modules_tag if needed.  */
+         if (modules_tag != NULL)
+             option_with_arg ("-M", modules_tag);
  
        {
            int i;
*************** patch (argc, argv)
*** 252,258 ****
      (void)SIG_register (SIGTERM, patch_cleanup);
  #endif
  
!     db = open_module ();
      for (i = 0; i < argc; i++)
        err += do_module (db, argv[i], PATCH, "Patching", patch_proc,
                          (char *)NULL, 0, local, 0, 0, (char *)NULL);
--- 261,267 ----
      (void)SIG_register (SIGTERM, patch_cleanup);
  #endif
  
!     db = open_module (modules_tag);
      for (i = 0; i < argc; i++)
        err += do_module (db, argv[i], PATCH, "Patching", patch_proc,
                          (char *)NULL, 0, local, 0, 0, (char *)NULL);
diff -rp cvs-1.11.17/src/server.c 
cvs-1.11.17-versioned-modules-only/src/server.c
*** cvs-1.11.17/src/server.c    Wed Jun  9 11:34:55 2004
--- cvs-1.11.17-versioned-modules-only/src/server.c     Fri Aug 27 10:07:23 2004
*************** serve_expand_modules (arg)
*** 4720,4727 ****
      int err;
      DBM *db;
      err = 0;
  
-     db = open_module ();
      for (i = 1; i < argument_count; i++)
        err += do_module (db, argument_vector[i],
                          CHECKOUT, "Updating", expand_proc,
--- 4720,4734 ----
      int err;
      DBM *db;
      err = 0;
+     int c;
+ 
+     const char* module_tag = NULL;
+ 
+     if (strlen(arg) > 0)
+       module_tag = arg;
+ 
+     db = open_module (module_tag);
  
      for (i = 1; i < argument_count; i++)
        err += do_module (db, argument_vector[i],
                          CHECKOUT, "Updating", expand_proc,
diff -rp cvs-1.11.17/src/tag.c cvs-1.11.17-versioned-modules-only/src/tag.c
*** cvs-1.11.17/src/tag.c       Tue Apr  6 15:37:10 2004
--- cvs-1.11.17-versioned-modules-only/src/tag.c        Fri Aug 27 10:07:23 2004
*************** struct master_lists
*** 64,70 ****
  static List *mtlist;
  static List *tlist;
  
! static const char rtag_opts[] = "+aBbdFflnQqRr:D:";
  static const char *const rtag_usage[] =
  {
      "Usage: %s %s [-abdFflnR] [-r rev|-D date] tag modules...\n",
--- 64,70 ----
  static List *mtlist;
  static List *tlist;
  
! static const char rtag_opts[] = "+aBbdFflnQqRr:D:M:";
  static const char *const rtag_usage[] =
  {
      "Usage: %s %s [-abdFflnR] [-r rev|-D date] tag modules...\n",
*************** static const char *const rtag_usage[] =
*** 79,84 ****
--- 79,85 ----
      "\t-R\tProcess directories recursively.\n",
      "\t-r rev\tExisting revision/tag.\n",
      "\t-D\tExisting date.\n",
+     "\t-M mrev\tUse a revision or tag of the modules file for expansion.\n",
      "(Specify the --help global option for a list of other help options)\n",
      NULL
  };
*************** cvstag (argc, argv)
*** 110,115 ****
--- 111,118 ----
      int c;
      int err = 0;
      int run_module_prog = 1;
+     /* What tag will be used to look at the modules file, if any? */
+     const char *modules_tag = NULL;
  
      is_rtag = (strcmp (cvs_cmd_name, "rtag") == 0);
      
*************** cvstag (argc, argv)
*** 170,175 ****
--- 173,181 ----
                      free (date);
                  date = Make_Date (optarg);
                  break;
+             case 'M':
+                 modules_tag = optarg;
+                 break;
            case '?':
            default:
                usage (is_rtag ? rtag_usage : tag_usage);
*************** cvstag (argc, argv)
*** 217,222 ****
--- 223,231 ----
            send_arg("-l");
        if (!run_module_prog)
            send_arg("-n");
+         /* Pass the modules_tag if needed. */
+         if (modules_tag != NULL)
+             option_with_arg ("-M", modules_tag);
  
        if (numtag)
            option_with_arg ("-r", numtag);
*************** cvstag (argc, argv)
*** 254,260 ****
      {
        DBM *db;
        int i;
!       db = open_module ();
        for (i = 0; i < argc; i++)
        {
            /* XXX last arg should be repository, but doesn't make sense here */
--- 263,269 ----
      {
        DBM *db;
        int i;
!       db = open_module (modules_tag);
        for (i = 0; i < argc; i++)
        {
            /* XXX last arg should be repository, but doesn't make sense here */
diff -rp cvs-1.12.9/doc/cvs.texinfo 
cvs-1.12.9-versioned-modules-only/doc/cvs.texinfo
*** cvs-1.12.9/doc/cvs.texinfo  Wed May 19 18:38:31 2004
--- cvs-1.12.9-versioned-modules-only/doc/cvs.texinfo   Fri Aug 27 12:12:20 2004
*************** recent revision (instead of ignoring the
*** 3768,3773 ****
--- 3768,3781 ----
  Only tag those files that contain existing tag @var{tag}.
  @end table
  
+ In addition the @code{cvs rtag} command also supports
+ the following additional option:
+ 
+ @table @code
+ @item -M @var{rev}
+ Use @var{rev} version of CVSROOT/modules when expanding modules.
+ @end table
+ 
  The @code{cvs tag} command also allows one to specify
  files by revision or date, using the same @samp{-r},
  @samp{-D}, and @samp{-f} options.  However, this
*************** date.  An optional date is specified by 
*** 9210,9215 ****
--- 9218,9226 ----
  
  @xref{Branching and merging}.
  
+ @item -M @var{rev}
+ Use @var{rev} version of CVSROOT/modules when expanding modules.
+ 
  @item -N
  Only useful together with @samp{-d @var{dir}}.  With
  this option, @sc{cvs} will not ``shorten'' module paths
*************** files, instead of using the module name.
*** 10150,10155 ****
--- 10161,10169 ----
  @item -k @var{subst}
  Set keyword expansion mode (@pxref{Substitution modes}).
  
+ @item -M @var{tag}
+ Use @var{tag} version of CVSROOT/modules when expanding modules.
+ 
  @item -N
  Only useful together with @samp{-d @var{dir}}.
  @xref{checkout options}, for complete details on how
*************** you would need to prefix the examples ab
*** 10743,10748 ****
--- 10757,10763 ----
  @itemize @bullet
  @item
  ls [-e | -l] [-RP] [-r revision] [-D date] [path@dots{}]
+ rls [-e | -l] [-RP] [-r revision] [-M module_revision ] [-D date] 
[path@dots{}]
  @item
  Requires: repository for @code{rls}, repository & working directory for
  @code{ls}.
*************** Show files with revision or tag.
*** 10803,10808 ****
--- 10818,10830 ----
  Show files from date.
  @end table
  
+ In addition, @code{rls} supports the following option:
+ 
+ @table @code
+ @item -M @var{revision}
+ Use @var{revision} of CVSROOT/modules to expand modules.
+ @end table
+ 
  @c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  @node rls examples
  @appendixsubsec rls examples
*************** recent revision (instead of ignoring the
*** 10891,10896 ****
--- 10913,10921 ----
  @item -l
  Local; don't descend subdirectories.
  
+ @item -M @var{rev}
+ Use @var{rev} version of CVSROOT/modules when expanding modules.
+ 
  @item -R
  Examine directories recursively.  This option is on by default.
  
*************** Use @var{kflag} keyword expansion.  See
*** 11574,11579 ****
--- 11599,11608 ----
  @item -l
  Local; run only in current working directory.  @xref{Recursive behavior}.
  
+ @item -M @var{rev}
+ Use @var{rev} version of CVSROOT/modules when expanding modules.
+ @ref{checkout options}.
+ 
  @item -N
  Don't ``shorten'' module paths if -d specified.  See
  @ref{checkout options}.
*************** Use @var{kflag} keyword expansion.  See
*** 11723,11728 ****
--- 11752,11761 ----
  @item -l
  Local; run only in current working directory.  @xref{Recursive behavior}.
  
+ @item -M @var{rev}
+ Use @var{rev} version of CVSROOT/modules when expanding modules.
+ @ref{export options}.
+ 
  @item -N
  Don't ``shorten'' module paths if -d specified.  See
  @ref{export options}.
*************** Only print header.  See @ref{log options
*** 11858,11863 ****
--- 11891,11899 ----
  @item -l
  Local; run only in current working directory.  See @ref{Recursive behavior}.
  
+ @item -M @var{rev}
+ Use @var{rev} version of CVSROOT/modules when expanding modules.
+ 
  @item -N
  Do not list tags.  See @ref{log options}.
  
*************** Use head revision if tag/date not found.
*** 11914,11919 ****
--- 11950,11959 ----
  @item -l
  Local; run only in current working directory.  @xref{Recursive behavior}.
  
+ @item -M @var{rev}
+ Use @var{rev} version of CVSROOT/modules when expanding modules.
+ @ref{export options}.
+ 
  @item -R
  Operate recursively (default).  @xref{Recursive behavior}.
  
*************** See @ref{Tagging by date/tag}.
*** 12056,12061 ****
--- 12096,12104 ----
  
  @item -l
  Local; run only in current working directory.  See @ref{Recursive behavior}.
+ 
+ @item -M @var{rev}
+ Use @var{rev} version of CVSROOT/modules when expanding modules.
  
  @item -n
  No execution of tag program.  See @ref{Common options}.
diff -rp cvs-1.12.9/doc/cvsclient.texi 
cvs-1.12.9-versioned-modules-only/doc/cvsclient.texi
*** cvs-1.12.9/doc/cvsclient.texi       Fri Apr 23 21:29:06 2004
--- cvs-1.12.9-versioned-modules-only/doc/cvsclient.texi        Fri Aug 27 
11:08:23 2004
*************** Response expected: no.
*** 1031,1042 ****
  Set a user variable @var{variable} to @var{value}.
  The @code{Root} request need not have been previously sent.
  
! @item expand-modules \n
  Response expected: yes.  Expand the modules which are specified in the
! arguments.  Returns the data in @code{Module-expansion} responses.  Note
! that the server can assume that this is checkout or export, not rtag or
! rdiff; the latter do not access the working directory and thus have no
! need to expand modules on the client side.
  
  Expand may not be the best word for what this request does.  It does not
  necessarily tell you all the files contained in a module, for example.
--- 1031,1044 ----
  Set a user variable @var{variable} to @var{value}.
  The @code{Root} request need not have been previously sent.
  
! @item expand-modules @var{text} \n
  Response expected: yes.  Expand the modules which are specified in the
! arguments using either the trunk version of the CVSROOT/modules file or,
! optionally, the version passed as a tag or revision number.  Returns the
! data in @code{Module-expansion} responses.  Note that the server can
! assume that this is checkout or export, not rtag or rdiff; the latter do
! not access the working directory and thus have no need to expand modules
! on the client side.
  
  Expand may not be the best word for what this request does.  It does not
  necessarily tell you all the files contained in a module, for example.
*************** S: ok
*** 1082,1087 ****
--- 1084,1106 ----
  and then it knows to check the @file{1dir} directory and send
  requests such as @code{Entry} and @code{Modified} for the files in that
  directory.
+ 
+ If the optional version specifier for the CVSROOT/modules file is
+ sent, for example @code{modules_tag}, then the exchange would be:
+ 
+ @example
+ C: Root /home/kingdon/zwork/cvsroot
+ . . .
+ C: Argument aliasmodule
+ C: Directory .
+ C: /home/kingdon/zwork/cvsroot
+ C: expand-modules modules_tag
+ S: Module-expansion 1dir
+ S: ok
+ @end example
+ 
+ and the specified version of the modules file would be used as the
+ reference used to expand the argument.
  
  @item ci \n
  @itemx diff \n
diff -rp cvs-1.12.9/src/annotate.c 
cvs-1.12.9-versioned-modules-only/src/annotate.c
*** cvs-1.12.9/src/annotate.c   Sat Mar 20 19:40:44 2004
--- cvs-1.12.9-versioned-modules-only/src/annotate.c    Fri Aug 27 11:36:35 2004
*************** static int rannotate_proc (int argc, cha
*** 29,34 ****
--- 29,48 ----
                                 char *mwhere, char *mfile, int shorten,
                                 int local, char *mname, char *msg);
  
+ static const char *const rannotate_usage[] =
+ {
+     "Usage: %s %s [-lRfF] [-r rev] [-D date] [files...]\n",
+     "\t-l\tLocal directory only, no recursion.\n",
+     "\t-R\tProcess directories recursively.\n",
+     "\t-f\tUse head revision if tag/date not found.\n",
+     "\t-F\tAnnotate binary files.\n",
+     "\t-r rev\tAnnotate file as of specified revision/tag.\n",
+     "\t-D date\tAnnotate file as of specified date.\n",
+     "\t-M mrev\tUse a revision or tag of the modules file for expansion.\n",
+     "(Specify the --help global option for a list of other help options)\n",
+     NULL
+ };
+ 
  static const char *const annotate_usage[] =
  {
      "Usage: %s %s [-lRfF] [-r rev] [-D date] [files...]\n",
*************** annotate (int argc, char **argv)
*** 51,64 ****
      int local = 0;
      int err = 0;
      int c;
  
      is_rannotate = (strcmp(cvs_cmd_name, "rannotate") == 0);
  
      if (argc == -1)
!       usage (annotate_usage);
  
      optind = 0;
!     while ((c = getopt (argc, argv, "+lr:D:fFR")) != -1)
      {
        switch (c)
        {
--- 65,93 ----
      int local = 0;
      int err = 0;
      int c;
+     char *valid_options;
+     const char *const *valid_usage;
+     /* What tag will be used to look at the modules file, if any? */
+     const char *modules_tag = NULL;
  
      is_rannotate = (strcmp(cvs_cmd_name, "rannotate") == 0);
  
+     if (is_rannotate)
+     {
+         valid_options = "+lr:D:fFRM:";
+         valid_usage = rannotate_usage;
+     }
+     else
+     {
+         valid_options = "+lr:D:fFR";
+         valid_usage = annotate_usage;
+     }
+         
      if (argc == -1)
!       usage (valid_usage);
  
      optind = 0;
!     while ((c = getopt (argc, argv, valid_options)) != -1)
      {
        switch (c)
        {
*************** annotate (int argc, char **argv)
*** 80,88 ****
            case 'F':
                force_binary = 1;
                break;
            case '?':
            default:
!               usage (annotate_usage);
                break;
        }
      }
--- 109,120 ----
            case 'F':
                force_binary = 1;
                break;
+             case 'M':
+                 modules_tag = optarg;
+                 break;
            case '?':
            default:
!               usage (valid_usage);
                break;
        }
      }
*************** annotate (int argc, char **argv)
*** 106,111 ****
--- 138,146 ----
        if (force_binary)
            send_arg ("-F");
        option_with_arg ("-r", tag);
+         /* Pass the modules_tag if needed.  */
+         if (modules_tag != NULL)
+             option_with_arg ("-M", modules_tag);
        if (date)
            client_senddate (date);
        send_arg ("--");
*************** annotate (int argc, char **argv)
*** 130,136 ****
      {
        DBM *db;
        int i;
!       db = open_module ();
        for (i = 0; i < argc; i++)
        {
            err += do_module (db, argv[i], MISC, "Annotating", rannotate_proc,
--- 165,171 ----
      {
        DBM *db;
        int i;
!       db = open_module (modules_tag);
        for (i = 0; i < argc; i++)
        {
            err += do_module (db, argv[i], MISC, "Annotating", rannotate_proc,
diff -rp cvs-1.12.9/src/checkout.c 
cvs-1.12.9-versioned-modules-only/src/checkout.c
*** cvs-1.12.9/src/checkout.c   Mon Mar 22 11:37:34 2004
--- cvs-1.12.9-versioned-modules-only/src/checkout.c    Fri Aug 27 11:08:23 2004
*************** static const char *const checkout_usage[
*** 60,65 ****
--- 60,66 ----
      "\t-d dir\tCheck out into dir instead of module name.\n",
      "\t-k kopt\tUse RCS kopt -k option on checkout. (is sticky)\n",
      "\t-j rev\tMerge in changes made between current revision and rev.\n",
+     "\t-M mrev\tUse a revision or tag of the modules file for expansion.\n",
      "(Specify the --help global option for a list of other help options)\n",
      NULL
  };
*************** static const char *const export_usage[] 
*** 76,81 ****
--- 77,83 ----
      "\t-D date\tExport revisions as of date.\n",
      "\t-d dir\tExport into dir instead of module name.\n",
      "\t-k kopt\tUse RCS kopt -k option on checkout.\n",
+     "\t-M mrev\tUse a revision or tag of the modules file for expansion.\n",
      "(Specify the --help global option for a list of other help options)\n",
      NULL
  };
*************** checkout (int argc, char **argv)
*** 108,113 ****
--- 110,117 ----
      char *where = NULL;
      char *valid_options;
      const char *const *valid_usage;
+     /* What tag will be used to look at the modules file, if any? */
+     const char *modules_tag = NULL;
  
      /* initialize static options */
      force_tag_match = 1;
*************** checkout (int argc, char **argv)
*** 130,142 ****
      if (strcmp (cvs_cmd_name, "export") == 0)
      {
          m_type = EXPORT;
!       valid_options = "+Nnk:d:flRQqr:D:";
        valid_usage = export_usage;
      }
      else
      {
          m_type = CHECKOUT;
!       valid_options = "+ANnk:d:flRpQqcsr:D:j:P";
        valid_usage = checkout_usage;
      }
  
--- 134,146 ----
      if (strcmp (cvs_cmd_name, "export") == 0)
      {
          m_type = EXPORT;
!       valid_options = "+Nnk:d:flRQqr:D:M:";
        valid_usage = export_usage;
      }
      else
      {
          m_type = CHECKOUT;
!       valid_options = "+ANnk:d:flRpQqcsr:D:j:PM:";
        valid_usage = checkout_usage;
      }
  
*************** checkout (int argc, char **argv)
*** 208,213 ****
--- 212,220 ----
                tag = optarg;
                checkout_prune_dirs = 1;
                break;
+             case 'M':
+                 modules_tag = optarg;
+                 break;
            case 'D':
                date = Make_Date (optarg);
                checkout_prune_dirs = 1;
*************** checkout (int argc, char **argv)
*** 277,285 ****
        {
            /* This is done here because we need to read responses
                 from the server before we send the command checkout or
!                export files. */
  
!           client_expand_modules (argc, argv, local);
        }
  
        if (!run_module_prog)
--- 284,293 ----
        {
            /* This is done here because we need to read responses
                 from the server before we send the command checkout or
!                export files.  We need to send the modules_tag along
!                if it is set. */
  
!           client_expand_modules (argc, argv, local, modules_tag);
        }
  
        if (!run_module_prog)
*************** checkout (int argc, char **argv)
*** 312,317 ****
--- 320,328 ----
            option_with_arg ("-j", join_rev1);
        if (join_rev2 != NULL)
            option_with_arg ("-j", join_rev2);
+         /* Pass the modules_tag if needed.  */
+         if (modules_tag != NULL)
+             option_with_arg ("-M", modules_tag);
        send_arg ("--");
  
        if (expand_modules)
*************** checkout (int argc, char **argv)
*** 333,339 ****
  
      if (cat)
      {
!       cat_module (status);
        if (options)
        {
            free (options);
--- 344,350 ----
  
      if (cat)
      {
!       cat_module (status, modules_tag);
        if (options)
        {
            free (options);
*************** checkout (int argc, char **argv)
*** 341,347 ****
        }
        return (0);
      }
!     db = open_module ();
  
  
      /* If we've specified something like "cvs co foo/bar baz/quux"
--- 352,358 ----
        }
        return (0);
      }
!     db = open_module (modules_tag);
  
  
      /* If we've specified something like "cvs co foo/bar baz/quux"
diff -rp cvs-1.12.9/src/client.c cvs-1.12.9-versioned-modules-only/src/client.c
*** cvs-1.12.9/src/client.c     Wed May 19 18:39:47 2004
--- cvs-1.12.9-versioned-modules-only/src/client.c      Fri Aug 27 11:12:30 2004
*************** static int module_argc;
*** 2454,2460 ****
  static char **module_argv;
  
  void
! client_expand_modules( int argc, char **argv, int local )
  {
      int errs;
      int i;
--- 2454,2461 ----
  static char **module_argv;
  
  void
! client_expand_modules( int argc, char **argv, int local,
!                        const char *modules_tag )
  {
      int errs;
      int i;
*************** client_expand_modules( int argc, char **
*** 2469,2475 ****
        send_arg (argv[i]);
      send_a_repository ("", current_parsed_root->directory, "");
  
!     send_to_server ("expand-modules\012", 0);
  
      errs = get_server_responses ();
      if (last_repos != NULL)
--- 2470,2482 ----
        send_arg (argv[i]);
      send_a_repository ("", current_parsed_root->directory, "");
  
!     send_to_server ("expand-modules", 0);
!     if (modules_tag != NULL)
!     {
!         send_to_server(" ", 1);
!         send_to_server(modules_tag, 0);
!     }
!     send_to_server("\012", 1);
  
      errs = get_server_responses ();
      if (last_repos != NULL)
*************** start_server (void)
*** 3903,3912 ****
  
  /* Send an argument STRING.  */
  void
! send_arg (char *string)
  {
      char buf[1];
!     char *p = string;
  
      send_to_server ("Argument ", 0);
  
--- 3910,3919 ----
  
  /* Send an argument STRING.  */
  void
! send_arg (const char *string)
  {
      char buf[1];
!     const char *p = string;
  
      send_to_server ("Argument ", 0);
  
*************** client_notify (const char *repository, c
*** 4901,4907 ****
   * the argument.  If ARG is NULL, forget the whole thing.
   */
  void
! option_with_arg (char *option, char *arg)
  {
      if (arg == NULL)
        return;
--- 4908,4914 ----
   * the argument.  If ARG is NULL, forget the whole thing.
   */
  void
! option_with_arg (const char *option, const char *arg)
  {
      if (arg == NULL)
        return;
diff -rp cvs-1.12.9/src/client.h cvs-1.12.9-versioned-modules-only/src/client.h
*** cvs-1.12.9/src/client.h     Tue Apr  6 22:12:30 2004
--- cvs-1.12.9-versioned-modules-only/src/client.h      Fri Aug 27 11:30:45 2004
*************** void read_from_server (char *buf, size_t
*** 73,79 ****
  
  /* Internal functions that handle client communication to server, etc.  */
  int supported_request (char *);
! void option_with_arg (char *option, char *arg);
  
  /* Get the responses and then close the connection.  */
  extern int get_responses_and_close (void);
--- 73,79 ----
  
  /* Internal functions that handle client communication to server, etc.  */
  int supported_request (char *);
! void option_with_arg (const char *option, const char *arg);
  
  /* Get the responses and then close the connection.  */
  extern int get_responses_and_close (void);
*************** send_files (int argc, char **argv, int l
*** 109,115 ****
  
  /* Send an argument to the remote server.  */
  void
! send_arg (char *string);
  
  /* Send a string of single-char options to the remote server, one by one.  */
  void
--- 109,115 ----
  
  /* Send an argument to the remote server.  */
  void
! send_arg (const char *string);
  
  /* Send a string of single-char options to the remote server, one by one.  */
  void
*************** extern struct response responses[];
*** 177,183 ****
  #ifdef CLIENT_SUPPORT
  
  extern void client_senddate (const char *date);
! extern void client_expand_modules (int argc, char **argv, int local);
  extern void client_send_expansions (int local, char *where,
                                          int build_dirs);
  extern void client_nonexpanded_setup (void);
--- 177,184 ----
  #ifdef CLIENT_SUPPORT
  
  extern void client_senddate (const char *date);
! extern void client_expand_modules (int argc, char **argv, int local,
!                                    const char *modules_tag);
  extern void client_send_expansions (int local, char *where,
                                          int build_dirs);
  extern void client_nonexpanded_setup (void);
diff -rp cvs-1.12.9/src/cvs.h cvs-1.12.9-versioned-modules-only/src/cvs.h
*** cvs-1.12.9/src/cvs.h        Wed Jun  9 11:52:38 2004
--- cvs-1.12.9-versioned-modules-only/src/cvs.h Fri Aug 27 11:14:10 2004
*************** int diff_exec (const char *file1, const 
*** 417,423 ****
  
  #include "error.h"
  
! DBM *open_module (void);
  FILE *open_file (const char *, const char *);
  List *Find_Directories (char *repository, int which, List *entries);
  void Entries_Close (List *entries);
--- 417,423 ----
  
  #include "error.h"
  
! DBM *open_module (const char *tag);
  FILE *open_file (const char *, const char *);
  List *Find_Directories (char *repository, int which, List *entries);
  void Entries_Close (List *entries);
*************** void WriteTag (const char *dir, const ch
*** 578,584 ****
                 int nonbranch, const char *update_dir, const char *repository);
  void WriteTemplate (const char *update_dir, int dotemplate,
                      const char *repository);
! void cat_module (int status);
  void check_entries (char *dir);
  void close_module (DBM * db);
  void copy_file (const char *from, const char *to);
--- 578,584 ----
                 int nonbranch, const char *update_dir, const char *repository);
  void WriteTemplate (const char *update_dir, int dotemplate,
                      const char *repository);
! void cat_module (int status, const char *tag);
  void check_entries (char *dir);
  void close_module (DBM * db);
  void copy_file (const char *from, const char *to);
diff -rp cvs-1.12.9/src/log.c cvs-1.12.9-versioned-modules-only/src/log.c
*** cvs-1.12.9/src/log.c        Wed May 19 18:39:47 2004
--- cvs-1.12.9-versioned-modules-only/src/log.c Fri Aug 27 11:08:24 2004
*************** static int version_compare (const char *
*** 143,148 ****
--- 143,178 ----
  static struct log_data log_data;
  static int is_rlog;
  
+ static const char *const rlog_usage[] =
+ {
+     "Usage: %s %s [-lRhtNb] [-r[revisions]] [-d dates] [-s states]\n",
+     "    [-w[logins]] [files...]\n",
+     "\t-l\tLocal directory only, no recursion.\n",
+     "\t-R\tOnly print name of RCS file.\n",
+     "\t-h\tOnly print header.\n",
+     "\t-t\tOnly print header and descriptive text.\n",
+     "\t-N\tDo not list tags.\n",
+     "\t-S\tDo not print name/header if no revisions selected.\n",
+     "\t-b\tOnly list revisions on the default branch.\n",
+     "\t-r[revisions]\tA comma-separated list of revisions to print:\n",
+     "\t   rev1:rev2   Between rev1 and rev2, including rev1 and rev2.\n",
+     "\t   rev1::rev2  Between rev1 and rev2, excluding rev1.\n",
+     "\t   rev:        rev and following revisions on the same branch.\n",
+     "\t   rev::       After rev on the same branch.\n",
+     "\t   :rev        rev and previous revisions on the same branch.\n",
+     "\t   ::rev       rev and previous revisions on the same branch.\n",
+     "\t   rev         Just rev.\n",
+     "\t   branch      All revisions on the branch.\n",
+     "\t   branch.     The last revision on the branch.\n",
+     "\t-d dates\tA semicolon-separated list of dates\n",
+     "\t        \t(D1<D2 for range, D for latest before).\n",
+     "\t-s states\tOnly list revisions with specified states.\n",
+     "\t-w[logins]\tOnly list revisions checked in by specified logins.\n",
+     "\t-M mrev\tUse a revision or tag of the modules file for expansion.\n",
+     "(Specify the --help global option for a list of other help options)\n",
+     NULL
+ };
+ 
  static const char *const log_usage[] =
  {
      "Usage: %s %s [-lRhtNb] [-r[revisions]] [-d dates] [-s states]\n",
*************** static const char *const log_usage[] =
*** 168,173 ****
--- 198,204 ----
      "\t        \t(D1<D2 for range, D for latest before).\n",
      "\t-s states\tOnly list revisions with specified states.\n",
      "\t-w[logins]\tOnly list revisions checked in by specified logins.\n",
+     "\t-M mrev\tUse a revision or tag of the modules file for expansion.\n",
      "(Specify the --help global option for a list of other help options)\n",
      NULL
  };
*************** cvslog (int argc, char **argv)
*** 218,234 ****
      int err = 0;
      int local = 0;
      struct option_revlist **prl;
  
      is_rlog = (strcmp (cvs_cmd_name, "rlog") == 0);
  
      if (argc == -1)
!       usage (log_usage);
  
      memset (&log_data, 0, sizeof log_data);
      prl = &log_data.revlist;
  
      optind = 0;
!     while ((c = getopt (argc, argv, "+bd:hlNSRr::s:tw::")) != -1)
      {
        switch (c)
        {
--- 249,280 ----
      int err = 0;
      int local = 0;
      struct option_revlist **prl;
+     char *valid_options;
+     const char *const *valid_usage;
+     /* What tag will be used to look at the modules file, if any? */
+     const char *modules_tag = NULL;
  
      is_rlog = (strcmp (cvs_cmd_name, "rlog") == 0);
  
+     if (is_rlog)
+     {
+         valid_options = "+bd:M:hlNSRr::s:tw::";
+         valid_usage = rlog_usage;
+     }
+     else
+     {
+         valid_options = "+bd:hlNSRr::s:tw::";
+         valid_usage = log_usage;
+     }
+ 
      if (argc == -1)
!       usage (valid_usage);
  
      memset (&log_data, 0, sizeof log_data);
      prl = &log_data.revlist;
  
      optind = 0;
!     while ((c = getopt (argc, argv, valid_options)) != -1)
      {
        switch (c)
        {
*************** cvslog (int argc, char **argv)
*** 269,274 ****
--- 315,323 ----
                else
                    log_parse_list (&log_data.authorlist, "@@MYSELF");
                break;
+             case 'M':
+                 modules_tag = optarg;
+                 break;
            case '?':
            default:
                usage (log_usage);
*************** cvslog (int argc, char **argv)
*** 345,350 ****
--- 394,402 ----
            send_arg("-R");
        if (log_data.long_header)
            send_arg("-t");
+         /* Pass the modules_tag if needed.  */
+         if (modules_tag != NULL)
+             option_with_arg ("-M", modules_tag);
  
        while (log_data.revlist != NULL)
        {
*************** cvslog (int argc, char **argv)
*** 407,413 ****
      {
        DBM *db;
        int i;
!       db = open_module ();
        for (i = 0; i < argc; i++)
        {
               err += do_module (db, argv[i], MISC, "Logging", rlog_proc,
--- 459,465 ----
      {
        DBM *db;
        int i;
!       db = open_module (modules_tag);
        for (i = 0; i < argc; i++)
        {
               err += do_module (db, argv[i], MISC, "Logging", rlog_proc,
diff -rp cvs-1.12.9/src/ls.c cvs-1.12.9-versioned-modules-only/src/ls.c
*** cvs-1.12.9/src/ls.c Thu May 20 00:00:43 2004
--- cvs-1.12.9-versioned-modules-only/src/ls.c  Fri Aug 27 12:01:27 2004
*************** static int ls_proc (int argc, char **arg
*** 19,24 ****
--- 19,39 ----
  
  static RCSNode *xrcsnode;
  
+ static const char *const rls_usage[] =
+ {
+     "Usage: %s %s [-e | -l] [-RP] [-r rev] [-D date] [path...]\n",
+     "\t-d\tShow dead revisions (with tag when specified).\n",
+     "\t-e\tDisplay in CVS/Entries format.\n",
+     "\t-l\tDisplay all details.\n",
+     "\t-P\tPrune empty directories.\n",
+     "\t-R\tList recursively.\n",
+     "\t-r rev\tShow files with revision or tag.\n",
+     "\t-D date\tShow files from date.\n",
+     "\t-M mrev\tUse a revision or tag of the modules file for expansion.\n",
+     "(Specify the --help global option for a list of other help options)\n",
+     NULL
+ };
+ 
  static const char *const ls_usage[] =
  {
      "Usage: %s %s [-e | -l] [-RP] [-r rev] [-D date] [path...]\n",
*************** ls (int argc, char **argv)
*** 53,63 ****
  {
      int c;
      int err = 0;
  
      is_rls = strcmp (cvs_cmd_name, "rls") == 0;
  
      if (argc == -1)
!       usage (ls_usage);
  
      entries_format = false;
      long_format = false;
--- 68,101 ----
  {
      int c;
      int err = 0;
+     char *valid_options;
+     const char *const *valid_usage;
+     /* What tag will be used to look at the modules file, if any? */
+     const char *modules_tag = NULL;
  
      is_rls = strcmp (cvs_cmd_name, "rls") == 0;
  
+     if (is_rls)
+     {
+         valid_options =
+ #ifdef SERVER_SUPPORT
+             server_active ? "qdelr:D:PRM:" :
+ #endif /* SERVER_SUPPORT */
+             "delr:D:PRM:";
+         valid_usage = rls_usage;
+     }
+     else
+     {
+         valid_options =
+ #ifdef SERVER_SUPPORT
+             server_active ? "qdelr:D:PR" :
+ #endif /* SERVER_SUPPORT */
+             "delr:D:PR";
+         valid_usage = ls_usage;
+     }
+ 
      if (argc == -1)
!       usage (valid_usage);
  
      entries_format = false;
      long_format = false;
*************** ls (int argc, char **argv)
*** 70,81 ****
  
      optind = 0;
  
!     while ((c = getopt (argc, argv,
! #ifdef SERVER_SUPPORT
!            server_active ? "qdelr:D:PR" :
! #endif /* SERVER_SUPPORT */
!            "delr:D:RP"
!            )) != -1)
      {
        switch (c)
        {
--- 108,114 ----
  
      optind = 0;
  
!     while ((c = getopt (argc, argv, valid_options)) != -1)
      {
        switch (c)
        {
*************** ls (int argc, char **argv)
*** 89,95 ****
                    quiet = true;
                }
                else
!                   usage (ls_usage);
                break;
  #endif /* SERVER_SUPPORT */
            case 'd':
--- 122,128 ----
                    quiet = true;
                }
                else
!                   usage (valid_usage);
                break;
  #endif /* SERVER_SUPPORT */
            case 'd':
*************** ls (int argc, char **argv)
*** 113,121 ****
            case 'R':
                recurse = true;
                break;
            case '?':
            default:
!               usage (ls_usage);
                break;
        }
      }
--- 146,157 ----
            case 'R':
                recurse = true;
                break;
+             case 'M':
+                 modules_tag = optarg;
+                 break;
            case '?':
            default:
!               usage (valid_usage);
                break;
        }
      }
*************** ls (int argc, char **argv)
*** 125,131 ****
      if (entries_format && long_format)
      {
          error (0, 0, "`-e' & `-l' are mutually exclusive.");
!         usage (ls_usage);
      }
  
      wrap_setup ();
--- 161,167 ----
      if (entries_format && long_format)
      {
          error (0, 0, "`-e' & `-l' are mutually exclusive.");
!         usage (valid_usage);
      }
  
      wrap_setup ();
*************** ls (int argc, char **argv)
*** 158,163 ****
--- 194,202 ----
            option_with_arg ("-r", show_tag);
        if (show_date)
            client_senddate (show_date);
+         /* Pass the modules_tag if needed.  */
+         if (modules_tag != NULL)
+             option_with_arg ("-M", modules_tag);
  
        send_arg ("--");
  
*************** ls (int argc, char **argv)
*** 199,205 ****
      {
        DBM *db;
        int i;
!       db = open_module ();
        if (argc)
        {
            for (i = 0; i < argc; i++)
--- 238,244 ----
      {
        DBM *db;
        int i;
!       db = open_module (modules_tag);
        if (argc)
        {
            for (i = 0; i < argc; i++)
diff -rp cvs-1.12.9/src/modules.c 
cvs-1.12.9-versioned-modules-only/src/modules.c
*** cvs-1.12.9/src/modules.c    Sun Apr 11 11:59:22 2004
--- cvs-1.12.9-versioned-modules-only/src/modules.c     Fri Aug 27 11:22:55 2004
*************** static void save_d (char *k, int ks, cha
*** 58,81 ****
   * Open the modules file, and die if the CVSROOT environment variable
   * was not set.  If the modules file does not exist, that's fine, and
   * a warning message is displayed and a NULL is returned.
   */
  DBM *
! open_module (void)
  {
      char *mfile;
      DBM *retval;
  
      if (current_parsed_root == NULL)
      {
        error (0, 0, "must set the CVSROOT environment variable");
        error (1, 0, "or specify the '-d' global option");
      }
!     mfile = xmalloc (strlen (current_parsed_root->directory)
!                    + sizeof (CVSROOTADM)
!                    + sizeof (CVSROOTADM_MODULES) + 3);
!     (void) sprintf (mfile, "%s/%s/%s", current_parsed_root->directory,
!                   CVSROOTADM, CVSROOTADM_MODULES);
      retval = dbm_open (mfile, O_RDONLY, 0666);
      free (mfile);
      return retval;
  }
--- 58,176 ----
   * Open the modules file, and die if the CVSROOT environment variable
   * was not set.  If the modules file does not exist, that's fine, and
   * a warning message is displayed and a NULL is returned.
+  * If tag is not NULL, then we use the tag or revision specified by tag to
+  * checkout the modules file before reading it.  This allows versioned
+  * modules. 
   */
  DBM *
! open_module (const char *tag)
  {
      char *mfile;
      DBM *retval;
  
+     if(trace)
+     {
+         cvs_outerr(CLIENT_SERVER_STR, 0);
+         cvs_outerr("-> open_module(", 0);
+         cvs_outerr((tag == NULL ? "NULL" : tag), 0);
+         cvs_outerr(")\n", 0);
+     }
+ 
      if (current_parsed_root == NULL)
      {
        error (0, 0, "must set the CVSROOT environment variable");
        error (1, 0, "or specify the '-d' global option");
      }
! 
!     /* Need a special tagged version of the modules file? */
!     if (tag == NULL)
!     {
!         mfile = xmalloc (strlen (current_parsed_root->directory)
!                        + sizeof (CVSROOTADM)
!                        + sizeof (CVSROOTADM_MODULES) + 3);
!         (void) sprintf (mfile, "%s/%s/%s", current_parsed_root->directory,
!                       CVSROOTADM, CVSROOTADM_MODULES);
!     }
!     else
!     {
!         /* Where is the repository?
!          * What's a modifiable version of the tag?
!          */
!         char *repository = xmalloc (strlen (current_parsed_root->directory)
!                                     + sizeof(CVSROOTADM) + 2);
!         char *mutable_tag = xstrdup (tag);
!         char *rev;
!         RCSNode *rcs;
! 
!         sprintf (repository, "%s/%s", current_parsed_root->directory,
!                  CVSROOTADM);
! 
!         /* Build the string we'll gfive to dbm_open */
!         mfile = xmalloc (strlen (Tmpdir) + sizeof (CVSROOTADM_MODULES)
!                          + 1 + 1 + 17 + 1);
!         sprintf (mfile, "%s/%s.%ld", Tmpdir, CVSROOTADM_MODULES,
!                  getpid());
! 
!         if(trace)
!         {
!             cvs_outerr(CLIENT_SERVER_STR, 0);
!             cvs_outerr("-> RCS checkout of modules file from `", 0);
!             cvs_outerr(repository, 0);
!             cvs_outerr("' to '", 0);
!             cvs_outerr(mfile, 0);
!             cvs_outerr("'\n", 0);
!         }
! 
!         /* Parse the RCS file that is the modules file */
!         rcs = RCS_parse (CVSROOTADM_MODULES, repository);
! 
!         if(rcs == NULL)
!         {
!             error (1, 0, "cannot parse modules RCS file");
!         }
!         free (repository);
! 
!         /* Turn the tag into an RCS revision */
!         rev = RCS_gettag(rcs, mutable_tag, 1, (int *) NULL);
!         if(rev == NULL)
!         {
!             error (1, 0, "no version '%s' in modules file", tag);
!         }
! 
!         if(trace)
!         {
!             cvs_outerr(CLIENT_SERVER_STR, 0);
!             cvs_outerr("-> Resolved modules file tag '", 0);
!             cvs_outerr(tag, 0);
!             cvs_outerr("' to '", 0);
!             cvs_outerr(rev, 0);
!             cvs_outerr("'\n", 0);
!         }
! 
!         /* Check the modules RCS file out into a temporary file */
!         if(RCS_checkout (rcs, mfile, rev, mutable_tag,
!                          NULL, RUN_TTY, NULL, NULL) != 0)
!         {
!             /* Can't do this */
!             error (1, 0, "cannot checkout modules file with specified tag");
!         }
!         /* Don't free the RCSNode because I don't know if you should */
!         free (rev);
!         free (mutable_tag);
!     }
! 
!     /* Open the database */
      retval = dbm_open (mfile, O_RDONLY, 0666);
+ 
+     /* Unlink the temporary file now.  Even if it's not done being read, it'll
+      * go away when it's closed.
+      */
+     if(tag != NULL && unlink_file (mfile) < 0)
+     {
+         error (0, 0, "cannot unlink temporary file `%s'", mfile);
+     }
+ 
+     /* Either way, free the temporary filename */
      free (mfile);
      return retval;
  }
*************** save_d (char *k, int ks, char *d, int ds
*** 900,906 ****
     non-zero, print out status information for each module. */
  
  void
! cat_module (int status)
  {
      DBM *db;
      datum key, val;
--- 995,1001 ----
     non-zero, print out status information for each module. */
  
  void
! cat_module (int status, const char*tag)
  {
      DBM *db;
      datum key, val;
*************** cat_module (int status)
*** 913,919 ****
      Status = status;
  
      /* Read the whole modules file into allocated records */
!     if (!(db = open_module ()))
        error (1, 0, "failed to open the modules file");
  
      for (key = dbm_firstkey (db); key.dptr != NULL; key = dbm_nextkey (db))
--- 1008,1014 ----
      Status = status;
  
      /* Read the whole modules file into allocated records */
!     if (!(db = open_module (tag)))
        error (1, 0, "failed to open the modules file");
  
      for (key = dbm_firstkey (db); key.dptr != NULL; key = dbm_nextkey (db))
diff -rp cvs-1.12.9/src/patch.c cvs-1.12.9-versioned-modules-only/src/patch.c
*** cvs-1.12.9/src/patch.c      Fri Apr  2 15:56:22 2004
--- cvs-1.12.9-versioned-modules-only/src/patch.c       Fri Aug 27 11:08:24 2004
*************** static const char *const patch_usage[] =
*** 53,58 ****
--- 53,59 ----
      "\t-D date\tDate.\n",
      "\t-r rev\tRevision - symbolic or numeric.\n",
      "\t-V vers\tUse RCS Version \"vers\" for keyword expansion.\n",
+     "\t-M mrev\tUse a revision or tag of the modules file for expansion.\n",
      "(Specify the --help global option for a list of other help options)\n",
      NULL
  };
*************** patch (int argc, char **argv)
*** 67,78 ****
      int c;
      int err = 0;
      DBM *db;
  
      if (argc == -1)
        usage (patch_usage);
  
      optind = 0;
!     while ((c = getopt (argc, argv, "+V:k:cuftsQqlRD:r:")) != -1)
      {
        switch (c)
        {
--- 68,81 ----
      int c;
      int err = 0;
      DBM *db;
+     /* What tag will be used to look at the modules file, if any? */
+     const char *modules_tag = NULL;
  
      if (argc == -1)
        usage (patch_usage);
  
      optind = 0;
!     while ((c = getopt (argc, argv, "+V:k:cuftsQqlRD:r:M:")) != -1)
      {
        switch (c)
        {
*************** patch (int argc, char **argv)
*** 158,163 ****
--- 161,169 ----
            case 'c':                   /* Context diff */
                unidiff = 0;
                break;
+             case 'M':
+                 modules_tag = optarg;
+                 break;
            case '?':
            default:
                usage (patch_usage);
*************** patch (int argc, char **argv)
*** 217,222 ****
--- 223,231 ----
            client_senddate (date2);
        if (options[0] != '\0')
            send_arg (options);
+         /* Pass the modules_tag if needed.  */
+         if (modules_tag != NULL)
+             option_with_arg ("-M", modules_tag);
  
        {
            int i;
*************** patch (int argc, char **argv)
*** 249,255 ****
      (void)SIG_register (SIGTERM, patch_cleanup);
  #endif
  
!     db = open_module ();
      for (i = 0; i < argc; i++)
        err += do_module (db, argv[i], PATCH, "Patching", patch_proc,
                          (char *)NULL, 0, local, 0, 0, (char *)NULL);
--- 258,264 ----
      (void)SIG_register (SIGTERM, patch_cleanup);
  #endif
  
!     db = open_module (modules_tag);
      for (i = 0; i < argc; i++)
        err += do_module (db, argv[i], PATCH, "Patching", patch_proc,
                          (char *)NULL, 0, local, 0, 0, (char *)NULL);
diff -rp cvs-1.12.9/src/server.c cvs-1.12.9-versioned-modules-only/src/server.c
*** cvs-1.12.9/src/server.c     Wed Jun  9 11:52:39 2004
--- cvs-1.12.9-versioned-modules-only/src/server.c      Fri Aug 27 11:08:24 2004
*************** serve_expand_modules (char *arg)
*** 4664,4671 ****
      int err;
      DBM *db;
      err = 0;
  
-     db = open_module ();
      for (i = 1; i < argument_count; i++)
        err += do_module (db, argument_vector[i],
                          CHECKOUT, "Updating", expand_proc,
--- 4664,4678 ----
      int err;
      DBM *db;
      err = 0;
+     int c;
+ 
+     const char* module_tag = NULL;
+ 
+     if (strlen(arg) > 0)
+       module_tag = arg;
+ 
+     db = open_module (module_tag);
  
      for (i = 1; i < argument_count; i++)
        err += do_module (db, argument_vector[i],
                          CHECKOUT, "Updating", expand_proc,
diff -rp cvs-1.12.9/src/tag.c cvs-1.12.9-versioned-modules-only/src/tag.c
*** cvs-1.12.9/src/tag.c        Fri Apr 30 11:11:49 2004
--- cvs-1.12.9-versioned-modules-only/src/tag.c Fri Aug 27 11:15:54 2004
*************** struct master_lists
*** 64,70 ****
  
  static List *mtlist;
  
! static const char rtag_opts[] = "+aBbdFflnQqRr:D:";
  static const char *const rtag_usage[] =
  {
      "Usage: %s %s [-abdFflnR] [-r rev|-D date] tag modules...\n",
--- 64,70 ----
  
  static List *mtlist;
  
! static const char rtag_opts[] = "+aBbdFflnQqRr:D:M:";
  static const char *const rtag_usage[] =
  {
      "Usage: %s %s [-abdFflnR] [-r rev|-D date] tag modules...\n",
*************** static const char *const rtag_usage[] =
*** 79,84 ****
--- 79,85 ----
      "\t-R\tProcess directories recursively.\n",
      "\t-r rev\tExisting revision/tag.\n",
      "\t-D\tExisting date.\n",
+     "\t-M mrev\tUse a revision or tag of the modules file for expansion.\n",
      "(Specify the --help global option for a list of other help options)\n",
      NULL
  };
*************** cvstag (int argc, char **argv)
*** 110,115 ****
--- 111,118 ----
      int c;
      int err = 0;
      bool run_module_prog = true;
+     /* What tag will be used to look at the modules file, if any? */
+     const char *modules_tag = NULL;
  
      is_rtag = (strcmp (cvs_cmd_name, "rtag") == 0);
  
*************** cvstag (int argc, char **argv)
*** 170,175 ****
--- 173,181 ----
                      free (date);
                  date = Make_Date (optarg);
                  break;
+             case 'M':
+                 modules_tag = optarg;
+                 break;
            case '?':
            default:
                usage (is_rtag ? rtag_usage : tag_usage);
*************** cvstag (int argc, char **argv)
*** 217,222 ****
--- 223,231 ----
            send_arg ("-l");
        if (!run_module_prog)
            send_arg ("-n");
+         /* Pass the modules_tag if needed. */
+         if (modules_tag != NULL)
+             option_with_arg ("-M", modules_tag);
  
        if (numtag)
            option_with_arg ("-r", numtag);
*************** cvstag (int argc, char **argv)
*** 254,260 ****
      {
        DBM *db;
        int i;
!       db = open_module ();
        for (i = 0; i < argc; i++)
        {
            /* XXX last arg should be repository, but doesn't make sense here */
--- 263,269 ----
      {
        DBM *db;
        int i;
!       db = open_module (modules_tag);
        for (i = 0; i < argc; i++)
        {
            /* XXX last arg should be repository, but doesn't make sense here */

reply via email to

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