[BACK]Return to commit.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / cvs

Diff for /src/usr.bin/cvs/commit.c between version 1.54 and 1.55

version 1.54, 2006/04/14 02:45:35 version 1.55, 2006/05/27 03:30:30
Line 1 
Line 1 
 /*      $OpenBSD$       */  /*      $OpenBSD$       */
 /*  /*
  * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>   * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
  * All rights reserved.  
  *   *
  * Redistribution and use in source and binary forms, with or without   * Permission to use, copy, modify, and distribute this software for any
  * modification, are permitted provided that the following conditions   * purpose with or without fee is hereby granted, provided that the above
  * are met:   * copyright notice and this permission notice appear in all copies.
  *   *
  * 1. Redistributions of source code must retain the above copyright   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  *    notice, this list of conditions and the following disclaimer.   * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  * 2. The name of the author may not be used to endorse or promote products   * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  *    derived from this software without specific prior written permission.   * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  *   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,   * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL  
  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  
  * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,  
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;  
  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR  
  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF  
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
  */   */
   
 #include "includes.h"  #include "includes.h"
   
 #include "buf.h"  
 #include "cvs.h"  #include "cvs.h"
   #include "diff.h"
 #include "log.h"  #include "log.h"
 #include "proto.h"  #include "proto.h"
   
   int     cvs_commit(int, char **);
   void    cvs_commit_local(struct cvs_file *);
   void    cvs_commit_check_conflicts(struct cvs_file *);
   
 static int      cvs_commit_init(struct cvs_cmd *, int, char **, int *);  static char *commit_diff_file(struct cvs_file *);
 static int      cvs_commit_prepare(CVSFILE *, void *);  
 static int      cvs_commit_remote(CVSFILE *, void *);  
 static int      cvs_commit_local(CVSFILE *, void *);  
 static int      cvs_commit_pre_exec(struct cvsroot *);  
   
   struct  cvs_flisthead files_affected;
   int     conflicts_found;
   char    *logmsg;
   
 struct cvs_cmd cvs_cmd_commit = {  struct cvs_cmd cvs_cmd_commit = {
         CVS_OP_COMMIT, CVS_REQ_CI, "commit",          CVS_OP_COMMIT, CVS_REQ_CI, "commit",
         { "ci",  "com" },          { "ci", "com" },
         "Check files into the repository",          "Check files into the repository",
         "[-flR] [-F logfile | -m msg] [-r rev] ...",          "[-flR] [-F logfile | -m msg] [-r rev] ...",
         "F:flm:Rr:",          "F:flm:Rr:",
         NULL,          NULL,
         CF_RECURSE | CF_IGNORE | CF_SORT,          cvs_commit
         cvs_commit_init,  
         cvs_commit_pre_exec,  
         cvs_commit_remote,  
         cvs_commit_local,  
         NULL,  
         NULL,  
         CVS_CMD_SENDDIR | CVS_CMD_ALLOWSPEC | CVS_CMD_SENDARGS2  
 };  };
   
 static char *mfile = NULL;  int
 static char *rev = NULL;  cvs_commit(int argc, char **argv)
 static char **commit_files = NULL;  
 static int commit_fcount = 0;  
 static int wantedstatus = 0;  
   
 static int  
 cvs_commit_init(struct cvs_cmd *cmd, int argc, char **argv, int *arg)  
 {  {
         int ch;          int ch;
           char *arg = ".";
           struct cvs_recursion cr;
   
         while ((ch = getopt(argc, argv, cmd->cmd_opts)) != -1) {          while ((ch = getopt(argc, argv, cvs_cmd_commit.cmd_opts)) != -1) {
                 switch (ch) {                  switch (ch) {
                 case 'F':  
                         mfile = optarg;  
                         break;  
                 case 'f':                  case 'f':
                         /* XXX half-implemented */  
                         cmd->file_flags &= ~CF_RECURSE;  
                         break;                          break;
                   case 'F':
                           break;
                 case 'l':                  case 'l':
                         cmd->file_flags &= ~CF_RECURSE;  
                         break;                          break;
                 case 'm':                  case 'm':
                         cvs_msg = xstrdup(optarg);                          logmsg = xstrdup(optarg);
                         break;                          break;
                 case 'R':  
                         cmd->file_flags |= CF_RECURSE;  
                         break;  
                 case 'r':                  case 'r':
                         rev = optarg;  
                         break;                          break;
                   case 'R':
                           break;
                 default:                  default:
                         return (CVS_EX_USAGE);                          fatal("%s", cvs_cmd_commit.cmd_synopsis);
                 }                  }
         }          }
   
         if (cvs_msg != NULL && mfile != NULL) {          argc -= optind;
                 cvs_log(LP_ERR, "the -F and -m flags are mutually exclusive");          argv += optind;
                 return (CVS_EX_USAGE);  
         }  
   
         if (mfile != NULL)          if (logmsg == NULL)
                 cvs_msg = cvs_logmsg_open(mfile);                  fatal("please use -m to specify a log message for now");
   
         *arg = optind;          TAILQ_INIT(&files_affected);
           conflicts_found = 0;
   
         commit_files = (argv + optind);          cr.enterdir = NULL;
         commit_fcount = (argc - optind);          cr.leavedir = NULL;
           cr.local = cvs_commit_check_conflicts;
           cr.remote = NULL;
   
           if (argc > 0)
                   cvs_file_run(argc, argv, &cr);
           else
                   cvs_file_run(1, &arg, &cr);
   
           if (conflicts_found != 0)
                   fatal("%d conflicts found, please correct these first",
                       conflicts_found);
   
           cr.local = cvs_commit_local;
           cvs_file_walklist(&files_affected, &cr);
           cvs_file_freelist(&files_affected);
   
         return (0);          return (0);
 }  }
   
 int  void
 cvs_commit_pre_exec(struct cvsroot *root)  cvs_commit_check_conflicts(struct cvs_file *cf)
 {  {
         CVSFILE *cfp;          cvs_log(LP_TRACE, "cvs_commit_check_conflicts(%s)", cf->file_path);
         CVSFILE *tmp;  
         int ret, i, flags = CF_RECURSE | CF_IGNORE | CF_SORT;  
         struct cvs_flist added, modified, removed, *cl[3];  
         int stattype[] = { CVS_FST_ADDED, CVS_FST_MODIFIED, CVS_FST_REMOVED };  
   
         SIMPLEQ_INIT(&added);  
         SIMPLEQ_INIT(&modified);  
         SIMPLEQ_INIT(&removed);  
   
         cl[0] = &added;  
         cl[1] = &modified;  
         cl[2] = &removed;  
   
         if ((tmp = cvs_file_loadinfo(".", CF_NOFILES, NULL, NULL, 1)) == NULL)  
                 return (CVS_EX_DATA);  
   
         /*          /*
          * Obtain the file lists for the logmessage.           * cvs_file_classify makes the noise for us
            * XXX - we want that?
          */           */
         for (i = 0; i < 3; i++) {          cvs_file_classify(cf);
                 wantedstatus = stattype[i];  
                 if (commit_fcount != 0) {  
                         ret = cvs_file_getspec(commit_files, commit_fcount,  
                             flags, cvs_commit_prepare, cl[i], NULL);  
                 } else {  
                         ret = cvs_file_get(".", flags, cvs_commit_prepare,  
                             cl[i], NULL);  
                 }  
   
                 if (ret != CVS_EX_OK) {          if (cf->file_status == FILE_CONFLICT ||
                         cvs_file_free(tmp);              cf->file_status == FILE_LOST ||
                         return (CVS_EX_DATA);              cf->file_status == FILE_UNLINK)
                 }                  conflicts_found++;
         }  
   
         /*          if (cf->file_status == FILE_ADDED ||
          * If we didn't catch any file, don't call the editor.              cf->file_status == FILE_REMOVED ||
          */              cf->file_status == FILE_MODIFIED)
         if (SIMPLEQ_EMPTY(&added) && SIMPLEQ_EMPTY(&modified) &&                  cvs_file_get(cf->file_path, &files_affected);
             SIMPLEQ_EMPTY(&removed)) {  }
                 cvs_file_free(tmp);  
                 return (0);  
         }  
   
         /*  void
          * Fetch the log message for real, with all the files.  cvs_commit_local(struct cvs_file *cf)
          */  {
         if (cvs_msg == NULL)          BUF *b;
                 cvs_msg = cvs_logmsg_get(tmp->cf_name, &added, &modified,          char *d, *f, rbuf[16];
                     &removed);  
   
         cvs_file_free(tmp);          cvs_log(LP_TRACE, "cvs_commit_local(%s)", cf->file_path);
           cvs_file_classify(cf);
   
         /* free the file lists */          rcsnum_tostr(cf->file_rcs->rf_head, rbuf, sizeof(rbuf));
         for (i = 0; i < 3; i++) {  
                 while (!SIMPLEQ_EMPTY(cl[i])) {  
                         cfp = SIMPLEQ_FIRST(cl[i]);  
                         SIMPLEQ_REMOVE_HEAD(cl[i], cf_list);  
                         cvs_file_free(cfp);  
                 }  
         }  
   
         if (cvs_msg == NULL)          cvs_printf("Checking in %s:\n", cf->file_path);
                 return (CVS_EX_DATA);          cvs_printf("%s <- %s\n", cf->file_rpath, cf->file_path);
           cvs_printf("old revision: %s; ", rbuf);
   
         if (root->cr_method != CVS_METHOD_LOCAL) {          d = commit_diff_file(cf);
                 cvs_logmsg_send(root, cvs_msg);  
   
                 if (rev != NULL) {          if ((b = cvs_buf_load(cf->file_path, BUF_AUTOEXT)) == NULL)
                         cvs_sendarg(root, "-r", 0);                  fatal("cvs_commit_local: failed to load file");
                         cvs_sendarg(root, rev, 0);  
                 }  
         }  
   
         return (0);          cvs_buf_putc(b, '\0');
 }          f = cvs_buf_release(b);
   
 /*          if (rcs_deltatext_set(cf->file_rcs, cf->file_rcs->rf_head, d) == -1)
  * cvs_commit_prepare()                  fatal("cvs_commit_local: failed to set delta");
  *  
  * Examine the file <cf> to see if it will be part of the commit, in which  
  * case it gets added to the list passed as second argument.  
  */  
 int  
 cvs_commit_prepare(CVSFILE *cf, void *arg)  
 {  
         CVSFILE *copy;  
         struct cvs_flist *clp = (struct cvs_flist *)arg;  
   
         if (cf->cf_type == DT_REG && cf->cf_cvstat == wantedstatus) {          if (rcs_rev_add(cf->file_rcs, RCS_HEAD_REV, logmsg, -1, NULL) == -1)
                 copy = cvs_file_copy(cf);                  fatal("cvs_commit_local: failed to add new revision");
                 if (copy == NULL)  
                         return (CVS_EX_DATA);  
   
                 SIMPLEQ_INSERT_TAIL(clp, copy, cf_list);          if (rcs_deltatext_set(cf->file_rcs, cf->file_rcs->rf_head, f) == -1)
         }                  fatal("cvs_commit_local: failed to set new HEAD delta");
   
         return (0);          xfree(f);
 }          xfree(d);
   
           rcs_write(cf->file_rcs);
   
 /*          rcsnum_tostr(cf->file_rcs->rf_head, rbuf, sizeof(rbuf));
  * cvs_commit_remote()          cvs_printf("new revision: %s\n", rbuf);
  *  
  * Commit a single file.  
  */  
 int  
 cvs_commit_remote(CVSFILE *cf, void *arg)  
 {  
         char fpath[MAXPATHLEN];  
         struct cvsroot *root;  
   
         root = CVS_DIR_ROOT(cf);          (void)unlink(cf->file_path);
           (void)close(cf->fd);
           cf->fd = -1;
           cvs_checkout_file(cf, cf->file_rcs->rf_head, 0);
   
         if (cf->cf_type == DT_DIR) {          cvs_printf("done\n");
                 if (cf->cf_cvstat != CVS_FST_UNKNOWN)  
                         cvs_senddir(root, cf);  
                 return (0);  
         }  
   
         cvs_file_getpath(cf, fpath, sizeof(fpath));  }
   
         if (cf->cf_cvstat == CVS_FST_ADDED ||  static char *
             cf->cf_cvstat == CVS_FST_MODIFIED ||  commit_diff_file(struct cvs_file *cf)
             cf->cf_cvstat == CVS_FST_REMOVED) {  {
                 cvs_sendentry(root, cf);          char*delta,  *p1, *p2;
           BUF *b1, *b2, *b3;
   
                 /* if it's removed, don't bother sending a          if ((b1 = cvs_buf_load(cf->file_path, BUF_AUTOEXT)) == NULL)
                  * Modified request together with the file its                  fatal("commit_diff_file: failed to load '%s'", cf->file_path);
                  * contents.  
                  */  
                 if (cf->cf_cvstat == CVS_FST_REMOVED)  
                         return (0);  
   
                 cvs_sendreq(root, CVS_REQ_MODIFIED, cf->cf_name);          if ((b2 = rcs_getrev(cf->file_rcs, cf->file_rcs->rf_head)) == NULL)
                 cvs_sendfile(root, fpath);                  fatal("commit_diff_file: failed to load HEAD for '%s'",
         }                      cf->file_path);
   
         return (0);          if ((b3 = cvs_buf_alloc(128, BUF_AUTOEXT)) == NULL)
 }                  fatal("commit_diff_file: failed to create diff buf");
   
 static int          (void)xasprintf(&p1, "%s/diff1.XXXXXXXXXX", cvs_tmpdir);
 cvs_commit_local(CVSFILE *cf, void *arg)          cvs_buf_write_stmp(b1, p1, 0600, NULL);
 {          cvs_buf_free(b1);
         char fpath[MAXPATHLEN], rcspath[MAXPATHLEN];  
   
         if (cf->cf_type == DT_DIR) {          (void)xasprintf(&p2, "%s/diff2.XXXXXXXXXX", cvs_tmpdir);
                 if (verbosity > 1)          cvs_buf_write_stmp(b2, p2, 0600, NULL);
                         cvs_log(LP_NOTICE, "Examining %s", cf->cf_name);          cvs_buf_free(b2);
                 return (0);  
         }  
   
         cvs_file_getpath(cf, fpath, sizeof(fpath));          diff_format = D_RCSDIFF;
         cvs_rcs_getpath(cf, rcspath, sizeof(rcspath));          if (cvs_diffreg(p1, p2, b3) == D_ERROR)
                   fatal("commit_diff_file: failed to get RCS patch");
   
         return (0);          cvs_buf_putc(b3, '\0');
           delta = cvs_buf_release(b3);
           return (delta);
 }  }

Legend:
Removed from v.1.54  
changed lines
  Added in v.1.55