home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / cvs-1.8.7-src.tgz / tar.out / fsf / cvs / src / rcscmds.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  7KB  |  209 lines

  1. /*
  2.  * Copyright (c) 1992, Brian Berliner and Jeff Polk
  3.  * Copyright (c) 1989-1992, Brian Berliner
  4.  * 
  5.  * You may distribute under the terms of the GNU General Public License as
  6.  * specified in the README file that comes with the CVS 1.4 kit.
  7.  * 
  8.  * The functions in this file provide an interface for performing 
  9.  * operations directly on RCS files. 
  10.  */
  11.  
  12. #include "cvs.h"
  13. #include <assert.h>
  14.  
  15. /* This file, rcs.h, and rcs.c, are intended to define our interface
  16.    to RCS files.  As of July, 1996, there are still a few places that
  17.    still exec RCS commands directly.  The intended long-term direction
  18.    is to have CVS access RCS files directly, for performance,
  19.    cleanliness (CVS has some awful hacks to work around RCS behaviors
  20.    which don't make sense for CVS), installation hassles, ease of
  21.    implementing the CVS server (I don't think that the
  22.    output-out-of-order bug can be completely fixed as long as CVS
  23.    calls RCS), and perhaps other reasons.
  24.  
  25.    It is often suggested that this should be a common library shared
  26.    between RCS and CVS.  It is not clear that this is the most natural
  27.    way (at least for the first-cut implementation).  Some
  28.    considerations:
  29.  
  30.    1.  CVS already has data structures and a fair bit of code dedicated
  31.    to handling RCS files.
  32.  
  33.    2.  The existing RCS code can be hard to understand.  Too few
  34.    comments and too many layers of abstraction.  I don't know whether it
  35.    gets better if you know the code better.
  36.  
  37.    3.  CVS does not need all the functionality of RCS.  */
  38.  
  39. /* For RCS file PATH, make symbolic tag TAG point to revision REV.
  40.    This validates that TAG is OK for a user to use.  Return value is
  41.    -1 for error (and errno is set to indicate the error), positive for
  42.    error (and an error message has been printed), or zero for success.  */
  43.  
  44. int
  45. RCS_settag(path, tag, rev)
  46.     const char *path;
  47.     const char *tag;
  48.     const char *rev;
  49. {
  50.     /* FIXME: This check should be moved to RCS_check_tag.  There is no
  51.        reason for it to be here.  */
  52.     if (strcmp (tag, TAG_BASE) == 0
  53.     || strcmp (tag, TAG_HEAD) == 0)
  54.     {
  55.     /* Print the name of the tag might be considered redundant
  56.        with the caller, which also prints it.  Perhaps this helps
  57.        clarify why the tag name is considered reserved, I don't
  58.        know.  */
  59.     error (0, 0, "Attempt to add reserved tag name %s", tag);
  60.     return 1;
  61.     }
  62.  
  63.     run_setup ("%s%s -x,v/ -q -N%s:%s", Rcsbin, RCS, tag, rev);
  64.     run_arg (path);
  65.     return run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
  66. }
  67.  
  68. /* NOERR is 1 to suppress errors--FIXME it would
  69.    be better to avoid the errors or some cleaner solution.  */
  70. int
  71. RCS_deltag(path, tag, noerr)
  72.     const char *path;
  73.     const char *tag;
  74.     int noerr;
  75. {
  76.     run_setup ("%s%s -x,v/ -q -N%s", Rcsbin, RCS, tag);
  77.     run_arg (path);
  78.     return run_exec (RUN_TTY, RUN_TTY, noerr ? DEVNULL : RUN_TTY, RUN_NORMAL);
  79. }
  80.  
  81. /* set RCS branch to REV */
  82. int
  83. RCS_setbranch(path, rev)
  84.     const char *path;
  85.     const char *rev;
  86. {
  87.     run_setup ("%s%s -x,v/ -q -b%s", Rcsbin, RCS, rev ? rev : "");
  88.     run_arg (path);
  89.     return run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
  90. }
  91.  
  92. /* Lock revision REV.  NOERR is 1 to suppress errors--FIXME it would
  93.    be better to avoid the errors or some cleaner solution.  */
  94. int
  95. RCS_lock(path, rev, noerr)
  96.     const char *path;
  97.     const char *rev;
  98.     int noerr;
  99. {
  100.     run_setup ("%s%s -x,v/ -q -l%s", Rcsbin, RCS, rev ? rev : "");
  101.     run_arg (path);
  102.     return run_exec (RUN_TTY, RUN_TTY, noerr ? DEVNULL : RUN_TTY, RUN_NORMAL);
  103. }
  104.  
  105. /* Unlock revision REV.  NOERR is 1 to suppress errors--FIXME it would
  106.    be better to avoid the errors or some cleaner solution.  */
  107. int
  108. RCS_unlock(path, rev, noerr)
  109.     const char *path;
  110.     const char *rev;
  111.     int noerr;
  112. {
  113.     run_setup ("%s%s -x,v/ -q -u%s", Rcsbin, RCS, rev ? rev : "");
  114.     run_arg (path);
  115.     return run_exec (RUN_TTY, RUN_TTY, noerr ? DEVNULL : RUN_TTY, RUN_NORMAL);
  116. }
  117.  
  118. /* Merge revisions REV1 and REV2. */
  119. int
  120. RCS_merge(path, options, rev1, rev2)
  121.      const char *path;
  122.      const char *options;
  123.      const char *rev1;
  124.      const char *rev2;
  125. {
  126.     int status;
  127.  
  128.     /* XXX - Do merge by hand instead of using rcsmerge, due to -k handling */
  129.  
  130.     run_setup ("%s%s -x,v/ %s -r%s -r%s %s", Rcsbin, RCS_RCSMERGE,
  131.            options, rev1, rev2, path);
  132.     status = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
  133. #ifndef HAVE_RCS5
  134.     if (status == 0) 
  135.     {
  136.     /* Run GREP to see if there appear to be conflicts in the file */
  137.     run_setup ("%s", GREP);
  138.     run_arg (RCS_MERGE_PAT);
  139.     run_arg (path);
  140.     status = (run_exec (RUN_TTY, DEVNULL, RUN_TTY, RUN_NORMAL) == 0);
  141.  
  142.     }
  143. #endif
  144.     return status;
  145. }
  146.  
  147. /* Check out a revision from RCSFILE into WORKFILE, or to standard output
  148.    if WORKFILE is NULL.  If WORKFILE is "", let RCS pick the working file
  149.    name.  TAG is the tag to check out, or NULL if one should check out
  150.    the head of the default branch.  OPTIONS is a string such as
  151.    -kb or -kkv, for keyword expansion options, or NULL if there are none.
  152.    If WORKFILE is NULL, run regardless of noexec; if non-NULL, noexec
  153.    inhibits execution.  SOUT is what to do with standard output
  154.    (typically RUN_TTY).  If FLAGS & RCS_FLAGS_FORCE, check out even on top
  155.    of an existing file.  */
  156. int
  157. RCS_checkout (rcsfile, workfile, tag, options, sout, flags)
  158.     char *rcsfile;
  159.     char *workfile;
  160.     char *tag;
  161.     char *options;
  162.     char *sout;
  163.     int flags;
  164. {
  165.     run_setup ("%s%s -x,v/ -q %s%s", Rcsbin, RCS_CO,
  166.                tag ? "-r" : "", tag ? tag : "");
  167.     if (options != NULL && options[0] != '\0')
  168.     run_arg (options);
  169.     if (workfile == NULL)
  170.     run_arg ("-p");
  171.     if (flags & RCS_FLAGS_FORCE)
  172.     run_arg ("-f");
  173.     run_arg (rcsfile);
  174.     if (workfile != NULL && workfile[0] != '\0')
  175.     run_arg (workfile);
  176.     return run_exec (RUN_TTY, sout, RUN_TTY,
  177.                      workfile == NULL ? (RUN_NORMAL | RUN_REALLY) : RUN_NORMAL);
  178. }
  179.  
  180. /* Check in to RCSFILE with revision REV (which must be greater than the
  181.    largest revision) and message MESSAGE (which is checked for legality).
  182.    If FLAGS & RCS_FLAGS_DEAD, check in a dead revision.  If FLAGS &
  183.    RCS_FLAGS_QUIET, tell ci to be quiet.  If FLAGS & RCS_FLAGS_MODTIME,
  184.    use the working file's modification time for the checkin time.
  185.    WORKFILE is the working file to check in from, or NULL to use the usual
  186.    RCS rules for deriving it from the RCSFILE.  */
  187. int
  188. RCS_checkin (rcsfile, workfile, message, rev, flags)
  189.     char *rcsfile;
  190.     char *workfile;
  191.     char *message;
  192.     char *rev;
  193.     int flags;
  194. {
  195.     run_setup ("%s%s -x,v/ -f %s%s", Rcsbin, RCS_CI,
  196.            rev ? "-r" : "", rev ? rev : "");
  197.     if (flags & RCS_FLAGS_DEAD)
  198.     run_arg ("-sdead");
  199.     if (flags & RCS_FLAGS_QUIET)
  200.     run_arg ("-q");
  201.     if (flags & RCS_FLAGS_MODTIME)
  202.     run_arg ("-d");
  203.     run_args ("-m%s", make_message_rcslegal (message));
  204.     if (workfile != NULL)
  205.     run_arg (workfile);
  206.     run_arg (rcsfile);
  207.     return run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
  208. }
  209.