rcscmds.c revision 17721
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/* For RCS file PATH, make symbolic tag TAG point to revision REV. 16 This validates that TAG is OK for a user to use. Return value is 17 -1 for error (and errno is set to indicate the error), positive for 18 error (and an error message has been printed), or zero for success. */ 19 20int 21RCS_settag(path, tag, rev) 22 const char *path; 23 const char *tag; 24 const char *rev; 25{ 26 if (strcmp (tag, TAG_BASE) == 0 27 || strcmp (tag, TAG_HEAD) == 0) 28 { 29 /* Print the name of the tag might be considered redundant 30 with the caller, which also prints it. Perhaps this helps 31 clarify why the tag name is considered reserved, I don't 32 know. */ 33 error (0, 0, "Attempt to add reserved tag name %s", tag); 34 return 1; 35 } 36 37 run_setup ("%s%s -x,v/ -q -N%s:%s", Rcsbin, RCS, tag, rev); 38 run_arg (path); 39 return run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); 40} 41 42/* NOERR is 1 to suppress errors--FIXME it would 43 be better to avoid the errors or some cleaner solution. */ 44int 45RCS_deltag(path, tag, noerr) 46 const char *path; 47 const char *tag; 48 int noerr; 49{ 50 run_setup ("%s%s -x,v/ -q -N%s", Rcsbin, RCS, tag); 51 run_arg (path); 52 return run_exec (RUN_TTY, RUN_TTY, noerr ? DEVNULL : RUN_TTY, RUN_NORMAL); 53} 54 55/* set RCS branch to REV */ 56int 57RCS_setbranch(path, rev) 58 const char *path; 59 const char *rev; 60{ 61 run_setup ("%s%s -x,v/ -q -b%s", Rcsbin, RCS, rev ? rev : ""); 62 run_arg (path); 63 return run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); 64} 65 66/* Lock revision REV. NOERR is 1 to suppress errors--FIXME it would 67 be better to avoid the errors or some cleaner solution. */ 68int 69RCS_lock(path, rev, noerr) 70 const char *path; 71 const char *rev; 72 int noerr; 73{ 74 run_setup ("%s%s -x,v/ -q -l%s", Rcsbin, RCS, rev ? rev : ""); 75 run_arg (path); 76 return run_exec (RUN_TTY, RUN_TTY, noerr ? DEVNULL : RUN_TTY, RUN_NORMAL); 77} 78 79/* Unlock revision REV. NOERR is 1 to suppress errors--FIXME it would 80 be better to avoid the errors or some cleaner solution. */ 81int 82RCS_unlock(path, rev, noerr) 83 const char *path; 84 const char *rev; 85 int noerr; 86{ 87 run_setup ("%s%s -x,v/ -q -u%s", Rcsbin, RCS, rev ? rev : ""); 88 run_arg (path); 89 return run_exec (RUN_TTY, RUN_TTY, noerr ? DEVNULL : RUN_TTY, RUN_NORMAL); 90} 91 92/* Merge revisions REV1 and REV2. */ 93int 94RCS_merge(path, options, rev1, rev2) 95 const char *path; 96 const char *options; 97 const char *rev1; 98 const char *rev2; 99{ 100 int status; 101 102 /* XXX - Do merge by hand instead of using rcsmerge, due to -k handling */ 103 104 run_setup ("%s%s -x,v/ %s -r%s -r%s %s", Rcsbin, RCS_RCSMERGE, 105 options, rev1, rev2, path); 106 status = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); 107#ifndef HAVE_RCS5 108 if (status == 0) 109 { 110 /* Run GREP to see if there appear to be conflicts in the file */ 111 run_setup ("%s", GREP); 112 run_arg (RCS_MERGE_PAT); 113 run_arg (path); 114 status = (run_exec (RUN_TTY, DEVNULL, RUN_TTY, RUN_NORMAL) == 0); 115 116 } 117#endif 118 return status; 119} 120 121/* Check out a revision from RCSFILE into WORKFILE, or to standard output 122 if WORKFILE is NULL. If WORKFILE is "", let RCS pick the working file 123 name. TAG is the tag to check out, or NULL if one should check out 124 the head of the default branch. OPTIONS is a string such as 125 -kb or -kkv, for keyword expansion options, or NULL if there are none. 126 If WORKFILE is NULL, run regardless of noexec; if non-NULL, noexec 127 inhibits execution. SOUT is what to do with standard output 128 (typically RUN_TTY). If FLAGS & RCS_FLAGS_LOCK, lock it. If 129 FLAGS & RCS_FLAGS_FORCE, check out even on top of an existing file. 130 If NOERR is nonzero, suppress errors. */ 131int 132RCS_checkout (rcsfile, workfile, tag, options, sout, flags, noerr) 133 char *rcsfile; 134 char *workfile; 135 char *tag; 136 char *options; 137 char *sout; 138 int flags; 139 int noerr; 140{ 141 run_setup ("%s%s -x,v/ -q %s%s", Rcsbin, RCS_CO, 142 tag ? "-r" : "", tag ? tag : ""); 143 if (options != NULL && options[0] != '\0') 144 run_arg (options); 145 if (workfile == NULL) 146 run_arg ("-p"); 147 if (flags & RCS_FLAGS_LOCK) 148 run_arg ("-l"); 149 if (flags & RCS_FLAGS_FORCE) 150 run_arg ("-f"); 151 run_arg (rcsfile); 152 if (workfile != NULL && workfile[0] != '\0') 153 run_arg (workfile); 154 return run_exec (RUN_TTY, sout, noerr ? DEVNULL : RUN_TTY, 155 workfile == NULL ? (RUN_NORMAL | RUN_REALLY) : RUN_NORMAL); 156} 157 158/* Check in to RCSFILE with revision REV (which must be greater than the 159 largest revision) and message MESSAGE (which is checked for legality). 160 If FLAGS & RCS_FLAGS_DEAD, check in a dead revision. If NOERR, do not 161 report errors. If FLAGS & RCS_FLAGS_QUIET suppress errors somewhat more 162 selectively. If FLAGS & RCS_FLAGS_MODTIME, use the working file's 163 modification time for the checkin time. WORKFILE is the working file 164 to check in from, or NULL to use the usual RCS rules for deriving it 165 from the RCSFILE. */ 166int 167RCS_checkin (rcsfile, workfile, message, rev, flags, noerr) 168 char *rcsfile; 169 char *workfile; 170 char *message; 171 char *rev; 172 int flags; 173 int noerr; 174{ 175 run_setup ("%s%s -x,v/ -f %s%s", Rcsbin, RCS_CI, 176 rev ? "-r" : "", rev ? rev : ""); 177 if (flags & RCS_FLAGS_DEAD) 178 run_arg ("-sdead"); 179 if (flags & RCS_FLAGS_QUIET) 180 run_arg ("-q"); 181 if (flags & RCS_FLAGS_MODTIME) 182 run_arg ("-d"); 183 run_args ("-m%s", make_message_rcslegal (message)); 184 if (workfile != NULL) 185 run_arg (workfile); 186 run_arg (rcsfile); 187 return run_exec (RUN_TTY, RUN_TTY, noerr ? DEVNULL : RUN_TTY, RUN_NORMAL); 188} 189