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