=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/cvs/commit.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- src/usr.bin/cvs/commit.c 2004/11/09 22:22:47 1.5 +++ src/usr.bin/cvs/commit.c 2004/11/26 16:23:50 1.6 @@ -1,4 +1,4 @@ -/* $OpenBSD: commit.c,v 1.5 2004/11/09 22:22:47 krapht Exp $ */ +/* $OpenBSD: commit.c,v 1.6 2004/11/26 16:23:50 jfb Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau * All rights reserved. @@ -25,6 +25,7 @@ */ #include +#include #include #include @@ -41,18 +42,19 @@ #include "proto.h" -#define CVS_COMMIT_BIGMSG 32000 -#define CVS_COMMIT_FTMPL "/tmp/cvsXXXXXXXXXX" -#define CVS_COMMIT_LOGPREFIX "CVS:" -#define CVS_COMMIT_LOGLINE \ -"----------------------------------------------------------------------" +LIST_HEAD(ci_list, ci_file); +struct ci_file { + char *ci_path; + RCSNUM *ci_rev; + LIST_ENTRY(ci_file) ci_link; +}; -static char* cvs_commit_openmsg (const char *); -static char* cvs_commit_getmsg (const char *); +int cvs_commit_file (CVSFILE *, void *); + /* * cvs_commit() * @@ -62,15 +64,16 @@ int cvs_commit(int argc, char **argv) { - int ch, recurse; + int ch, recurse, flags; char *msg, *mfile; + struct ci_list cl; + flags = 0; recurse = 1; mfile = NULL; msg = NULL; + LIST_INIT(&cl); - cvs_commit_getmsg("."); - while ((ch = getopt(argc, argv, "F:flm:R")) != -1) { switch (ch) { case 'F': @@ -98,210 +101,90 @@ return (EX_USAGE); } - if ((mfile != NULL) && (msg = cvs_commit_openmsg(mfile)) == NULL) + if ((mfile != NULL) && (msg = cvs_logmsg_open(mfile)) == NULL) return (EX_DATAERR); argc -= optind; argv += optind; - return (0); -} - - -/* - * cvs_commit_openmsg() - * - * Open the file specified by and allocate a buffer large enough to - * hold all of the file's contents. The returned value must later be freed - * using the free() function. - * Returns a pointer to the allocated buffer on success, or NULL on failure. - */ - -static char* -cvs_commit_openmsg(const char *path) -{ - int ch; - size_t len; - char lbuf[256], *msg; - struct stat st; - FILE *fp; - BUF *bp; - - if (stat(path, &st) == -1) { - cvs_log(LP_ERRNO, "failed to stat `%s'", path); - return (NULL); + if (argc == 0) + cvs_files = cvs_file_get(".", flags); + else { + cvs_files = cvs_file_getspec(argv, argc, flags); } + if (cvs_files == NULL) + return (EX_DATAERR); - if (!S_ISREG(st.st_mode)) { - cvs_log(LP_ERR, "message file must be a regular file"); - return (NULL); - } + cvs_file_examine(cvs_files, cvs_commit_file, &cl); - if (st.st_size > CVS_COMMIT_BIGMSG) { - do { - fprintf(stderr, - "The specified message file seems big. " - "Proceed anyways? (y/n) "); - if (fgets(lbuf, sizeof(lbuf), stdin) == NULL) { - cvs_log(LP_ERRNO, - "failed to read from standard input"); - return (NULL); - } + cvs_senddir(cvs_files->cf_ddat->cd_root, cvs_files); + cvs_sendreq(cvs_files->cf_ddat->cd_root, CVS_REQ_CI, NULL); - len = strlen(lbuf); - if ((len == 0) || (len > 2) || - ((lbuf[0] != 'y') && (lbuf[0] != 'n'))) { - fprintf(stderr, "invalid input\n"); - continue; - } - else if (lbuf[0] == 'y') - break; - else if (lbuf[0] == 'n') { - cvs_log(LP_ERR, "aborted by user"); - return (NULL); - } - - } while (1); - } - - if ((fp = fopen(path, "r")) == NULL) { - cvs_log(LP_ERRNO, "failed to open message file `%s'", path); - return (NULL); - } - - bp = cvs_buf_alloc(128, BUF_AUTOEXT); - if (bp == NULL) { - return (NULL); - } - - while (fgets(lbuf, sizeof(lbuf), fp) != NULL) { - len = strlen(lbuf); - if (len == 0) - continue; - - /* skip lines starting with the prefix */ - if (strncmp(lbuf, CVS_COMMIT_LOGPREFIX, - strlen(CVS_COMMIT_LOGPREFIX)) == 0) - continue; - - cvs_buf_append(bp, lbuf, strlen(lbuf)); - } - cvs_buf_putc(bp, '\0'); - - msg = (char *)cvs_buf_release(bp); - - return (msg); + return (0); } /* - * cvs_commit_getmsg() + * cvs_commit_file() * - * Get a commit log message by forking the user's editor. - * Returns the message in a dynamically allocated string on success, NULL on - * failure. + * Commit a single file. */ -static char* -cvs_commit_getmsg(const char *dir) +int +cvs_commit_file(CVSFILE *cf, void *arg) { - int ret, fd, argc, fds[3]; - size_t len; - char *argv[4], buf[16], path[MAXPATHLEN], *msg; - FILE *fp; - struct stat st1, st2; + char *repo, rcspath[MAXPATHLEN], fpath[MAXPATHLEN]; + RCSFILE *rf; + struct cvsroot *root; + struct cvs_ent *entp; + struct ci_list *cl; - msg = NULL; - fds[0] = -1; - fds[1] = -1; - fds[2] = -1; - strlcpy(path, CVS_COMMIT_FTMPL, sizeof(path)); - argc = 0; - argv[argc++] = cvs_editor; - argv[argc++] = path; - argv[argc] = NULL; + cl = (struct ci_list *)arg; - if ((fd = mkstemp(path)) == -1) { - cvs_log(LP_ERRNO, "failed to create temporary file"); - return (NULL); - } + if (cf->cf_type == DT_DIR) { + if (cf->cf_cvstat != CVS_FST_UNKNOWN) { + root = cf->cf_ddat->cd_root; + if ((cf->cf_parent == NULL) || + (root != cf->cf_parent->cf_ddat->cd_root)) { + cvs_connect(root); + } - fp = fdopen(fd, "w"); - if (fp == NULL) { - cvs_log(LP_ERRNO, "failed to fdopen"); - } else { - fprintf(fp, - "\n%s %s\n%s Enter Log. Lines beginning with `%s' are " - "removed automatically\n%s\n%s Commiting in %s\n" - "%s\n%s Modified Files:\n", - CVS_COMMIT_LOGPREFIX, CVS_COMMIT_LOGLINE, - CVS_COMMIT_LOGPREFIX, CVS_COMMIT_LOGPREFIX, - CVS_COMMIT_LOGPREFIX, CVS_COMMIT_LOGPREFIX, - dir, CVS_COMMIT_LOGPREFIX, CVS_COMMIT_LOGPREFIX); + cvs_senddir(root, cf); + } - /* XXX list files here */ - - fprintf(fp, "%s %s\n", CVS_COMMIT_LOGPREFIX, - CVS_COMMIT_LOGLINE); + return (0); } - (void)fflush(fp); + else + root = cf->cf_parent->cf_ddat->cd_root; - if (fstat(fd, &st1) == -1) { - cvs_log(LP_ERRNO, "failed to stat log message file"); - - (void)fclose(fp); - if (unlink(path) == -1) - cvs_log(LP_ERRNO, "failed to unlink log file %s", path); - return (NULL); + rf = NULL; + if (cf->cf_parent != NULL) { + repo = cf->cf_parent->cf_ddat->cd_repo; } + else { + repo = NULL; + } - for (;;) { - ret = cvs_exec(argc, argv, fds); - if (ret == -1) - break; - if (fstat(fd, &st2) == -1) { - cvs_log(LP_ERRNO, "failed to stat log message file"); - break; - } + entp = cvs_ent_getent(fpath); + if (entp == NULL) + return (-1); - if (st2.st_mtime != st1.st_mtime) - break; - - /* nothing was entered */ - fprintf(stderr, - "Log message unchanged or not specified\na)bort, " - "c)ontinue, e)dit, !)reuse this message unchanged " - "for remaining dirs\nAction: (continue) "); - - if (fgets(buf, sizeof(buf), stdin) == NULL) { - cvs_log(LP_ERRNO, "failed to read from standard input"); - break; + if ((cf->cf_cvstat == CVS_FST_ADDED) || + (cf->cf_cvstat == CVS_FST_MODIFIED)) { + if ((root->cr_method != CVS_METHOD_LOCAL) && + (cvs_sendentry(root, entp) < 0)) { + cvs_ent_free(entp); + return (-1); } - len = strlen(buf); - if ((len == 0) || (len > 2)) { - fprintf(stderr, "invalid input\n"); - continue; - } - else if (buf[0] == 'a') { - cvs_log(LP_ERR, "aborted by user"); - break; - } else if ((buf[0] == '\n') || (buf[0] == 'c')) { - /* empty message */ - msg = strdup(""); - break; - } else if (ret == 'e') - continue; - else if (ret == '!') { - /* XXX do something */ - } + cvs_sendreq(root, CVS_REQ_MODIFIED, CVS_FILE_NAME(cf)); + cvs_sendfile(root, fpath); } - (void)fclose(fp); - (void)close(fd); + snprintf(rcspath, sizeof(rcspath), "%s/%s/%s%s", + root->cr_dir, repo, fpath, RCS_FILE_EXT); - if (unlink(path) == -1) - cvs_log(LP_ERRNO, "failed to unlink log file %s", path); + cvs_ent_free(entp); - return (msg); + return (0); }