summaryrefslogtreecommitdiff
path: root/contrib/cvs/src/checkout.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/cvs/src/checkout.c')
-rw-r--r--contrib/cvs/src/checkout.c178
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)
{