=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/cvs/import.c,v retrieving revision 1.44 retrieving revision 1.45 diff -u -r1.44 -r1.45 --- src/usr.bin/cvs/import.c 2006/05/27 03:30:30 1.44 +++ src/usr.bin/cvs/import.c 2006/05/30 07:00:30 1.45 @@ -1,370 +1,214 @@ -/* $OpenBSD: import.c,v 1.44 2006/05/27 03:30:30 joris dead $ */ +/* $OpenBSD: import.c,v 1.45 2006/05/30 07:00:30 joris Exp $ */ /* - * Copyright (c) 2004 Joris Vink - * All rights reserved. + * Copyright (c) 2006 Joris Vink * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * 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. * - * 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. + * 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 "diff.h" #include "log.h" #include "proto.h" +int cvs_import(int, char **); +void cvs_import_local(struct cvs_file *); -#define CVS_IMPORT_DEFBRANCH "1.1.1" +static void import_new(struct cvs_file *); +static void import_update(struct cvs_file *); +#define IMPORT_DEFAULT_BRANCH "1.1.1" -static int cvs_import_init(struct cvs_cmd *, int, char **, int *); -static int cvs_import_pre_exec(struct cvsroot *); -static int cvs_import_pre_exec(struct cvsroot *); -static int cvs_import_post_exec(struct cvsroot *); -static int cvs_import_remote(CVSFILE *, void *); -static int cvs_import_local(CVSFILE *, void *); -static int cvs_import_cleanup(void); +static char *import_branch = IMPORT_DEFAULT_BRANCH; +static char *logmsg = NULL; +static char *vendor_tag = NULL; +static char *release_tag = NULL; -static int dflag = 0; -static int conflicts = 0; -static RCSNUM *imp_brnum; +char *import_repository = NULL; -static char *module, *vendor, *release; - struct cvs_cmd cvs_cmd_import = { CVS_OP_IMPORT, CVS_REQ_IMPORT, "import", { "im", "imp" }, "Import sources into CVS, using vendor branches", - "[-d] [-b branch] [-I ign] [-k mode] [-m msg] [-W spec] module " - "vendortag releasetag ...", - "b:dI:k:m:W:", + "[-b vendor branch id] [-m message] repository vendor-tag release-tags", + "b:m:", NULL, - CF_RECURSE | CF_IGNORE | CF_NOSYMS, - cvs_import_init, - cvs_import_pre_exec, - cvs_import_remote, - cvs_import_local, - cvs_import_post_exec, - cvs_import_cleanup, - CVS_CMD_SENDDIR + cvs_import }; -static int -cvs_import_init(struct cvs_cmd *cmd, int argc, char **argv, int *arg) +int +cvs_import(int argc, char **argv) { - int ch; + int ch, l; + char repo[MAXPATHLEN], *arg = "."; + struct cvs_recursion cr; - while ((ch = getopt(argc, argv, cmd->cmd_opts)) != -1) { + while ((ch = getopt(argc, argv, cvs_cmd_import.cmd_opts)) != -1) { switch (ch) { case 'b': - if ((imp_brnum = rcsnum_parse(optarg)) == NULL) { - cvs_log(LP_ERR, "%s is not a numeric branch", - optarg); - return (CVS_EX_USAGE); - } + import_branch = optarg; break; - case 'd': - dflag = 1; - break; - case 'I': - if (cvs_file_ignore(optarg) < 0) { - cvs_log(LP_ERR, "failed to add `%s' to list " - "of ignore patterns", optarg); - return (CVS_EX_USAGE); - } - break; - case 'k': - break; case 'm': - cvs_msg = xstrdup(optarg); + logmsg = optarg; break; default: - return (CVS_EX_USAGE); + fatal("%s", cvs_cmd_import.cmd_synopsis); + break; } } argc -= optind; argv += optind; - if (argc != 3) - return (CVS_EX_USAGE); - if (imp_brnum == NULL && - (imp_brnum = rcsnum_parse(CVS_IMPORT_DEFBRANCH)) == NULL) - fatal("cvs_import_init: rcsnum_parse failed"); + if (argc < 3) + fatal("%s", cvs_cmd_import.cmd_synopsis); - module = argv[0]; - vendor = argv[1]; - release = argv[2]; + if (logmsg == NULL) + fatal("please specify a logmessage using -m for now"); - *arg = optind + 3; + import_repository = argv[0]; + vendor_tag = argv[1]; + release_tag = argv[2]; - if (cvs_msg == NULL) - cvs_msg = cvs_logmsg_get(NULL, NULL, NULL, NULL); + l = snprintf(repo, sizeof(repo), "%s/%s", current_cvsroot->cr_dir, + import_repository); + if (l == -1 || l >= (int)sizeof(repo)) + fatal("cvs_import: overflow"); - return (0); -} + if (mkdir(repo, 0755) == -1 && errno != EEXIST) + fatal("cvs_import: %s: %s", repo, strerror(errno)); -static int -cvs_import_pre_exec(struct cvsroot *root) -{ - char numbuf[64], repodir[MAXPATHLEN]; + cr.enterdir = NULL; + cr.leavedir = NULL; + cr.remote = NULL; + cr.local = cvs_import_local; + cr.flags = CR_RECURSE_DIRS; + cvs_file_run(1, &arg, &cr); - if (root->cr_method == CVS_METHOD_LOCAL) { - if (cvs_path_cat(root->cr_dir, module, repodir, - sizeof(repodir)) >= sizeof(repodir)) - fatal("cvs_import_pre_exec: cvs_path_cat overflow"); - - if (mkdir(repodir, 0775) == -1) - fatal("cvs_import_pre_exec: mkdir `%s': %s", - repodir, strerror(errno)); - } else { - rcsnum_tostr(imp_brnum, numbuf, sizeof(numbuf)); - - cvs_sendarg(root, "-b", 0); - cvs_sendarg(root, numbuf, 0); - cvs_logmsg_send(root, cvs_msg); - cvs_sendarg(root, module, 0); - cvs_sendarg(root, vendor, 0); - cvs_sendarg(root, release, 0); - } - return (0); } -static int -cvs_import_post_exec(struct cvsroot *root) +void +cvs_import_local(struct cvs_file *cf) { - char buf[8]; + int l; + int isnew; + struct stat st; + char repo[MAXPATHLEN]; - if (root->cr_method == CVS_METHOD_LOCAL) { - if (conflicts > 0) - snprintf(buf, sizeof(buf), "%d", conflicts); + cvs_log(LP_TRACE, "cvs_import_local(%s)", cf->file_path); - if (verbosity > 0) - cvs_printf("\n%s conflicts created by this import\n\n", - conflicts == 0 ? "No" : buf); - } + cvs_file_classify(cf, 0); - return (CVS_EX_OK); -} + if (cf->file_type == CVS_DIR) { + if (!strcmp(cf->file_path, ".")) + return; -/* - * cvs_import_remote() - * - * Perform the import of a single file or directory. - */ -static int -cvs_import_remote(CVSFILE *cf, void *arg) -{ - size_t sz; - struct cvsroot *root; - char fpath[MAXPATHLEN], repodir[MAXPATHLEN]; - char repo[MAXPATHLEN], date[32]; + if (verbosity > 1) + cvs_log(LP_NOTICE, "Importing %s", cf->file_path); - root = CVS_DIR_ROOT(cf); - if (cvs_path_cat(root->cr_dir, module, repo, sizeof(repo)) >= - sizeof(repo)) - fatal("cvs_import_remove: cvs_path_cat overflow"); + if (mkdir(cf->file_rpath, 0755) == -1 && errno != EEXIST) + fatal("cvs_import_local: %s: %s", cf->file_rpath, + strerror(errno)); - cvs_file_getpath(cf, fpath, sizeof(fpath)); - - if (cf->cf_type == DT_DIR) { - if (!strcmp(cf->cf_name, ".")) - strlcpy(repodir, repo, sizeof(repodir)); - else { - if(cvs_path_cat(repo, fpath, repodir, - sizeof(repodir)) >= sizeof(repodir)) - fatal("cvs_import_remove: cvs_path_cat overflow"); - } - - cvs_sendreq(root, CVS_REQ_DIRECTORY, fpath); - cvs_sendln(root, repodir); - return (0); + return; } - if (dflag == 1) { - ctime_r(&(cf->cf_mtime), date); - sz = strlen(date); - if (sz > 0 && date[sz - 1] == '\n') - date[--sz] = '\0'; - cvs_sendreq(root, CVS_REQ_CHECKINTIME, date); - } + isnew = 1; + l = snprintf(repo, sizeof(repo), "%s/%s/%s/%s%s", + current_cvsroot->cr_dir, cf->file_wd, CVS_PATH_ATTIC, + cf->file_name, RCS_FILE_EXT); + if (l == -1 || l >= (int)sizeof(repo)) + fatal("import_new: overflow"); - cvs_sendreq(root, CVS_REQ_MODIFIED, cf->cf_name); - cvs_sendfile(root, fpath); + if (cf->file_rcs != NULL || stat(repo, &st) != -1) + isnew = 0; - return (0); + if (isnew == 1) + import_new(cf); + else + import_update(cf); } -static int -cvs_import_local(CVSFILE *cf, void *arg) +static void +import_new(struct cvs_file *cf) { - time_t stamp; - char *fcont; - char fpath[MAXPATHLEN], rpath[MAXPATHLEN], repo[MAXPATHLEN]; - const char *comment; - struct stat fst; - struct timeval ts[2]; - struct cvsroot *root; - struct rcs_delta *rdp; - struct rcs_branch *brp; - RCSFILE *rf; - RCSNUM *rev, *brev; BUF *bp; + char *content; + struct rcs_branch *brp; + struct rcs_delta *rdp; + RCSNUM *branch, *brev; - root = CVS_DIR_ROOT(cf); + cvs_log(LP_TRACE, "import_new(%s)", cf->file_name); - if (cvs_path_cat(root->cr_dir, module, repo, sizeof(repo)) >= - sizeof(repo)) - fatal("cvs_import_local: cvs_path_cat overflow"); + if ((branch = rcsnum_parse(import_branch)) == NULL) + fatal("import_new: failed to parse branch"); - cvs_file_getpath(cf, fpath, sizeof(fpath)); + if ((bp = cvs_buf_load(cf->file_path, BUF_AUTOEXT)) == NULL) + fatal("import_new: failed to load %s", cf->file_path); - if (cf->cf_type == DT_DIR) { - if (!strcmp(cf->cf_name, ".")) - strlcpy(rpath, repo, sizeof(rpath)); - else { - if (cvs_path_cat(repo, fpath, rpath, - sizeof(rpath)) >= sizeof(rpath)) - fatal("cvs_import_local: cvs_path_cat overflow"); + cvs_buf_putc(bp, '\0'); + content = cvs_buf_release(bp); - cvs_printf("Importing %s\n", rpath); - if (mkdir(rpath, 0755) == -1) { - cvs_log(LP_ERRNO, "failed to create %s", - rpath); - } - } + if ((brev = rcsnum_brtorev(branch)) == NULL) + fatal("import_new: failed to get first branch revision"); - return (0); - } + cf->repo_fd = open(cf->file_rpath, O_CREAT|O_TRUNC|O_WRONLY); + if (cf->repo_fd < 0) + fatal("import_new: %s: %s", cf->file_rpath, strerror(errno)); - /* - * If -d was given, use the file's last modification time as the - * timestamps for the initial revisions. - */ - if (dflag == 1) { - if (stat(fpath, &fst) == -1) - fatal("cvs_import_local: stat failed on `%s': %s", - fpath, strerror(errno)); + cf->file_rcs = rcs_open(cf->file_rpath, cf->repo_fd, RCS_CREATE, 0444); + if (cf->file_rcs == NULL) + fatal("import_new: failed to create RCS file for %s", + cf->file_path); - stamp = (time_t)fst.st_mtime; + rcs_branch_set(cf->file_rcs, branch); - ts[0].tv_sec = stamp; - ts[0].tv_usec = 0; - ts[1].tv_sec = stamp; - ts[1].tv_usec = 0; - } else - stamp = -1; + if (rcs_sym_add(cf->file_rcs, vendor_tag, branch) == -1) + fatal("import_new: failed to add release tag"); - if (strlcpy(rpath, repo, sizeof(rpath)) >= sizeof(rpath) || - strlcat(rpath, "/", sizeof(rpath)) >= sizeof(rpath) || - strlcat(rpath, fpath, sizeof(rpath)) >= sizeof(rpath) || - strlcat(rpath, RCS_FILE_EXT, sizeof(rpath)) >= sizeof(rpath)) - fatal("cvs_import_local: path truncation"); + if (rcs_sym_add(cf->file_rcs, release_tag, branch) == -1) + fatal("import_new: failed to add vendor tag"); - cvs_printf("N %s\n", fpath); + if (rcs_rev_add(cf->file_rcs, brev, logmsg, -1, NULL) == -1) + fatal("import_new: failed to create first branch revision"); - if ((rf = rcs_open(rpath, RCS_RDWR|RCS_CREATE, 0444)) == NULL) - fatal("cvs_import_local: rcs_open: `%s': %s", rpath, - rcs_errstr(rcs_errno)); + if (rcs_rev_add(cf->file_rcs, RCS_HEAD_REV, logmsg, -1, NULL) == -1) + fatal("import_new: failed to create first revision"); - comment = rcs_comment_lookup(cf->cf_name); - if (comment != NULL) - rcs_comment_set(rf, comment); + if ((rdp = rcs_findrev(cf->file_rcs, cf->file_rcs->rf_head)) == NULL) + fatal("import_new: cannot find newly added revision"); - brev = rcsnum_brtorev(imp_brnum); - if (rcs_rev_add(rf, brev, cvs_msg, stamp, NULL) < 0) { - (void)unlink(rpath); - fatal("cvs_import_local: rcs_rev_add failed: %s", - rcs_errstr(rcs_errno)); - } - - if (rcs_sym_add(rf, release, brev) < 0) { - (void)unlink(rpath); - fatal("cvs_import_local: rcs_sym_add failed: %s", - rcs_errstr(rcs_errno)); - } - - rev = rcsnum_alloc(); - rcsnum_cpy(imp_brnum, rev, 2); - if (rcs_rev_add(rf, rev, cvs_msg, stamp, NULL) < 0) { - (void)unlink(rpath); - fatal("cvs_import_local: rcs_rev_add failed: %s", - rcs_errstr(rcs_errno)); - } - - if (rcs_head_set(rf, rev) < 0) { - (void)unlink(rpath); - fatal("cvs_import_local: rcs_head_set failed: %s", - rcs_errstr(rcs_errno)); - } - - if (rcs_branch_set(rf, imp_brnum) < 0) { - (void)unlink(rpath); - fatal("cvs_import_local: rcs_branch_set failed: %s", - rcs_errstr(rcs_errno)); - } - - if (rcs_sym_add(rf, vendor, imp_brnum) < 0) { - (void)unlink(rpath); - fatal("cvs_import_local: rcs_sym_add failed: %s", - rcs_errstr(rcs_errno)); - } - - /* - * Put the branch revision on the branches list for the first revision. - */ - rdp = rcs_findrev(rf, rev); brp = xmalloc(sizeof(*brp)); brp->rb_num = rcsnum_alloc(); rcsnum_cpy(brev, brp->rb_num, 0); TAILQ_INSERT_TAIL(&(rdp->rd_branches), brp, rb_list); - if ((bp = cvs_buf_load(fpath, BUF_AUTOEXT)) == NULL) { - (void)unlink(rpath); - fatal("cvs_import_local: cvs_buf_load failed"); - } + if (rcs_deltatext_set(cf->file_rcs, + cf->file_rcs->rf_head, content) == -1) + fatal("import_new: failed to set deltatext"); - cvs_buf_putc(bp, '\0'); + rcs_write(cf->file_rcs); + cvs_printf("N %s\n", cf->file_path); - fcont = cvs_buf_release(bp); - - if (rcs_deltatext_set(rf, rev, fcont) < 0) { - (void)unlink(rpath); - fatal("cvs_import_local: rcs_deltatext_set failed"); - } - - /* add the vendor tag and release tag as symbols */ - rcs_close(rf); - - if (dflag ==1 && utimes(rpath, ts) == -1) - cvs_log(LP_ERRNO, "failed to timestamp RCS file"); - - return (0); + rcsnum_free(branch); + rcsnum_free(brev); } -static int -cvs_import_cleanup(void) +static void +import_update(struct cvs_file *cf) { - if (imp_brnum != NULL) - rcsnum_free(imp_brnum); - return (0); + cvs_log(LP_TRACE, "import_update(%s)", cf->file_path); }