diff options
Diffstat (limited to 'contrib/cvs/src/checkout.c')
-rw-r--r-- | contrib/cvs/src/checkout.c | 178 |
1 files changed, 105 insertions, 73 deletions
diff --git a/contrib/cvs/src/checkout.c b/contrib/cvs/src/checkout.c index fe30695173278..ee3bcb2dc8e08 100644 --- a/contrib/cvs/src/checkout.c +++ b/contrib/cvs/src/checkout.c @@ -130,7 +130,7 @@ checkout (argc, argv) * 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) + if (strcmp (cvs_cmd_name, "export") == 0) { m_type = EXPORT; valid_options = "+Nnk:d:flRQqr:D:"; @@ -177,7 +177,7 @@ checkout (argc, argv) #endif error (1, 0, "-q or -Q must be specified before \"%s\"", - command_name); + cvs_cmd_name); break; case 'l': local = 1; @@ -273,14 +273,6 @@ checkout (argc, argv) 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/Checkin.prog - or CVS/Update.prog) don't get created. Grrr. */ - expand_modules = (!cat && !pipeout && supported_request ("expand-modules")); @@ -323,6 +315,7 @@ checkout (argc, argv) option_with_arg ("-j", join_rev1); if (join_rev2 != NULL) option_with_arg ("-j", join_rev2); + send_arg ("--"); if (expand_modules) { @@ -398,39 +391,55 @@ checkout (argc, argv) /* FIXME: This is and emptydir_name are in checkout.c for historical reasons, probably want to move them. */ +/* int + * safe_location ( char *where ) + * + * Return true if where is a safe destination for a checkout. + * + * INPUTS + * where The requested destination directory. + * + * GLOBALS + * current_parsed_root->directory + * current_parsed_root->isremote + * Used to locate our CVSROOT. + * + * RETURNS + * true If we are running in client mode or if where is not located + * within the CVSROOT. + * false Otherwise. + * + * ERRORS + * Exits with a fatal error message when various events occur, such as not + * being able to resolve a path or failing ot chdir to a path. + */ int safe_location (where) char *where; { char *current; char *where_location; - char hardpath[PATH_MAX+5]; + char *hardpath; size_t hardpath_len; - int x; int retval; -#ifdef HAVE_READLINK - /* FIXME-arbitrary limit: should be retrying this like xgetwd. - But how does readlink let us know that the buffer was too small? - (by returning sizeof hardpath - 1?). */ - x = readlink(current_parsed_root->directory, hardpath, sizeof hardpath - 1); -#else - x = -1; -#endif - if (x == -1) - { - strcpy(hardpath, current_parsed_root->directory); - } - else - { - hardpath[x] = '\0'; - } + if (trace) + (void) fprintf (stderr, "%s-> safe_location( where=%s )\n", + CLIENT_SERVER_STR, + where ? where : "(null)"); + +#ifdef CLIENT_SUPPORT + /* Don't compare remote CVSROOTs to our destination directory. */ + if ( current_parsed_root->isremote ) return 1; +#endif /* CLIENT_SUPPORT */ /* set current - even if where is set we'll need to cd back... */ current = xgetwd (); if (current == NULL) error (1, errno, "could not get working directory"); + hardpath = xresolvepath ( current_parsed_root->directory ); + /* if where is set, set current to where, where - last_component( where ), * or fail, depending on whether the directories exist or not. */ @@ -457,12 +466,16 @@ safe_location (where) char *parent; /* strip the last_component */ - where_location = xstrdup( where ); - parent = last_component( where_location ); + where_location = xstrdup (where); + /* It's okay to cast out the const below since we know we just + * allocated where_location and can do what we like with it. + */ + parent = (char *)last_component (where_location); parent[-1] = '\0'; if( chdir( where_location ) != -1 ) { + free( where_location ); where_location = xgetwd(); if( where_location == NULL ) error( 1, errno, "could not get working directory (nominally `%s')", where_location ); @@ -505,6 +518,7 @@ safe_location (where) else retval = 1; free (current); + free (hardpath); return retval; } @@ -918,52 +932,48 @@ internal error: %s doesn't start with %s in checkout_proc", /* clean up */ free (reposcopy); + /* The top-level CVSADM directory should always be + current_parsed_root->directory. Create it, but only if WHERE is + relative. If WHERE is absolute, our current directory + may not have a thing to do with where the sources are + being checked out. If it does, build_dirs_and_chdir + will take care of creating adm files here. */ + /* FIXME: checking is_absolute (where) is a horrid kludge; + I suspect we probably can just skip the call to + build_one_dir whenever the -d command option was specified + to checkout. */ + + if (!isabsolute (where) && top_level_admin && m_type == CHECKOUT) { - int where_is_absolute = isabsolute (where); - - /* The top-level CVSADM directory should always be - current_parsed_root->directory. Create it, but only if WHERE is - relative. If WHERE is absolute, our current directory - may not have a thing to do with where the sources are - being checked out. If it does, build_dirs_and_chdir - will take care of creating adm files here. */ - /* FIXME: checking where_is_absolute is a horrid kludge; - I suspect we probably can just skip the call to - build_one_dir whenever the -d command option was specified - to checkout. */ - - if (! where_is_absolute && top_level_admin && m_type == CHECKOUT) - { - /* It may be argued that we shouldn't set any sticky - bits for the top-level repository. FIXME? */ - build_one_dir (current_parsed_root->directory, ".", argc <= 1); + /* It may be argued that we shouldn't set any sticky + bits for the top-level repository. FIXME? */ + build_one_dir (current_parsed_root->directory, ".", argc <= 1); #ifdef SERVER_SUPPORT - /* We _always_ want to have a top-level admin - directory. If we're running in client/server mode, - send a "Clear-static-directory" command to make - sure it is created on the client side. (See 5.10 - in cvsclient.dvi to convince yourself that this is - OK.) If this is a duplicate command being sent, it - will be ignored on the client side. */ + /* We _always_ want to have a top-level admin + directory. If we're running in client/server mode, + send a "Clear-static-directory" command to make + sure it is created on the client side. (See 5.10 + in cvsclient.dvi to convince yourself that this is + OK.) If this is a duplicate command being sent, it + will be ignored on the client side. */ - if (server_active) - server_clear_entstat (".", current_parsed_root->directory); + if (server_active) + server_clear_entstat (".", current_parsed_root->directory); #endif - } + } - /* 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 */ + /* 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 (head, argc <= 1) != 0) - { - error (0, 0, "ignoring module %s", omodule); - err = 1; - goto out; - } + if (build_dirs_and_chdir (head, argc <= 1) != 0) + { + error (0, 0, "ignoring module %s", omodule); + err = 1; + goto out; } /* set up the repository (or make sure the old one matches) */ @@ -1086,7 +1096,8 @@ internal error: %s doesn't start with %s in checkout_proc", force_tag_match, 0 /* !local */ , 1 /* update -d */ , aflag, checkout_prune_dirs, pipeout, which, join_rev1, join_rev2, - preload_update_dir, m_type == CHECKOUT); + preload_update_dir, m_type == CHECKOUT, + repository); goto out; } @@ -1142,7 +1153,8 @@ internal error: %s doesn't start with %s in checkout_proc", err += do_update (argc - 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, m_type == CHECKOUT); + join_rev2, preload_update_dir, m_type == CHECKOUT, + repository); out: free (preload_update_dir); preload_update_dir = oldupdate; @@ -1192,8 +1204,28 @@ emptydir_name () } /* Build all the dirs along the path to DIRS with CVS subdirs with appropriate - repositories. If ->repository is NULL, do not create a CVSADM directory - for that subdirectory; just CVS_CHDIR into it. */ + * repositories. If DIRS->repository is NULL or the directory already exists, + * do not create a CVSADM directory for that subdirectory; just CVS_CHDIR into + * it. Frees all storage used by DIRS. + * + * ASSUMPTIONS + * 1. Parent directories will be listed in DIRS before their children. + * 2. At most a single directory will need to be changed at one time. In + * other words, if we are in /a/b/c, and our final destination is + * /a/b/c/d/e/f, then we will build d, then d/e, then d/e/f. + * + * INPUTS + * dirs Simple list composed of dir_to_build structures, listing + * information about directories to build. + * sticky Passed to build_one_dir to tell it whether there are any sticky + * tags or dates to be concerned with. + * + * RETURNS + * 1 on error, 0 otherwise. + * + * ERRORS + * The only nonfatal error this function may return is if the CHDIR fails. + */ static int build_dirs_and_chdir (dirs, sticky) struct dir_to_build *dirs; @@ -1204,7 +1236,7 @@ build_dirs_and_chdir (dirs, sticky) while (dirs != NULL) { - char *dir = last_component (dirs->dirpath); + const char *dir = last_component (dirs->dirpath); if (!dirs->just_chdir) { |