diff options
Diffstat (limited to 'gnu/usr.bin/cvs/cvs/checkout.c')
-rw-r--r-- | gnu/usr.bin/cvs/cvs/checkout.c | 874 |
1 files changed, 0 insertions, 874 deletions
diff --git a/gnu/usr.bin/cvs/cvs/checkout.c b/gnu/usr.bin/cvs/cvs/checkout.c deleted file mode 100644 index bb126dd2de5d7..0000000000000 --- a/gnu/usr.bin/cvs/cvs/checkout.c +++ /dev/null @@ -1,874 +0,0 @@ -/* - * Copyright (c) 1992, Brian Berliner and Jeff Polk - * Copyright (c) 1989-1992, Brian Berliner - * - * You may distribute under the terms of the GNU General Public License as - * specified in the README file that comes with the CVS 1.4 kit. - * - * Create Version - * - * "checkout" creates a "version" of an RCS repository. This version is owned - * totally by the user and is actually an independent copy, to be dealt with - * as seen fit. Once "checkout" has been called in a given directory, it - * never needs to be called again. The user can keep up-to-date by calling - * "update" when he feels like it; this will supply him with a merge of his - * own modifications and the changes made in the RCS original. See "update" - * for details. - * - * "checkout" can be given a list of directories or files to be updated and in - * the case of a directory, will recursivley create any sub-directories that - * exist in the repository. - * - * When the user is satisfied with his own modifications, the present version - * can be committed by "commit"; this keeps the present version in tact, - * usually. - * - * The call is cvs checkout [options] <module-name>... - * - * "checkout" creates a directory ./CVS, in which it keeps its administration, - * in two files, Repository and Entries. The first contains the name of the - * repository. The second contains one line for each registered file, - * consisting of the version number it derives from, its time stamp at - * derivation time and its name. Both files are normal files and can be - * edited by the user, if necessary (when the repository is moved, e.g.) - */ - -#include "cvs.h" - -#ifndef lint -static const char rcsid[] = "$CVSid: @(#)checkout.c 1.78 94/10/07 $"; -USE(rcsid); -#endif - -static char *findslash PROTO((char *start, char *p)); -static int build_dirs_and_chdir PROTO((char *dir, char *prepath, char *realdir, - int sticky)); -static int checkout_proc PROTO((int *pargc, char **argv, char *where, - char *mwhere, char *mfile, int shorten, - int local_specified, char *omodule, - char *msg)); -static int safe_location PROTO((void)); - -static const char *const checkout_usage[] = -{ - "Usage:\n %s %s [-ANPcflnps] [-r rev | -D date] [-d dir] [-k kopt] modules...\n", - "\t-A\tReset any sticky tags/date/kopts.\n", - "\t-N\tDon't shorten module paths if -d specified.\n", - "\t-P\tPrune empty directories.\n", - "\t-c\t\"cat\" the module database.\n", - "\t-f\tForce a head revision match if tag/date not found.\n", - "\t-l\tLocal directory only, not recursive\n", - "\t-n\tDo not run module program (if any).\n", - "\t-p\tCheck out files to standard output.\n", - "\t-s\tLike -c, but include module status.\n", - "\t-r rev\tCheck out revision or tag. (implies -P)\n", - "\t-D date\tCheck out revisions as of date. (implies -P)\n", - "\t-d dir\tCheck out into dir instead of module name.\n", - "\t-k kopt\tUse RCS kopt -k option on checkout.\n", - "\t-j rev\tMerge in changes made between current revision and rev.\n", - NULL -}; - -static const char *const export_usage[] = -{ - "Usage: %s %s [-NPfln] [-r rev | -D date] [-d dir] [-k kopt] module...\n", - "\t-N\tDon't shorten module paths if -d specified.\n", - "\t-f\tForce a head revision match if tag/date not found.\n", - "\t-l\tLocal directory only, not recursive\n", - "\t-n\tDo not run module program (if any).\n", - "\t-r rev\tCheck out revision or tag.\n", - "\t-D date\tCheck out revisions as of date.\n", - "\t-d dir\tCheck out into dir instead of module name.\n", - "\t-k kopt\tUse RCS kopt -k option on checkout.\n", - NULL -}; - -static int checkout_prune_dirs; -static int force_tag_match = 1; -static int pipeout; -static int aflag; -static char *options = NULL; -static char *tag = NULL; -static char *date = NULL; -static char *join_rev1 = NULL; -static char *join_rev2 = NULL; -static char *preload_update_dir = NULL; - -int -checkout (argc, argv) - int argc; - char **argv; -{ - int i; - int c; - DBM *db; - int cat = 0, err = 0, status = 0; - int run_module_prog = 1; - int local = 0; - int shorten = -1; - char *where = NULL; - char *valid_options; - const char *const *valid_usage; - enum mtype m_type; - - /* - * A smaller subset of options are allowed for the export command, which - * is essentially like checkout, except that it hard-codes certain - * options to be default (like -kv) and takes care to remove the CVS - * directory when it has done its duty - */ - if (strcmp (command_name, "export") == 0) - { - m_type = EXPORT; - valid_options = "Nnk:d:flRQqr:D:"; - valid_usage = export_usage; - } - else - { - m_type = CHECKOUT; - valid_options = "ANnk:d:flRpQqcsr:D:j:P"; - valid_usage = checkout_usage; - } - - if (argc == -1) - usage (valid_usage); - - ign_setup (); - wrap_setup (); - - optind = 1; - while ((c = getopt (argc, argv, valid_options)) != -1) - { - switch (c) - { - case 'A': - aflag = 1; - break; - case 'N': - shorten = 0; - break; - case 'k': - if (options) - free (options); - options = RCS_check_kflag (optarg); - break; - case 'n': - run_module_prog = 0; - break; - case 'Q': - case 'q': -#ifdef SERVER_SUPPORT - /* The CVS 1.5 client sends these options (in addition to - Global_option requests), so we must ignore them. */ - if (!server_active) -#endif - error (1, 0, - "-q or -Q must be specified before \"%s\"", - command_name); - break; - case 'l': - local = 1; - break; - case 'R': - local = 0; - break; - case 'P': - checkout_prune_dirs = 1; - break; - case 'p': - pipeout = 1; - run_module_prog = 0; /* don't run module prog when piping */ - noexec = 1; /* so no locks will be created */ - break; - case 'c': - cat = 1; - break; - case 'd': - where = optarg; - if (shorten == -1) - shorten = 1; - break; - case 's': - status = 1; - break; - case 'f': - force_tag_match = 0; - break; - case 'r': - tag = optarg; - checkout_prune_dirs = 1; - break; - case 'D': - date = Make_Date (optarg); - checkout_prune_dirs = 1; - break; - case 'j': - if (join_rev2) - error (1, 0, "only two -j options can be specified"); - if (join_rev1) - join_rev2 = optarg; - else - join_rev1 = optarg; - break; - case '?': - default: - usage (valid_usage); - break; - } - } - argc -= optind; - argv += optind; - - if (shorten == -1) - shorten = 0; - - if ((!(cat + status) && argc == 0) || ((cat + status) && argc != 0) - || (tag && date)) - usage (valid_usage); - - if (where && pipeout) - error (1, 0, "-d and -p are mutually exclusive"); - - if (strcmp (command_name, "export") == 0) - { - if (!tag && !date) - { - error (0, 0, "must specify a tag or date"); - usage (valid_usage); - } - if (tag && isdigit (tag[0])) - error (1, 0, "tag `%s' must be a symbolic tag", tag); -/* - * mhy 950615: -kv doesn't work for binaries with RCS keywords. - * Instead use the default provided in the RCS file (-ko for binaries). - */ -#if 0 - if (!options) - options = RCS_check_kflag ("v");/* -kv is default */ -#endif - } - - if (!safe_location()) { - error(1, 0, "Cannot check out files into the repository itself"); - } - -#ifdef CLIENT_SUPPORT - if (client_active) - { - int expand_modules; - - start_server (); - - ign_setup (); - - /* We have to expand names here because the "expand-modules" - directive to the server has the side-effect of having the - server send the check-in and update programs for the - various modules/dirs requested. If we turn this off and - simply request the names of the modules and directories (as - below in !expand_modules), those files (CVS/Checking.prog - or CVS/Update.prog) don't get created. Grrr. */ - - expand_modules = (!cat && !status && !pipeout - && supported_request ("expand-modules")); - - if (expand_modules) - { - /* This is done here because we need to read responses - from the server before we send the command checkout or - export files. */ - - client_expand_modules (argc, argv, local); - } - - if (!run_module_prog) send_arg ("-n"); - if (local) send_arg ("-l"); - if (pipeout) send_arg ("-p"); - if (!force_tag_match) send_arg ("-f"); - if (aflag) - send_arg("-A"); - if (!shorten) - send_arg("-N"); - if (checkout_prune_dirs && strcmp (command_name, "export") != 0) - send_arg("-P"); - client_prune_dirs = checkout_prune_dirs; - if (cat) - send_arg("-c"); - if (where != NULL) - { - option_with_arg ("-d", where); - } - if (status) - send_arg("-s"); - if (strcmp (command_name, "export") != 0 - && options != NULL - && options[0] != '\0') - send_arg (options); - option_with_arg ("-r", tag); - if (date) - client_senddate (date); - if (join_rev1 != NULL) - option_with_arg ("-j", join_rev1); - if (join_rev2 != NULL) - option_with_arg ("-j", join_rev2); - - if (expand_modules) - { - client_send_expansions (local); - } - else - { - int i; - for (i = 0; i < argc; ++i) - send_arg (argv[i]); - client_nonexpanded_setup (); - } - - if (fprintf - (to_server, - strcmp (command_name, "export") == 0 ? "export\n" : "co\n") - < 0) - error (1, errno, "writing to server"); - - return get_responses_and_close (); - } -#endif - - if (cat || status) - { - cat_module (status); - return (0); - } - db = open_module (); - - /* - * if we have more than one argument and where was specified, we make the - * where, cd into it, and try to shorten names as much as possible. - * Otherwise, we pass the where as a single argument to do_module. - */ - if (argc > 1 && where != NULL) - { - char repository[PATH_MAX]; - - (void) CVS_MKDIR (where, 0777); - if (chdir (where) < 0) - error (1, errno, "cannot chdir to %s", where); - preload_update_dir = xstrdup (where); - where = (char *) NULL; - if (!isfile (CVSADM)) - { - (void) sprintf (repository, "%s/%s/%s", CVSroot, CVSROOTADM, - CVSNULLREPOS); - if (!isfile (repository)) - { - mode_t omask; - omask = umask (cvsumask); - (void) CVS_MKDIR (repository, 0777); - (void) umask (omask); - } - - /* I'm not sure whether this check is redundant. */ - if (!isdir (repository)) - error (1, 0, "there is no repository %s", repository); - - Create_Admin (".", where, repository, - (char *) NULL, (char *) NULL); - if (!noexec) - { - FILE *fp; - - fp = open_file (CVSADM_ENTSTAT, "w+"); - if (fclose(fp) == EOF) - error(1, errno, "cannot close %s", CVSADM_ENTSTAT); -#ifdef SERVER_SUPPORT - if (server_active) - server_set_entstat (preload_update_dir, repository); -#endif - } - } - } - - /* - * if where was specified (-d) and we have not taken care of it already - * with the multiple arg stuff, and it was not a simple directory name - * but rather a path, we strip off everything but the last component and - * attempt to cd to the indicated place. where then becomes simply the - * last component - */ - if (where != NULL && strchr (where, '/') != NULL) - { - char *slash; - - slash = strrchr (where, '/'); - *slash = '\0'; - - if (chdir (where) < 0) - error (1, errno, "cannot chdir to %s", where); - - preload_update_dir = xstrdup (where); - - where = slash + 1; - if (*where == '\0') - where = NULL; - } - - for (i = 0; i < argc; i++) - err += do_module (db, argv[i], m_type, "Updating", checkout_proc, - where, shorten, local, run_module_prog, - (char *) NULL); - close_module (db); - return (err); -} - -static int -safe_location () -{ - char current[PATH_MAX]; - char hardpath[PATH_MAX+5]; - int x; - - x = readlink(CVSroot, hardpath, sizeof hardpath - 1); - if (x == -1) - { - strcpy(hardpath, CVSroot); - } - hardpath[x] = '\0'; - getwd (current); - if (strncmp(current, hardpath, strlen(hardpath)) == 0) - { - return (0); - } - return (1); -} - -/* - * process_module calls us back here so we do the actual checkout stuff - */ -/* ARGSUSED */ -static int -checkout_proc (pargc, argv, where, mwhere, mfile, shorten, - local_specified, omodule, msg) - int *pargc; - char **argv; - char *where; - char *mwhere; - char *mfile; - int shorten; - int local_specified; - char *omodule; - char *msg; -{ - int err = 0; - int which; - char *cp; - char *cp2; - char repository[PATH_MAX]; - char xwhere[PATH_MAX]; - char *oldupdate = NULL; - char *prepath; - char *realdirs; - - /* - * OK, so we're doing the checkout! Our args are as follows: - * argc,argv contain either dir or dir followed by a list of files - * where contains where to put it (if supplied by checkout) - * mwhere contains the module name or -d from module file - * mfile says do only that part of the module - * shorten = TRUE says shorten as much as possible - * omodule is the original arg to do_module() - */ - - /* set up the repository (maybe) for the bottom directory */ - (void) sprintf (repository, "%s/%s", CVSroot, argv[0]); - - /* save the original value of preload_update_dir */ - if (preload_update_dir != NULL) - oldupdate = xstrdup (preload_update_dir); - - /* fix up argv[] for the case of partial modules */ - if (mfile != NULL) - { - char file[PATH_MAX]; - - /* if mfile is really a path, straighten it out first */ - if ((cp = strrchr (mfile, '/')) != NULL) - { - *cp = 0; - (void) strcat (repository, "/"); - (void) strcat (repository, mfile); - - /* - * Now we need to fill in the where correctly. if !shorten, tack - * the rest of the path onto where if where is filled in - * otherwise tack the rest of the path onto mwhere and make that - * the where - * - * If shorten is enabled, we might use mwhere to set where if - * nobody set it yet, so we'll need to setup mwhere as the last - * component of the path we are tacking onto repository - */ - if (!shorten) - { - if (where != NULL) - (void) sprintf (xwhere, "%s/%s", where, mfile); - else - (void) sprintf (xwhere, "%s/%s", mwhere, mfile); - where = xwhere; - } - else - { - char *slash; - - if ((slash = strrchr (mfile, '/')) != NULL) - mwhere = slash + 1; - else - mwhere = mfile; - } - mfile = cp + 1; - } - - (void) sprintf (file, "%s/%s", repository, mfile); - if (isdir (file)) - { - - /* - * The portion of a module was a directory, so kludge up where to - * be the subdir, and fix up repository - */ - (void) strcpy (repository, file); - - /* - * At this point, if shorten is not enabled, we make where either - * where with mfile concatenated, or if where hadn't been set we - * set it to mwhere with mfile concatenated. - * - * If shorten is enabled and where hasn't been set yet, then where - * becomes mfile - */ - if (!shorten) - { - if (where != NULL) - (void) sprintf (xwhere, "%s/%s", where, mfile); - else - (void) sprintf (xwhere, "%s/%s", mwhere, mfile); - where = xwhere; - } - else if (where == NULL) - where = mfile; - } - else - { - int i; - - /* - * The portion of a module was a file, so kludge up argv to be - * correct - */ - for (i = 1; i < *pargc; i++)/* free the old ones */ - free (argv[i]); - argv[1] = xstrdup (mfile); /* set up the new one */ - *pargc = 2; - - /* where gets mwhere if where isn't set */ - if (where == NULL) - where = mwhere; - } - } - - /* - * if shorten is enabled and where isn't specified yet, we pluck the last - * directory component of argv[0] and make it the where - */ - if (shorten && where == NULL) - { - if ((cp = strrchr (argv[0], '/')) != NULL) - { - (void) strcpy (xwhere, cp + 1); - where = xwhere; - } - } - - /* if where is still NULL, use mwhere if set or the argv[0] dir */ - if (where == NULL) - { - if (mwhere) - where = mwhere; - else - { - (void) strcpy (xwhere, argv[0]); - where = xwhere; - } - } - - if (preload_update_dir != NULL) - { - char tmp[PATH_MAX]; - - (void) sprintf (tmp, "%s/%s", preload_update_dir, where); - free (preload_update_dir); - preload_update_dir = xstrdup (tmp); - } - else - preload_update_dir = xstrdup (where); - - /* - * At this point, where is the directory we want to build, repository is - * the repository for the lowest level of the path. - */ - - /* - * If we are sending everything to stdout, we can skip a whole bunch of - * work from here - */ - if (!pipeout) - { - - /* - * We need to tell build_dirs not only the path we want it to build, - * but also the repositories we want it to populate the path with. To - * accomplish this, we pass build_dirs a ``real path'' with valid - * repositories and a string to pre-pend based on how many path - * elements exist in where. Big Black Magic - */ - prepath = xstrdup (repository); - cp = strrchr (where, '/'); - cp2 = strrchr (prepath, '/'); - while (cp != NULL) - { - cp = findslash (where, cp - 1); - cp2 = findslash (prepath, cp2 - 1); - } - *cp2 = '\0'; - realdirs = cp2 + 1; - - /* - * build dirs on the path if necessary and leave us in the bottom - * directory (where if where was specified) doesn't contain a CVS - * subdir yet, but all the others contain CVS and Entries.Static - * files - */ - if (build_dirs_and_chdir (where, prepath, realdirs, *pargc <= 1) != 0) - { - error (0, 0, "ignoring module %s", omodule); - free (prepath); - free (preload_update_dir); - preload_update_dir = oldupdate; - return (1); - } - - /* clean up */ - free (prepath); - - /* set up the repository (or make sure the old one matches) */ - if (!isfile (CVSADM)) - { - FILE *fp; - - if (!noexec && *pargc > 1) - { - /* I'm not sure whether this check is redundant. */ - if (!isdir (repository)) - error (1, 0, "there is no repository %s", repository); - - Create_Admin (".", where, repository, - (char *) NULL, (char *) NULL); - fp = open_file (CVSADM_ENTSTAT, "w+"); - if (fclose(fp) == EOF) - error(1, errno, "cannot close %s", CVSADM_ENTSTAT); -#ifdef SERVER_SUPPORT - if (server_active) - server_set_entstat (where, repository); -#endif - } - else - { - /* I'm not sure whether this check is redundant. */ - if (!isdir (repository)) - error (1, 0, "there is no repository %s", repository); - - Create_Admin (".", where, repository, tag, date); - } - } - else - { - char *repos; - - /* get the contents of the previously existing repository */ - repos = Name_Repository ((char *) NULL, preload_update_dir); - if (fncmp (repository, repos) != 0) - { - error (0, 0, "existing repository %s does not match %s", - repos, repository); - error (0, 0, "ignoring module %s", omodule); - free (repos); - free (preload_update_dir); - preload_update_dir = oldupdate; - return (1); - } - free (repos); - } - } - - /* - * If we are going to be updating to stdout, we need to cd to the - * repository directory so the recursion processor can use the current - * directory as the place to find repository information - */ - if (pipeout) - { - if (chdir (repository) < 0) - { - error (0, errno, "cannot chdir to %s", repository); - free (preload_update_dir); - preload_update_dir = oldupdate; - return (1); - } - which = W_REPOS; - } - else - which = W_LOCAL | W_REPOS; - - if (tag != NULL || date != NULL) - which |= W_ATTIC; - - /* - * if we are going to be recursive (building dirs), go ahead and call the - * update recursion processor. We will be recursive unless either local - * only was specified, or we were passed arguments - */ - if (!(local_specified || *pargc > 1)) - { - if (strcmp (command_name, "export") != 0 && !pipeout) - history_write ('O', preload_update_dir, tag ? tag : date, where, - repository); - err += do_update (0, (char **) NULL, options, tag, date, - force_tag_match, 0 /* !local */ , - 1 /* update -d */ , aflag, checkout_prune_dirs, - pipeout, which, join_rev1, join_rev2, - preload_update_dir); - free (preload_update_dir); - preload_update_dir = oldupdate; - return (err); - } - - if (!pipeout) - { - int i; - List *entries; - - /* we are only doing files, so register them */ - entries = Entries_Open (0); - for (i = 1; i < *pargc; i++) - { - char line[MAXLINELEN]; - char *user; - Vers_TS *vers; - - user = argv[i]; - vers = Version_TS (repository, options, tag, date, user, - force_tag_match, 0, entries, (List *) NULL); - if (vers->ts_user == NULL) - { - (void) sprintf (line, "Initial %s", user); - Register (entries, user, vers->vn_rcs ? vers->vn_rcs : "0", - line, vers->options, vers->tag, - vers->date, (char *) 0); - } - freevers_ts (&vers); - } - - Entries_Close (entries); - } - - /* Don't log "export", just regular "checkouts" */ - if (strcmp (command_name, "export") != 0 && !pipeout) - history_write ('O', preload_update_dir, (tag ? tag : date), where, - repository); - - /* go ahead and call update now that everything is set */ - err += do_update (*pargc - 1, argv + 1, options, tag, date, - force_tag_match, local_specified, 1 /* update -d */, - aflag, checkout_prune_dirs, pipeout, which, join_rev1, - join_rev2, preload_update_dir); - free (preload_update_dir); - preload_update_dir = oldupdate; - return (err); -} - -static char * -findslash (start, p) - char *start; - char *p; -{ - while (p >= start && *p != '/') - p--; - if (p < start) - return (NULL); - else - return (p); -} - -/* - * build all the dirs along the path to dir with CVS subdirs with appropriate - * repositories and Entries.Static files - */ -static int -build_dirs_and_chdir (dir, prepath, realdir, sticky) - char *dir; - char *prepath; - char *realdir; - int sticky; -{ - FILE *fp; - char repository[PATH_MAX]; - char path[PATH_MAX]; - char path2[PATH_MAX]; - char *slash; - char *slash2; - char *cp; - char *cp2; - - (void) strcpy (path, dir); - (void) strcpy (path2, realdir); - for (cp = path, cp2 = path2; - (slash = strchr (cp, '/')) != NULL && (slash2 = strchr (cp2, '/')) != NULL; - cp = slash + 1, cp2 = slash2 + 1) - { - *slash = '\0'; - *slash2 = '\0'; - (void) CVS_MKDIR (cp, 0777); - if (chdir (cp) < 0) - { - error (0, errno, "cannot chdir to %s", cp); - return (1); - } - if (!isfile (CVSADM) && strcmp (command_name, "export") != 0) - { - (void) sprintf (repository, "%s/%s", prepath, path2); - /* I'm not sure whether this check is redundant. */ - if (!isdir (repository)) - error (1, 0, "there is no repository %s", repository); - Create_Admin (".", cp, repository, sticky ? (char *) NULL : tag, - sticky ? (char *) NULL : date); - if (!noexec) - { - fp = open_file (CVSADM_ENTSTAT, "w+"); - if (fclose(fp) == EOF) - error(1, errno, "cannot close %s", CVSADM_ENTSTAT); -#ifdef SERVER_SUPPORT - if (server_active) - server_set_entstat (path, repository); -#endif - } - } - *slash = '/'; - *slash2 = '/'; - } - (void) CVS_MKDIR (cp, 0777); - if (chdir (cp) < 0) - { - error (0, errno, "cannot chdir to %s", cp); - return (1); - } - return (0); -} |