summaryrefslogtreecommitdiffstats
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.c128
1 files changed, 103 insertions, 25 deletions
diff --git a/contrib/cvs/src/checkout.c b/contrib/cvs/src/checkout.c
index 86dc951..6b1f769 100644
--- a/contrib/cvs/src/checkout.c
+++ b/contrib/cvs/src/checkout.c
@@ -82,18 +82,18 @@ static const char *const export_usage[] =
};
static int checkout_prune_dirs;
-static int force_tag_match = 1;
+static int force_tag_match;
static int pipeout;
static int aflag;
-static char *options = NULL;
-static char *tag = NULL;
-static int tag_validated = 0;
-static char *date = NULL;
-static char *join_rev1 = NULL;
-static char *join_rev2 = NULL;
-static int join_tags_validated = 0;
-static char *preload_update_dir = NULL;
-static char *history_name = NULL;
+static char *options;
+static char *tag;
+static int tag_validated;
+static char *date;
+static char *join_rev1;
+static char *join_rev2;
+static int join_tags_validated;
+static char *preload_update_dir;
+static char *history_name;
static enum mtype m_type;
int
@@ -112,6 +112,18 @@ checkout (argc, argv)
char *valid_options;
const char *const *valid_usage;
+ /* initialize static options */
+ force_tag_match = 1;
+ if (options)
+ {
+ free (options);
+ options = NULL;
+ }
+ tag = date = join_rev1 = join_rev2 = preload_update_dir = NULL;
+ history_name = NULL;
+ tag_validated = join_tags_validated = 0;
+
+
/*
* A smaller subset of options are allowed for the export command, which
* is essentially like checkout, except that it hard-codes certain
@@ -248,7 +260,7 @@ checkout (argc, argv)
}
#endif
- if (!cat && !safe_location()) {
+ if (!cat && !pipeout && !safe_location( where )) {
error(1, 0, "Cannot check out files into the repository itself");
}
@@ -333,7 +345,10 @@ checkout (argc, argv)
{
cat_module (status);
if (options)
+ {
free (options);
+ options = NULL;
+ }
return (0);
}
db = open_module ();
@@ -351,17 +366,17 @@ checkout (argc, argv)
/* If we will be calling history_write, work out the name to pass
it. */
- if (m_type == CHECKOUT && !pipeout)
+ if (!pipeout)
{
- if (tag && date)
+ if (!date)
+ history_name = tag;
+ else if (!tag)
+ history_name = date;
+ else
{
history_name = xmalloc (strlen (tag) + strlen (date) + 2);
sprintf (history_name, "%s:%s", tag, date);
}
- else if (tag)
- history_name = tag;
- else
- history_name = date;
}
@@ -371,7 +386,12 @@ checkout (argc, argv)
(char *) NULL);
close_module (db);
if (options)
+ {
free (options);
+ options = NULL;
+ }
+ if (history_name != tag && history_name != date && history_name != NULL)
+ free (history_name);
return (err);
}
@@ -379,9 +399,11 @@ checkout (argc, argv)
reasons, probably want to move them. */
int
-safe_location ()
+safe_location (where)
+ char *where;
{
char *current;
+ char *where_location;
char hardpath[PATH_MAX+5];
size_t hardpath_len;
int x;
@@ -403,9 +425,68 @@ safe_location ()
{
hardpath[x] = '\0';
}
+
+ /* 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");
+
+ /* if where is set, set current to where, where - last_component( where ),
+ * or fail, depending on whether the directories exist or not.
+ */
+ if( where != NULL )
+ {
+ if( chdir( where ) != -1 )
+ {
+ /* where */
+ where_location = xgetwd();
+ if( where_location == NULL )
+ error( 1, errno, "could not get working directory" );
+
+ if( chdir( current ) == -1 )
+ error( 1, errno, "could not change directory to `%s'", current );
+
+ free( current );
+ current = where_location;
+ }
+ else if( errno == ENOENT )
+ {
+ if ( last_component( where ) != where )
+ {
+ /* where - last_component( where ) */
+ char *parent;
+
+ /* strip the last_component */
+ where_location = strdup( where );
+ parent = last_component( where_location );
+ parent[-1] = '\0';
+
+ if( chdir( where_location ) != -1 )
+ {
+ where_location = xgetwd();
+ if( where_location == NULL )
+ error( 1, errno, "could not get working directory (nominally `%s')", where_location );
+
+ if( chdir( current ) == -1 )
+ error( 1, errno, "could not change directory to `%s'", current );
+
+ free( current );
+ current = where_location;
+ }
+ else
+ /* fail */
+ error( 1, errno, "could not change directory to requested checkout directory `%s'", where_location );
+ }
+ /* else: ERRNO == ENOENT & last_component(where) == where
+ * for example, 'cvs co -d newdir module', where newdir hasn't
+ * been created yet, so leave current set to '.' and check that
+ */
+ }
+ else
+ /* fail */
+ error( 1, errno, "could not change directory to requested checkout directory `%s'", where );
+ }
+
hardpath_len = strlen (hardpath);
if (strlen (current) >= hardpath_len
&& strncmp (current, hardpath, hardpath_len) == 0)
@@ -851,7 +932,7 @@ internal error: %s doesn't start with %s in checkout_proc",
build_one_dir whenever the -d command option was specified
to checkout. */
- if (! where_is_absolute && top_level_admin)
+ 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? */
@@ -998,12 +1079,9 @@ internal error: %s doesn't start with %s in checkout_proc",
*/
if (!(local_specified || argc > 1))
{
- if (m_type == CHECKOUT && !pipeout)
- history_write ('O', preload_update_dir, history_name, where,
- repository);
- else if (m_type == EXPORT && !pipeout)
- history_write ('E', preload_update_dir, tag ? tag : date, where,
- repository);
+ if (!pipeout)
+ history_write (m_type == CHECKOUT ? 'O' : 'E', preload_update_dir,
+ history_name, where, repository);
err += do_update (0, (char **) NULL, options, tag, date,
force_tag_match, 0 /* !local */ ,
1 /* update -d */ , aflag, checkout_prune_dirs,
OpenPOWER on IntegriCloud