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

Diff for /src/usr.bin/cvs/checkout.c between version 1.52 and 1.53

version 1.52, 2006/04/14 02:45:35 version 1.53, 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 "cvs.h"  #include "cvs.h"
 #include "log.h"  #include "log.h"
   #include "diff.h"
 #include "proto.h"  #include "proto.h"
   
   int     cvs_checkout(int, char **);
   static void checkout_repository(const char *, const char *);
   
 #define CVS_LISTMOD     1  
 #define CVS_STATMOD     2  
   
 static int      cvs_checkout_init(struct cvs_cmd *, int, char **, int *);  
 static int      cvs_checkout_pre_exec(struct cvsroot *);  
 static int      cvs_checkout_local(CVSFILE *cf, void *);  
   
 struct cvs_cmd cvs_cmd_checkout = {  struct cvs_cmd cvs_cmd_checkout = {
         CVS_OP_CHECKOUT, CVS_REQ_CO, "checkout",          CVS_OP_CHECKOUT, CVS_REQ_CO, "checkout",
         { "co", "get" },          { "co", "get" },
         "Checkout sources for editing",          "Checkout a working copy of a repository",
         "[-AcflNnPpRs] [-D date | -r tag] [-d dir] [-j rev] [-k mode] "          "[-AcflNnPpRs] [-D date | -r tag] [-d dir] [-j rev] [-k mode] "
         "[-t id] module ...",          "[-t id] module ...",
         "AcD:d:fj:k:lNnPRr:st:",          "AcD:d:fj:k:lNnPRr:st:",
         NULL,          NULL,
         0,          cvs_checkout
         cvs_checkout_init,  
         cvs_checkout_pre_exec,  
         NULL,  
         NULL,  
         NULL,  
         NULL,  
         CVS_CMD_ALLOWSPEC | CVS_CMD_SENDDIR  
 };  };
   
 struct cvs_cmd cvs_cmd_export = {  int
         CVS_OP_EXPORT, CVS_REQ_EXPORT, "export",  cvs_checkout(int argc, char **argv)
         { "ex", "exp" },  
         "Extract copy of a module without management directories",  
         "[-flNnR] [-d dir] [-k mode] -D date | -r tag module ...",  
         "D:d:fk:lNnRr:",  
         NULL,  
         0,  
         cvs_checkout_init,  
         cvs_checkout_pre_exec,  
         NULL,  
         NULL,  
         NULL,  
         NULL,  
         CVS_CMD_ALLOWSPEC | CVS_CMD_SENDDIR  
 };  
   
 static char *currepo = NULL;  
 static DIR *dirp = NULL;  
 static int cwdfd = -1;  
 static char *date, *tag, *koptstr, *tgtdir, *rcsid;  
 static int statmod = 0;  
 static int shorten = 0;  
 static int usehead = 0;  
 static int kflag = RCS_KWEXP_DEFAULT;  
   
 /* modules */  
 static char **co_mods;  
 static int    co_nmod;  
   
 /* XXX checkout has issues in remote mode, -N gets seen as module */  
   
 static int  
 cvs_checkout_init(struct cvs_cmd *cmd, int argc, char **argv, int *arg)  
 {  {
         int ch;          int i, ch, l;
           struct stat st;
           char repo[MAXPATHLEN];
   
         date = tag = koptstr = tgtdir = rcsid = NULL;          while ((ch = getopt(argc, argv, cvs_cmd_checkout.cmd_opts)) != -1) {
   
         while ((ch = getopt(argc, argv, cmd->cmd_opts)) != -1) {  
                 switch (ch) {                  switch (ch) {
                 case 'A':  
                         break;  
                 case 'c':  
                         statmod = CVS_LISTMOD;  
                         break;  
                 case 'D':  
                         date = optarg;  
                         cmd->cmd_flags |= CVS_CMD_PRUNEDIRS;  
                         break;  
                 case 'd':  
                         tgtdir = optarg;  
                         shorten = 1;  
                         break;  
                 case 'f':  
                         usehead = 1;  
                         break;  
                 case 'j':  
                         break;  
                 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;  
                 case 'P':  
                         cmd->cmd_flags |= CVS_CMD_PRUNEDIRS;  
                         break;  
                 case 'N':  
                         shorten = 0;  
                         break;  
                 case 'p':  
                         cvs_noexec = 1; /* no locks will be created */  
                         break;  
                 case 'r':  
                         tag = optarg;  
                         cmd->cmd_flags |= CVS_CMD_PRUNEDIRS;  
                         break;  
                 case 's':  
                         statmod = CVS_STATMOD;  
                         break;  
                 case 't':  
                         rcsid = optarg;  
                         break;  
                 default:                  default:
                         return (CVS_EX_USAGE);                          fatal("%s", cvs_cmd_checkout.cmd_synopsis);
                 }                  }
         }          }
   
         argc -= optind;          argc -= optind;
         argv += optind;          argv += optind;
   
         co_mods = argv;          if (argc == 0)
         co_nmod = argc;                  fatal("%s", cvs_cmd_checkout.cmd_synopsis);
   
         if (statmod == 0 && argc == 0)          for (i = 0; i < argc; i++) {
                 fatal("must specify at least one module or directory");                  cvs_mkpath(argv[i]);
   
         if (statmod && (argc > 0))                  l = snprintf(repo, sizeof(repo), "%s/%s",
                 fatal("-c and -s must not get any arguments");                      current_cvsroot->cr_dir, argv[i]);
                   if (l == -1 || l >= (int)sizeof(repo))
                           fatal("cvs_checkout: overflow");
   
         /* `export' command exceptions */                  if (stat(repo, &st) == -1) {
         if (cvs_cmdop == CVS_OP_EXPORT) {                          cvs_log(LP_ERR, "cannot find repository %s - ignored",
                 if (tag == NULL && date == NULL)                              argv[i]);
                         fatal("must specify a tag or date");                          continue;
                   }
   
                 /* we don't want numerical revisions here */                  checkout_repository(repo, argv[i]);
                 if (tag != NULL && rcsnum_parse(tag) != NULL)  
                         fatal("tag `%s' must be a symbolic tag", tag);  
         }          }
   
         *arg = optind;  
         return (0);          return (0);
 }  }
   
 static int  static void
 cvs_checkout_pre_exec(struct cvsroot *root)  checkout_repository(const char *repobase, const char *wdbase)
 {  {
         int i, ret;          struct cvs_flisthead fl, dl;
         char *sp, repo[MAXPATHLEN];          struct cvs_recursion cr;
   
         if ((dirp = opendir(".")) == NULL)          TAILQ_INIT(&fl);
                 fatal("cvs_checkout_pre_exec: opendir failed");          TAILQ_INIT(&dl);
   
         cwdfd = dirfd(dirp);          cr.enterdir = cvs_update_enterdir;
           cr.leavedir = NULL;
           cr.local = cvs_update_local;
           cr.remote = NULL;
   
         for (i = 0; i < co_nmod; i++) {          cvs_repository_lock(repobase);
                 if ((sp = strchr(co_mods[i], '/')) != NULL)          cvs_repository_getdir(repobase, wdbase, &fl, &dl);
                         *sp = '\0';  
   
                 if (mkdir(co_mods[i], 0755) == -1 && errno != EEXIST)          cvs_file_walklist(&fl, &cr);
                         fatal("cvs_checkout_pre_exec: mkdir `%s': %s",          cvs_file_freelist(&fl);
                             co_mods[i], strerror(errno));  
   
                 cvs_mkadmin(co_mods[i], root->cr_str, co_mods[i], NULL,          cvs_repository_unlock(repobase);
                     NULL, 0);  
   
                 if (sp != NULL)          cvs_file_walklist(&dl, &cr);
                         *sp = '/';          cvs_file_freelist(&dl);
         }  }
   
         if (root->cr_method == CVS_METHOD_LOCAL) {  int
                 if ((dirp = opendir(".")) == NULL)  cvs_checkout_file(struct cvs_file *cf, RCSNUM *rnum, int flags)
                         fatal("cvs_checkout_pre_exec: opendir failed");  {
           BUF *bp;
           int l, oflags, exists;
           time_t rcstime;
           CVSENTRIES *ent;
           struct timeval tv[2];
           char *entry, rev[16], timebuf[32];
   
                 cwdfd = dirfd(dirp);          rcsnum_tostr(rnum, rev, sizeof(rev));
   
                 for (i = 0; i < co_nmod; i++) {          cvs_log(LP_TRACE, "cvs_checkout_file(%s, %s, %d)",
                         if (strlcpy(repo, root->cr_dir, sizeof(repo)) >=              cf->file_path, rev, flags);
                             sizeof(repo) ||  
                             strlcat(repo, "/", sizeof(repo)) >= sizeof(repo) ||  
                             strlcat(repo, co_mods[i], sizeof(repo)) >=  
                             sizeof(repo))  
                                 fatal("cvs_checkout_pre_exec: path truncation");  
   
                         currepo = co_mods[i];          if ((bp = rcs_getrev(cf->file_rcs, rnum)) == NULL) {
                         ret = cvs_file_get(repo, CF_RECURSE | CF_REPO |                  cvs_log(LP_ERR, "%s: cannot find revision %s",
                             CF_IGNORE, cvs_checkout_local, NULL, NULL);                      cf->file_path, rev);
                         if (ret != CVS_EX_OK) {                  return (0);
                                 closedir(dirp);  
                                 return (ret);  
                         }  
                 }  
   
                 closedir(dirp);  
         } else {  
                 /*  
                  * These arguments are for the expand-modules  
                  * command that we send to the server before requesting  
                  * a checkout.  
                  */  
                 for (i = 0; i < co_nmod; i++)  
                         cvs_sendarg(root, co_mods[i], 0);  
   
                 cvs_sendreq(root, CVS_REQ_DIRECTORY, ".");  
                 cvs_sendln(root, root->cr_dir);  
                 cvs_sendreq(root, CVS_REQ_XPANDMOD, NULL);  
   
                 if (usehead == 1)  
                         cvs_sendarg(root, "-f", 0);  
   
                 if (tgtdir != NULL) {  
                         cvs_sendarg(root, "-d", 0);  
                         cvs_sendarg(root, tgtdir, 0);  
                 }  
   
                 if (shorten == 0)  
                         cvs_sendarg(root, "-N", 0);  
   
                 if (cvs_cmd_checkout.cmd_flags & CVS_CMD_PRUNEDIRS);  
                         cvs_sendarg(root, "-P", 0);  
   
                 for (i = 0; i < co_nmod; i++)  
                         cvs_sendarg(root, co_mods[i], 0);  
   
                 if (statmod == CVS_LISTMOD)  
                         cvs_sendarg(root, "-c", 0);  
                 else if (statmod == CVS_STATMOD)  
                         cvs_sendarg(root, "-s", 0);  
   
                 if (tag != NULL) {  
                         cvs_sendarg(root, "-r", 0);  
                         cvs_sendarg(root, tag, 0);  
                 }  
   
                 if (date != NULL) {  
                         cvs_sendarg(root, "-D", 0);  
                         cvs_sendarg(root, date, 0);  
                 }  
         }          }
   
         return (0);          oflags = O_WRONLY | O_TRUNC;
 }          if (cf->fd != -1) {
                   exists = 1;
 static int                  (void)close(cf->fd);
 cvs_checkout_local(CVSFILE *cf, void *arg)          } else  {
 {                  exists = 0;
         char rcspath[MAXPATHLEN], fpath[MAXPATHLEN];                  oflags |= O_CREAT;
         RCSFILE *rf;  
         struct cvsroot *root;  
         static int inattic = 0;  
   
         /* we don't want these */  
         if (cf->cf_type == DT_DIR && !strcmp(cf->cf_name, "Attic")) {  
                 inattic = 1;  
                 return (CVS_EX_OK);  
         }          }
   
         root = CVS_DIR_ROOT(cf);          cf->fd = open(cf->file_path, oflags);
           if (cf->fd == -1)
                   fatal("cvs_checkout_file: open: %s", strerror(errno));
   
         cvs_file_getpath(cf, fpath, sizeof(fpath));          if (cvs_buf_write_fd(bp, cf->fd) == -1)
         cvs_rcs_getpath(cf, rcspath, sizeof(rcspath));                  fatal("cvs_checkout_file: %s", strerror(errno));
   
         if (cf->cf_type == DT_DIR) {          cvs_buf_free(bp);
                 inattic = 0;  
                 if (verbosity > 1)  
                         cvs_log(LP_INFO, "Updating %s", fpath);  
   
                 if (cvs_cmdop != CVS_OP_SERVER) {          if (fchmod(cf->fd, 0644) == -1)
                         /*                  fatal("cvs_checkout_file: fchmod: %s", strerror(errno));
                          * We pass an empty repository name to  
                          * cvs_create_dir(), because it will correctly  
                          * create the repository directory for us.  
                          */  
                         if (cvs_create_dir(fpath, 1, root->cr_dir, NULL) < 0)  
                                 fatal("cvs_checkout_local: cvs_create_dir failed");  
                         if (fchdir(cwdfd) < 0)  
                                 fatal("cvs_checkout_local: fchdir failed");  
                 } else {  
                         /*  
                          * TODO: send responses to client so it'll  
                          * create it's directories.  
                          */  
                 }  
   
                 return (CVS_EX_OK);          if (exists == 0) {
                   rcstime = rcs_rev_getdate(cf->file_rcs, rnum);
                   if ((rcstime = cvs_hack_time(rcstime, 0)) == 0)
                           fatal("cvs_checkout_file: time conversion failed");
           } else {
                   time(&rcstime);
         }          }
   
         if (inattic == 1)          tv[0].tv_sec = rcstime;
                 return (CVS_EX_OK);          tv[0].tv_usec = 0;
           tv[1] = tv[0];
           if (futimes(cf->fd, tv) == -1)
                   fatal("cvs_checkout_file: futimes: %s", strerror(errno));
   
         if ((rf = rcs_open(rcspath, RCS_READ)) == NULL)          if ((rcstime = cvs_hack_time(rcstime, 1)) == 0)
                 fatal("cvs_checkout_local: rcs_open `%s': %s", rcspath,                  fatal("cvs_checkout_file: to gmt failed");
                     rcs_errstr(rcs_errno));  
   
         if (cvs_checkout_rev(rf, rf->rf_head, cf, fpath,          ctime_r(&rcstime, timebuf);
             (cvs_cmdop != CVS_OP_SERVER) ? 1 : 0,          if (timebuf[strlen(timebuf) - 1] == '\n')
             CHECKOUT_REV_CREATED) < 0)                  timebuf[strlen(timebuf) - 1] = '\0';
                 fatal("cvs_checkout_local: cvs_checkout_rev failed");  
   
         rcs_close(rf);          entry = xmalloc(CVS_ENT_MAXLINELEN);
           l = snprintf(entry, CVS_ENT_MAXLINELEN, "/%s/%s/%s//", cf->file_name,
               rev, timebuf);
   
         cvs_printf("U %s\n", fpath);          ent = cvs_ent_open(cf->file_wd);
         return (0);          cvs_ent_add(ent, entry);
           cvs_ent_close(ent, ENT_SYNC);
   
           xfree(entry);
   
           return (1);
 }  }

Legend:
Removed from v.1.52  
changed lines
  Added in v.1.53