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

Diff for /src/usr.bin/cvs/update.c between version 1.58 and 1.59

version 1.58, 2006/04/14 02:45:35 version 1.59, 2006/05/27 03:30:31
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 "cvs.h"  #include "cvs.h"
 #include "log.h"  #include "log.h"
 #include "proto.h"  
 #include "diff.h"  #include "diff.h"
   #include "proto.h"
   
 static int      cvs_update_init(struct cvs_cmd *, int, char **, int *);  int     cvs_update(int, char **);
 static int      cvs_update_pre_exec(struct cvsroot *);  
 static int      cvs_update_remote(CVSFILE *, void *);  
 static int      cvs_update_local(CVSFILE *, void *);  
   
 struct cvs_cmd cvs_cmd_update = {  struct cvs_cmd cvs_cmd_update = {
         CVS_OP_UPDATE, CVS_REQ_UPDATE, "update",          CVS_OP_UPDATE, CVS_REQ_UPDATE, "update",
Line 44 
Line 32 
         "[-t id] ...",          "[-t id] ...",
         "ACD:dfI:j:k:lPpQqRr:t:",          "ACD:dfI:j:k:lPpQqRr:t:",
         NULL,          NULL,
         CF_SORT | CF_RECURSE | CF_IGNORE | CF_NOSYMS,          cvs_update
         cvs_update_init,  
         cvs_update_pre_exec,  
         cvs_update_remote,  
         cvs_update_local,  
         NULL,  
         NULL,  
         CVS_CMD_ALLOWSPEC | CVS_CMD_SENDARGS2 | CVS_CMD_SENDDIR  
 };  };
   
 static char *date, *rev, *koptstr;  int
 static int dflag, Aflag;  cvs_update(int argc, char **argv)
 static int kflag = RCS_KWEXP_DEFAULT;  
   
 static int  
 cvs_update_init(struct cvs_cmd *cmd, int argc, char **argv, int *arg)  
 {  {
         int ch;          int ch;
           char *arg = ".";
           struct cvs_recursion cr;
   
         dflag = Aflag = 0;          while ((ch = getopt(argc, argv, cvs_cmd_update.cmd_opts)) != -1) {
         date = NULL;  
         rev = NULL;  
   
         while ((ch = getopt(argc, argv, cmd->cmd_opts)) != -1) {  
                 switch (ch) {                  switch (ch) {
                 case 'A':                  case 'A':
                         Aflag = 1;  
                         break;                          break;
                 case 'C':                  case 'C':
                 case 'D':                  case 'D':
                         date = optarg;  
                         break;                          break;
                 case 'd':                  case 'd':
                         dflag = 1;  
                         break;                          break;
                 case 'f':                  case 'f':
                         break;                          break;
Line 86 
Line 58 
                 case 'j':                  case 'j':
                         break;                          break;
                 case 'k':                  case 'k':
                         koptstr = optarg;  
                         kflag = rcs_kflag_get(koptstr);  
                         if (RCS_KWEXP_INVAL(kflag)) {  
                                 cvs_log(LP_ERR,  
                                     "invalid RCS keyword expansion mode");  
                                 rcs_kflag_usage();  
                                 return (CVS_EX_USAGE);  
                         }  
                         break;                          break;
                 case 'l':                  case 'l':
                         cmd->file_flags &= ~CF_RECURSE;  
                         break;                          break;
                 case 'P':                  case 'P':
                         cmd->cmd_flags |= CVS_CMD_PRUNEDIRS;  
                         break;                          break;
                 case 'p':                  case 'p':
                         cvs_noexec = 1; /* no locks will be created */  
                         break;                          break;
                 case 'Q':                  case 'Q':
                 case 'q':                  case 'q':
                         break;                          break;
                 case 'R':                  case 'R':
                         cmd->file_flags |= CF_RECURSE;  
                         break;                          break;
                 case 'r':                  case 'r':
                         rev = optarg;  
                         break;                          break;
                 default:                  default:
                         return (CVS_EX_USAGE);                          fatal("%s", cvs_cmd_update.cmd_synopsis);
                 }                  }
         }          }
   
         *arg = optind;          argc -= optind;
         return (0);          argv += optind;
 }  
   
 static int          cr.enterdir = cvs_update_enterdir;
 cvs_update_pre_exec(struct cvsroot *root)          cr.leavedir = NULL;
 {          cr.local = cvs_update_local;
         if (root->cr_method != CVS_METHOD_LOCAL) {          cr.remote = NULL;
                 if (cvs_cmd_update.cmd_flags & CVS_CMD_PRUNEDIRS)  
                         cvs_sendarg(root, "-P", 0);  
   
                 if (Aflag == 1)          if (argc > 0)
                         cvs_sendarg(root, "-A", 0);                  cvs_file_run(argc, argv, &cr);
           else
                   cvs_file_run(1, &arg, &cr);
   
                 if (dflag == 1)  
                         cvs_sendarg(root, "-d", 0);  
   
                 if (rev != NULL) {  
                         cvs_sendarg(root, "-r", 0);  
                         cvs_sendarg(root, rev, 0);  
                 }  
   
                 if (date != NULL) {  
                         cvs_sendarg(root, "-D", 0);  
                         cvs_sendarg(root, date, 0);  
                 }  
         }  
   
         return (0);          return (0);
 }  }
   
 /*  void
  * cvs_update_remote()  cvs_update_enterdir(struct cvs_file *cf)
  *  
  * Update a single file.  In the case where we act as client, send any  
  * pertinent information about that file to the server.  
  */  
 static int  
 cvs_update_remote(CVSFILE *cf, void *arg)  
 {  {
         char fpath[MAXPATHLEN];          int l;
         struct cvsroot *root;          char *entry;
           CVSENTRIES *entlist;
   
         root = CVS_DIR_ROOT(cf);          cvs_log(LP_TRACE, "cvs_update_enterdir(%s)", cf->file_path);
   
         if (cf->cf_type == DT_DIR) {          cvs_file_classify(cf);
                 if (cf->cf_cvstat == CVS_FST_UNKNOWN)  
                         cvs_sendreq(root, CVS_REQ_QUESTIONABLE, cf->cf_name);  
                 else  
                         cvs_senddir(root, cf);  
                 return (0);  
         }  
   
         cvs_file_getpath(cf, fpath, sizeof(fpath));          if (cf->file_status == DIR_CREATE) {
                   cvs_mkpath(cf->file_path);
                   if ((cf->fd = open(cf->file_path, O_RDONLY)) == -1)
                           fatal("cvs_update_enterdir: %s", strerror(errno));
   
         cvs_sendentry(root, cf);                  entry = xmalloc(CVS_ENT_MAXLINELEN);
                   l = snprintf(entry, CVS_ENT_MAXLINELEN, "D/%s////",
                       cf->file_name);
                   if (l == -1 || l >= CVS_ENT_MAXLINELEN)
                           fatal("cvs_update_enterdir: overflow");
   
         if (!(cf->cf_flags & CVS_FILE_ONDISK))                  entlist = cvs_ent_open(cf->file_wd);
                 return (0);                  cvs_ent_add(entlist, entry);
                   cvs_ent_close(entlist, ENT_SYNC);
         switch (cf->cf_cvstat) {                  xfree(entry);
         case CVS_FST_UNKNOWN:  
                 cvs_sendreq(root, CVS_REQ_QUESTIONABLE, cf->cf_name);  
                 break;  
         case CVS_FST_UPTODATE:  
                 cvs_sendreq(root, CVS_REQ_UNCHANGED, cf->cf_name);  
                 break;  
         case CVS_FST_ADDED:  
         case CVS_FST_MODIFIED:  
                 cvs_sendreq(root, CVS_REQ_MODIFIED, cf->cf_name);  
                 cvs_sendfile(root, fpath);  
                 break;  
         default:  
                 break;  
         }          }
   
         return (0);  
 }  }
   
 /*  void
  * cvs_update_local()  cvs_update_local(struct cvs_file *cf)
  */  
 static int  
 cvs_update_local(CVSFILE *cf, void *arg)  
 {  {
         int islocal, revdiff;          CVSENTRIES *entlist;
         char fpath[MAXPATHLEN], rcspath[MAXPATHLEN];  
         RCSFILE *rf;  
         RCSNUM *frev;  
         BUF *fbuf;  
   
         revdiff = 0;          cvs_log(LP_TRACE, "cvs_update_local(%s)", cf->file_path);
         rf = NULL;  
         frev = NULL;  
         islocal = (cvs_cmdop != CVS_OP_SERVER);  
   
         cvs_file_getpath(cf, fpath, sizeof(fpath));          if (cf->file_type == CVS_DIR) {
                   if (cf->file_status != FILE_UNKNOWN &&
         if (cf->cf_cvstat == CVS_FST_UNKNOWN) {                      verbosity > 1)
                 if (verbosity > 1)                          cvs_log(LP_NOTICE, "Updating %s", cf->file_path);
                         cvs_printf("? %s\n", fpath);                  return;
                 return (CVS_EX_OK);  
         }          }
   
         if (cf->cf_type == DT_DIR) {          cvs_file_classify(cf);
                 if (verbosity > 1)  
                         cvs_log(LP_NOTICE, "Updating %s", fpath);  
                 return (CVS_EX_OK);  
         }  
   
         cvs_rcs_getpath(cf, rcspath, sizeof(rcspath));          switch (cf->file_status) {
           case FILE_UNKNOWN:
         /*                  cvs_printf("? %s\n", cf->file_path);
          * Only open the RCS file for files that have not been added.  
          */  
         if (cf->cf_cvstat != CVS_FST_ADDED) {  
                 rf = rcs_open(rcspath, RCS_READ);  
   
                 /*  
                  * If there is no RCS file available in the repository  
                  * directory that matches this file, it's gone.  
                  * XXX: so what about the Attic?  
                  */  
                 if (rf == NULL) {  
                         cvs_log(LP_WARN, "%s is no longer in the repository",  
                             fpath);  
                         if (cvs_checkout_rev(NULL, NULL, cf, fpath,  
                             islocal, CHECKOUT_REV_REMOVED) < 0)  
                                 fatal("cvs_update_local: cvs_checkout_rev failed");  
                         return (CVS_EX_OK);  
                 }  
         } else {  
                 /* There's no need to update a newly added file */  
                 cvs_printf("A %s\n", fpath);  
                 return (CVS_EX_OK);  
         }  
   
         /* set keyword expansion */  
         /* XXX look at cf->cf_opts as well for this */  
         rcs_kwexp_set(rf, kflag);  
   
         /* fill in the correct revision */  
         if (rev != NULL) {  
                 if ((frev = rcsnum_parse(rev)) == NULL)  
                         fatal("cvs_update_local: rcsnum_parse failed");  
         } else  
                 frev = rf->rf_head;  
   
         /*  
          * Compare the headrevision with the revision we currently have.  
          */  
         if (cf->cf_lrev != NULL)  
                 revdiff = rcsnum_cmp(cf->cf_lrev, frev, 0);  
   
         switch (cf->cf_cvstat) {  
         case CVS_FST_MODIFIED:  
                 /*  
                  * If the file has been modified but there is a newer version  
                  * available, we try to merge it into the existing changes.  
                  */  
                 if (revdiff == 1) {  
                         fbuf = cvs_diff3(rf, fpath, cf->cf_lrev, frev, 0);  
                         if (fbuf == NULL) {  
                                 cvs_log(LP_ERR, "merge failed");  
                                 break;  
                         }  
   
                         /*  
                          * Please note fbuf will be free'd in cvs_checkout_rev  
                          */  
                         if (cvs_checkout_rev(rf, frev, cf, fpath, islocal,  
                             CHECKOUT_REV_MERGED, fbuf) != -1) {  
                                 cvs_printf("%c %s\n",  
                                     (diff3_conflicts > 0) ? 'C' : 'M',  
                                     fpath);  
                                 if (diff3_conflicts > 0)  
                                         cf->cf_cvstat = CVS_FST_CONFLICT;  
                         }  
                 } else {  
                         cvs_printf("M %s\n", fpath);  
                 }  
                 break;                  break;
         case CVS_FST_REMOVED:          case FILE_MODIFIED:
                 cvs_printf("R %s\n", fpath);                  if (cf->file_ent->ce_conflict != NULL)
                           cvs_printf("C %s\n", cf->file_path);
                   else
                           cvs_printf("M %s\n", cf->file_path);
                 break;                  break;
         case CVS_FST_CONFLICT:          case FILE_ADDED:
                 cvs_printf("C %s\n", fpath);                  cvs_printf("A %s\n", cf->file_path);
                 break;                  break;
         case CVS_FST_LOST:          case FILE_REMOVED:
                 if (cvs_checkout_rev(rf, frev, cf, fpath, islocal,                  cvs_printf("R %s\n", cf->file_path);
                     CHECKOUT_REV_UPDATED) != -1) {  
                         cf->cf_cvstat = CVS_FST_UPTODATE;  
                         cvs_printf("U %s\n", fpath);  
                 }  
                 break;                  break;
         case CVS_FST_UPTODATE:          case FILE_CONFLICT:
                 if (revdiff == 1) {                  cvs_printf("C %s\n", cf->file_path);
                         if (cvs_checkout_rev(rf, frev, cf, fpath, islocal,  
                             CHECKOUT_REV_UPDATED) != -1)  
                                 cvs_printf("P %s\n", fpath);  
                 }  
                 break;                  break;
           case FILE_LOST:
           case FILE_CHECKOUT:
           case FILE_PATCH:
                   if (cvs_checkout_file(cf, cf->file_rcs->rf_head, 0))
                           cvs_printf("U %s\n", cf->file_path);
                   break;
           case FILE_MERGE:
                   cvs_printf("needs merge: %s\n", cf->file_path);
                   break;
           case FILE_UNLINK:
                   (void)unlink(cf->file_path);
           case FILE_REMOVE_ENTRY:
                   entlist = cvs_ent_open(cf->file_wd);
                   cvs_ent_remove(entlist, cf->file_name);
                   cvs_ent_close(entlist, ENT_SYNC);
                   break;
         default:          default:
                 break;                  break;
         }          }
   
         if (frev != NULL && frev != rf->rf_head)  
                 rcsnum_free(frev);  
         rcs_close(rf);  
   
         return (CVS_EX_OK);  
 }  }

Legend:
Removed from v.1.58  
changed lines
  Added in v.1.59