=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/cvs/checkout.c,v retrieving revision 1.52 retrieving revision 1.53 diff -c -r1.52 -r1.53 *** src/usr.bin/cvs/checkout.c 2006/04/14 02:45:35 1.52 --- src/usr.bin/cvs/checkout.c 2006/05/27 03:30:30 1.53 *************** *** 1,337 **** ! /* $OpenBSD: checkout.c,v 1.52 2006/04/14 02:45:35 deraadt Exp $ */ /* ! * Copyright (c) 2004 Jean-Francois Brousseau ! * All rights reserved. * ! * Redistribution and use in source and binary forms, with or without ! * modification, are permitted provided that the following conditions ! * are met: * ! * 1. Redistributions of source code must retain the above copyright ! * notice, this list of conditions and the following disclaimer. ! * 2. The name of the author may not be used to endorse or promote products ! * derived from this software without specific prior written permission. ! * ! * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, ! * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY ! * 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 "cvs.h" #include "log.h" #include "proto.h" - #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 = { CVS_OP_CHECKOUT, CVS_REQ_CO, "checkout", { "co", "get" }, ! "Checkout sources for editing", "[-AcflNnPpRs] [-D date | -r tag] [-d dir] [-j rev] [-k mode] " "[-t id] module ...", "AcD:d:fj:k:lNnPRr:st:", NULL, ! 0, ! cvs_checkout_init, ! cvs_checkout_pre_exec, ! NULL, ! NULL, ! NULL, ! NULL, ! CVS_CMD_ALLOWSPEC | CVS_CMD_SENDDIR }; ! struct cvs_cmd cvs_cmd_export = { ! CVS_OP_EXPORT, CVS_REQ_EXPORT, "export", ! { "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; ! date = tag = koptstr = tgtdir = rcsid = NULL; ! ! while ((ch = getopt(argc, argv, cmd->cmd_opts)) != -1) { 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: ! return (CVS_EX_USAGE); } } argc -= optind; argv += optind; ! co_mods = argv; ! co_nmod = argc; ! if (statmod == 0 && argc == 0) ! fatal("must specify at least one module or directory"); ! if (statmod && (argc > 0)) ! fatal("-c and -s must not get any arguments"); ! /* `export' command exceptions */ ! if (cvs_cmdop == CVS_OP_EXPORT) { ! if (tag == NULL && date == NULL) ! fatal("must specify a tag or date"); ! /* we don't want numerical revisions here */ ! if (tag != NULL && rcsnum_parse(tag) != NULL) ! fatal("tag `%s' must be a symbolic tag", tag); } - *arg = optind; return (0); } ! static int ! cvs_checkout_pre_exec(struct cvsroot *root) { ! int i, ret; ! char *sp, repo[MAXPATHLEN]; ! if ((dirp = opendir(".")) == NULL) ! fatal("cvs_checkout_pre_exec: opendir failed"); ! cwdfd = dirfd(dirp); ! for (i = 0; i < co_nmod; i++) { ! if ((sp = strchr(co_mods[i], '/')) != NULL) ! *sp = '\0'; ! if (mkdir(co_mods[i], 0755) == -1 && errno != EEXIST) ! fatal("cvs_checkout_pre_exec: mkdir `%s': %s", ! co_mods[i], strerror(errno)); ! cvs_mkadmin(co_mods[i], root->cr_str, co_mods[i], NULL, ! NULL, 0); ! if (sp != NULL) ! *sp = '/'; ! } ! if (root->cr_method == CVS_METHOD_LOCAL) { ! if ((dirp = opendir(".")) == NULL) ! fatal("cvs_checkout_pre_exec: opendir failed"); ! cwdfd = dirfd(dirp); ! for (i = 0; i < co_nmod; i++) { ! if (strlcpy(repo, root->cr_dir, sizeof(repo)) >= ! 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]; ! ret = cvs_file_get(repo, CF_RECURSE | CF_REPO | ! CF_IGNORE, cvs_checkout_local, NULL, NULL); ! if (ret != CVS_EX_OK) { ! 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); ! } ! ! static int ! cvs_checkout_local(CVSFILE *cf, void *arg) ! { ! char rcspath[MAXPATHLEN], fpath[MAXPATHLEN]; ! 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); ! cvs_file_getpath(cf, fpath, sizeof(fpath)); ! cvs_rcs_getpath(cf, rcspath, sizeof(rcspath)); ! if (cf->cf_type == DT_DIR) { ! inattic = 0; ! if (verbosity > 1) ! cvs_log(LP_INFO, "Updating %s", fpath); ! if (cvs_cmdop != CVS_OP_SERVER) { ! /* ! * 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 (inattic == 1) ! return (CVS_EX_OK); ! if ((rf = rcs_open(rcspath, RCS_READ)) == NULL) ! fatal("cvs_checkout_local: rcs_open `%s': %s", rcspath, ! rcs_errstr(rcs_errno)); ! if (cvs_checkout_rev(rf, rf->rf_head, cf, fpath, ! (cvs_cmdop != CVS_OP_SERVER) ? 1 : 0, ! CHECKOUT_REV_CREATED) < 0) ! fatal("cvs_checkout_local: cvs_checkout_rev failed"); ! rcs_close(rf); ! cvs_printf("U %s\n", fpath); ! return (0); } --- 1,179 ---- ! /* $OpenBSD: checkout.c,v 1.53 2006/05/27 03:30:30 joris Exp $ */ /* ! * Copyright (c) 2006 Joris Vink * ! * Permission to use, copy, modify, and distribute this software for any ! * purpose with or without fee is hereby granted, provided that the above ! * copyright notice and this permission notice appear in all copies. * ! * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ! * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ! * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ! * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ! * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ! * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ! * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #include "cvs.h" #include "log.h" + #include "diff.h" #include "proto.h" + int cvs_checkout(int, char **); + static void checkout_repository(const char *, const char *); struct cvs_cmd cvs_cmd_checkout = { CVS_OP_CHECKOUT, CVS_REQ_CO, "checkout", { "co", "get" }, ! "Checkout a working copy of a repository", "[-AcflNnPpRs] [-D date | -r tag] [-d dir] [-j rev] [-k mode] " "[-t id] module ...", "AcD:d:fj:k:lNnPRr:st:", NULL, ! cvs_checkout }; ! int ! cvs_checkout(int argc, char **argv) { ! int i, ch, l; ! struct stat st; ! char repo[MAXPATHLEN]; ! while ((ch = getopt(argc, argv, cvs_cmd_checkout.cmd_opts)) != -1) { switch (ch) { default: ! fatal("%s", cvs_cmd_checkout.cmd_synopsis); } } argc -= optind; argv += optind; ! if (argc == 0) ! fatal("%s", cvs_cmd_checkout.cmd_synopsis); ! for (i = 0; i < argc; i++) { ! cvs_mkpath(argv[i]); ! l = snprintf(repo, sizeof(repo), "%s/%s", ! current_cvsroot->cr_dir, argv[i]); ! if (l == -1 || l >= (int)sizeof(repo)) ! fatal("cvs_checkout: overflow"); ! if (stat(repo, &st) == -1) { ! cvs_log(LP_ERR, "cannot find repository %s - ignored", ! argv[i]); ! continue; ! } ! checkout_repository(repo, argv[i]); } return (0); } ! static void ! checkout_repository(const char *repobase, const char *wdbase) { ! struct cvs_flisthead fl, dl; ! struct cvs_recursion cr; ! TAILQ_INIT(&fl); ! TAILQ_INIT(&dl); ! cr.enterdir = cvs_update_enterdir; ! cr.leavedir = NULL; ! cr.local = cvs_update_local; ! cr.remote = NULL; ! cvs_repository_lock(repobase); ! cvs_repository_getdir(repobase, wdbase, &fl, &dl); ! cvs_file_walklist(&fl, &cr); ! cvs_file_freelist(&fl); ! cvs_repository_unlock(repobase); ! cvs_file_walklist(&dl, &cr); ! cvs_file_freelist(&dl); ! } ! int ! cvs_checkout_file(struct cvs_file *cf, RCSNUM *rnum, int flags) ! { ! BUF *bp; ! int l, oflags, exists; ! time_t rcstime; ! CVSENTRIES *ent; ! struct timeval tv[2]; ! char *entry, rev[16], timebuf[32]; ! rcsnum_tostr(rnum, rev, sizeof(rev)); ! cvs_log(LP_TRACE, "cvs_checkout_file(%s, %s, %d)", ! cf->file_path, rev, flags); ! if ((bp = rcs_getrev(cf->file_rcs, rnum)) == NULL) { ! cvs_log(LP_ERR, "%s: cannot find revision %s", ! cf->file_path, rev); ! return (0); } ! oflags = O_WRONLY | O_TRUNC; ! if (cf->fd != -1) { ! exists = 1; ! (void)close(cf->fd); ! } else { ! exists = 0; ! oflags |= O_CREAT; } ! cf->fd = open(cf->file_path, oflags); ! if (cf->fd == -1) ! fatal("cvs_checkout_file: open: %s", strerror(errno)); ! if (cvs_buf_write_fd(bp, cf->fd) == -1) ! fatal("cvs_checkout_file: %s", strerror(errno)); ! cvs_buf_free(bp); ! if (fchmod(cf->fd, 0644) == -1) ! fatal("cvs_checkout_file: fchmod: %s", strerror(errno)); ! 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); } ! tv[0].tv_sec = rcstime; ! tv[0].tv_usec = 0; ! tv[1] = tv[0]; ! if (futimes(cf->fd, tv) == -1) ! fatal("cvs_checkout_file: futimes: %s", strerror(errno)); ! if ((rcstime = cvs_hack_time(rcstime, 1)) == 0) ! fatal("cvs_checkout_file: to gmt failed"); ! ctime_r(&rcstime, timebuf); ! if (timebuf[strlen(timebuf) - 1] == '\n') ! timebuf[strlen(timebuf) - 1] = '\0'; ! entry = xmalloc(CVS_ENT_MAXLINELEN); ! l = snprintf(entry, CVS_ENT_MAXLINELEN, "/%s/%s/%s//", cf->file_name, ! rev, timebuf); ! ent = cvs_ent_open(cf->file_wd); ! cvs_ent_add(ent, entry); ! cvs_ent_close(ent, ENT_SYNC); ! ! xfree(entry); ! ! return (1); }