Annotation of src/usr.bin/cvs/edit.c, Revision 1.18
1.18 ! xsa 1: /* $OpenBSD: edit.c,v 1.17 2007/01/05 07:13:49 xsa Exp $ */
1.1 jfb 2: /*
1.15 xsa 3: * Copyright (c) 2006, 2007 Xavier Santolaria <xsa@openbsd.org>
1.1 jfb 4: *
1.14 xsa 5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.1 jfb 16: */
17:
1.11 xsa 18: #include "includes.h"
1.1 jfb 19:
20: #include "cvs.h"
21: #include "log.h"
1.14 xsa 22: #include "remote.h"
1.1 jfb 23:
1.18 ! xsa 24: #define E_COMMIT 0x01
! 25: #define E_EDIT 0x02
! 26: #define E_UNEDIT 0x04
! 27: #define E_ALL (E_EDIT|E_COMMIT|E_UNEDIT)
! 28:
! 29: static void cvs_edit_local(struct cvs_file *);
1.14 xsa 30: static void cvs_editors_local(struct cvs_file *);
1.15 xsa 31: static void cvs_unedit_local(struct cvs_file *);
1.1 jfb 32:
1.18 ! xsa 33: static int edit_aflags = 0;
! 34:
! 35: struct cvs_cmd cvs_cmd_edit = {
! 36: CVS_OP_EDIT, 0, "edit",
! 37: { },
! 38: "Get ready to edit a watched file",
! 39: "[-lR] [-a action] [file ...]",
! 40: "a:lR",
! 41: NULL,
! 42: cvs_edit
! 43: };
! 44:
1.1 jfb 45: struct cvs_cmd cvs_cmd_editors = {
1.14 xsa 46: CVS_OP_EDITORS, 0, "editors",
1.1 jfb 47: { },
1.14 xsa 48: "See who is editing a watched file",
1.3 xsa 49: "[-lR] [file ...]",
1.1 jfb 50: "lR",
51: NULL,
1.14 xsa 52: cvs_editors
1.1 jfb 53: };
54:
1.15 xsa 55: struct cvs_cmd cvs_cmd_unedit = {
56: CVS_OP_UNEDIT, 0, "unedit",
57: { },
58: "Undo an edit command",
59: "[-lR] [file ...]",
60: "lR",
61: NULL,
62: cvs_unedit
63: };
64:
1.14 xsa 65: int
1.18 ! xsa 66: cvs_edit(int argc, char **argv)
! 67: {
! 68: int ch;
! 69: int flags;
! 70: struct cvs_recursion cr;
! 71:
! 72: flags = CR_RECURSE_DIRS;
! 73:
! 74: while ((ch = getopt(argc, argv, cvs_cmd_edit.cmd_opts)) != -1) {
! 75: switch (ch) {
! 76: case 'a':
! 77: if (strcmp(optarg, "edit") == 0)
! 78: edit_aflags |= E_EDIT;
! 79: else if (strcmp(optarg, "unedit") == 0)
! 80: edit_aflags |= E_UNEDIT;
! 81: else if (strcmp(optarg, "commit") == 0)
! 82: edit_aflags |= E_COMMIT;
! 83: else if (strcmp(optarg, "all") == 0)
! 84: edit_aflags |= E_ALL;
! 85: else if (strcmp(optarg, "none") == 0)
! 86: edit_aflags &= ~E_ALL;
! 87: else
! 88: fatal("%s", cvs_cmd_edit.cmd_synopsis);
! 89: break;
! 90: case 'l':
! 91: flags &= ~CR_RECURSE_DIRS;
! 92: break;
! 93: case 'R':
! 94: break;
! 95: default:
! 96: fatal("%s", cvs_cmd_edit.cmd_synopsis);
! 97: }
! 98: }
! 99:
! 100: argc -= optind;
! 101: argv += optind;
! 102:
! 103: if (argc == 0)
! 104: fatal("%s", cvs_cmd_edit.cmd_synopsis);
! 105:
! 106: if (edit_aflags == 0)
! 107: edit_aflags |= E_ALL;
! 108:
! 109: cr.enterdir = NULL;
! 110: cr.leavedir = NULL;
! 111:
! 112: if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
! 113: cr.fileproc = cvs_client_sendfile;
! 114:
! 115: if (!(flags & CR_RECURSE_DIRS))
! 116: cvs_client_send_request("Argument -l");
! 117: } else {
! 118: cr.fileproc = cvs_edit_local;
! 119: }
! 120:
! 121: cr.flags = flags;
! 122:
! 123: cvs_file_run(argc, argv, &cr);
! 124:
! 125: if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
! 126: cvs_client_send_files(argv, argc);
! 127: cvs_client_senddir(".");
! 128: cvs_client_send_request("edit");
! 129: cvs_client_get_responses();
! 130: }
! 131:
! 132: return (0);
! 133: }
! 134:
! 135: int
1.14 xsa 136: cvs_editors(int argc, char **argv)
1.1 jfb 137: {
1.12 xsa 138: int ch;
1.14 xsa 139: int flags;
140: struct cvs_recursion cr;
141:
142: flags = CR_RECURSE_DIRS;
1.1 jfb 143:
1.14 xsa 144: while ((ch = getopt(argc, argv, cvs_cmd_editors.cmd_opts)) != -1) {
1.1 jfb 145: switch (ch) {
146: case 'l':
1.14 xsa 147: flags &= ~CR_RECURSE_DIRS;
1.1 jfb 148: break;
149: case 'R':
150: break;
151: default:
1.14 xsa 152: fatal("%s", cvs_cmd_editors.cmd_synopsis);
1.1 jfb 153: }
154: }
155:
1.14 xsa 156: argc -= optind;
157: argv += optind;
1.1 jfb 158:
1.14 xsa 159: if (argc == 0)
160: fatal("%s", cvs_cmd_editors.cmd_synopsis);
1.1 jfb 161:
1.14 xsa 162: cr.enterdir = NULL;
163: cr.leavedir = NULL;
1.1 jfb 164:
1.14 xsa 165: if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
166: cr.fileproc = cvs_client_sendfile;
167:
168: if (!(flags & CR_RECURSE_DIRS))
169: cvs_client_send_request("Argument -l");
170: } else {
171: cr.fileproc = cvs_editors_local;
172: }
1.1 jfb 173:
1.14 xsa 174: cr.flags = flags;
1.9 xsa 175:
1.14 xsa 176: cvs_file_run(argc, argv, &cr);
1.9 xsa 177:
1.14 xsa 178: if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
179: cvs_client_send_files(argv, argc);
180: cvs_client_senddir(".");
181: cvs_client_send_request("editors");
182: cvs_client_get_responses();
1.9 xsa 183: }
184:
1.14 xsa 185: return (0);
186: }
1.9 xsa 187:
1.15 xsa 188: int
189: cvs_unedit(int argc, char **argv)
190: {
191: int ch;
192: int flags;
193: struct cvs_recursion cr;
194:
195: flags = CR_RECURSE_DIRS;
196:
197: while ((ch = getopt(argc, argv, cvs_cmd_unedit.cmd_opts)) != -1) {
198: switch (ch) {
199: case 'l':
200: flags &= ~CR_RECURSE_DIRS;
201: break;
202: case 'R':
203: break;
204: default:
205: fatal("%s", cvs_cmd_unedit.cmd_synopsis);
206: }
207: }
208:
209: argc -= optind;
210: argv += optind;
211:
212: if (argc == 0)
213: fatal("%s", cvs_cmd_unedit.cmd_synopsis);
214:
215: cr.enterdir = NULL;
216: cr.leavedir = NULL;
217:
218: if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
219: cr.fileproc = cvs_client_sendfile;
220:
221: if (!(flags & CR_RECURSE_DIRS))
222: cvs_client_send_request("Argument -l");
223: } else {
224: cr.fileproc = cvs_unedit_local;
225: }
226:
227: cr.flags = flags;
228:
229: cvs_file_run(argc, argv, &cr);
230:
231: if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
232: cvs_client_send_files(argv, argc);
233: cvs_client_senddir(".");
234: cvs_client_send_request("unedit");
235: cvs_client_get_responses();
236: }
237:
238: return (0);
1.18 ! xsa 239: }
! 240:
! 241: static void
! 242: cvs_edit_local(struct cvs_file *cf)
! 243: {
! 244: FILE *fp;
! 245: struct tm *t;
! 246: time_t now;
! 247: char *bfpath, *fdate;
! 248:
! 249: if (cvs_noexec == 1)
! 250: return;
! 251:
! 252: if ((fp = fopen(CVS_PATH_NOTIFY, "a")) == NULL)
! 253: fatal("cvs_edit_local: fopen: `%s': %s",
! 254: CVS_PATH_NOTIFY, strerror(errno));
! 255:
! 256: (void)time(&now);
! 257: if ((t = gmtime(&now)) == NULL)
! 258: fatal("gmtime failed");
! 259:
! 260: fdate = asctime(t);
! 261:
! 262: (void)fprintf(fp, "E%s\t%s GMT\t%s\t%s\t\n",
! 263: cf->file_name, fdate, current_cvsroot->cr_host, cf->file_wd);
! 264:
! 265: if (edit_aflags & E_EDIT)
! 266: (void)fprintf(fp, "E");
! 267: if (edit_aflags & E_UNEDIT)
! 268: (void)fprintf(fp, "U");
! 269: if (edit_aflags & E_COMMIT)
! 270: (void)fprintf(fp, "C");
! 271:
! 272: (void)fprintf(fp, "\n");
! 273:
! 274: (void)fclose(fp);
! 275:
! 276: if (fchmod(cf->fd, 0644) == -1)
! 277: fatal("cvs_edit_local: fchmod %s", strerror(errno));
! 278:
! 279: bfpath = xmalloc(MAXPATHLEN);
! 280: if (cvs_path_cat(CVS_PATH_BASEDIR, cf->file_name, bfpath,
! 281: MAXPATHLEN) >= MAXPATHLEN)
! 282: fatal("cvs_edit_local: truncation");
! 283:
! 284: /* XXX: copy cf->file_path to bfpath */
! 285:
! 286: xfree(bfpath);
! 287:
! 288: /* XXX: Update revision number in CVS/Baserev from CVS/Entries */
1.15 xsa 289: }
290:
1.14 xsa 291: static void
292: cvs_editors_local(struct cvs_file *cf)
293: {
1.15 xsa 294: }
295:
296: static void
297: cvs_unedit_local(struct cvs_file *cf)
298: {
299: FILE *fp;
300: struct stat st;
301: struct tm *t;
302: time_t now;
303: char *bfpath, *fdate;
304:
305: if (cvs_noexec == 1)
306: return;
307:
308: bfpath = xmalloc(MAXPATHLEN);
309: if (cvs_path_cat(CVS_PATH_BASEDIR, cf->file_name, bfpath,
310: MAXPATHLEN) >= MAXPATHLEN)
311: fatal("cvs_unedit_local: truncation");
312:
313: if (stat(bfpath, &st) == -1) {
314: xfree(bfpath);
315: return;
316: }
317:
1.17 xsa 318: if (cvs_file_cmp(cf->file_path, bfpath) != 0) {
319: cvs_printf("%s has been modified; revert changes? ",
320: cf->file_name);
321:
322: if (cvs_yesno() == -1) {
323: xfree(bfpath);
324: return;
325: }
326: }
1.15 xsa 327:
328: cvs_rename(bfpath, cf->file_path);
329: xfree(bfpath);
330:
331: if ((fp = fopen(CVS_PATH_NOTIFY, "a")) == NULL)
332: fatal("cvs_unedit_local: fopen: `%s': %s",
333: CVS_PATH_NOTIFY, strerror(errno));
334:
335: (void)time(&now);
336: if ((t = gmtime(&now)) == NULL)
337: fatal("gmtime failed");
338:
339: fdate = asctime(t);
340:
341: (void)fprintf(fp, "U%s\t%s GMT\t%s\t%s\t\n",
342: cf->file_name, fdate, current_cvsroot->cr_host, cf->file_wd);
343:
344: (void)fclose(fp);
345:
346: /* XXX: Update revision number in CVS/Entries from CVS/Baserev */
1.16 xsa 347:
348: if (fchmod(cf->fd, 0644) == -1)
349: fatal("cvs_unedit_local: fchmod %s", strerror(errno));
1.1 jfb 350: }