Index: CMT/HEAD/ChangeLog
===================================================================
--- CMT/HEAD/ChangeLog	(revision 44)
+++ CMT/HEAD/ChangeLog	(revision 45)
@@ -1,2 +1,26 @@
+2005-05-02  Christian Arnault  <arnault@lal.in2p3.fr> 272
+
+	* source/cmt_cvs.cxx: Adding CMTPATH internal management
+	Improve broadcast operation after recursive checkouts
+
+2005-05-01  Christian Arnault  <arnault@lal.in2p3.fr> 272
+
+	* mgr/Makefile (pacman): Create the pacman file for that version.
+
+	* mgr/CMT.pacman: Migrate to Pacman3
+
+	* source/cmt_cvs.cxx: Supporting project checkout
+	recursive project checkouts
+	without_version_directory mode
+	container statements in project files.
+	alias version directory
+	Various cleanup and restructuring operations
+
+	* mgr/requirements: Adapt for shared libs on CYGWIN (thanks to Guy Barrand)
+
+	* src/setup.zsh: Add cmt subprojects command
+
+	* src/setup.tcsh: Add cmt subprojects command
+
 2005-04-26  Christian Arnault  <arnault@lal.in2p3.fr> 271
 
Index: CMT/HEAD/mgr/CMT.pacman
===================================================================
--- CMT/HEAD/mgr/CMT.pacman	(revision 44)
+++ CMT/HEAD/mgr/CMT.pacman	(revision 45)
@@ -5,31 +5,23 @@
 #-----------------------------------------------------------
 
-#
-#   CMT installation and setup.
-#
-#      (from Saul Youssef himself)
-#
-description  = 'CMT <version>'
-url          = 'http://www.cmtsite.org'
+description ('CMT <version>')
+packageName ('CMT')
+version ('<version>')
 
-download     = {'unix':'CMT<version>.tar.gz'}
-source       = 'http://www.cmtsite.org/<version>/'
+{
+    platformGE ('Linux') ; downloadUntar ('http://www.cmtsite.org/<version>/CMT<version>Linux-i686.tar.gz', 'CMTBASE')
+  OR 
+    platformGE ('Cygwin') ; downloadUntar ('http://www.cmtsite.org/<version>/CMT<version>CYGWIN_NT-5.1-i686', 'CMTBASE')
+  OR
+    downloadUntar ('http://www.cmtsite.org/<version>/CMT<version>.tar.gz', 'CMTBASE')
+}
 
-inpath       = ['gcc','make']
+cd ('$CMTBASE/<version>/mgr')
+shellOutputContains ('INSTALL', 'CMT installation terminated')
+{
+  shellOutputContains ('. setup.sh; cmt version', '<version>') 
+    OR shell ('. setup.sh; gmake') 
+}
+shellOutputContains ('. setup.sh; cmt version', '<version>')
+cd ()
 
-#paths        = [['PATH','$PACMAN_INSTALLATION/CMT/<version>/mgr']]
-enviros      = [['CMTROOT',''],['CMTCONFIG','i386_linux24'],['CMTBIN','Linux'],['CLASSPATH','java']]
-localdoc     = 'doc/CMT.htm'
-#
-#   This turns off using the root directory extracted from tar.
-#
-usePackageRoot = 0
-#
-#   ...so I cd from the installation area by hand before each shell command.
-#
-install      = { '*': ['cd CMT/<version>/mgr; ./INSTALL'] }
-setup         = ["source ${PACMAN_INSTALLATION}/CMT/<version>/mgr/setup.SHELL"]
-#
-#  since usePackageRoot=0, I have to clean up by hand
-#
-uninstall    = ['rm -r -f CMT CMT<version>.tar']
Index: CMT/HEAD/mgr/Makefile
===================================================================
--- CMT/HEAD/mgr/Makefile	(revision 44)
+++ CMT/HEAD/mgr/Makefile	(revision 45)
@@ -209,4 +209,10 @@
 #        echo '  <tr><td><a href="CMT-'$${version}'-1.i386.rpm">RPM for redhat 7.2</a></td></tr>' >>doc/CMTDownload.html;
 
+#---------------------------------------------------------
+# Construct the pacman file from the generic form
+#---------------------------------------------------------
+pacman ::
+	version=`cmt version`; \
+	sed -e 's#<version>#'"$${version}"'#g' CMT.pacman >CMT-$${version}.pacman
 
 #---------------------------------------------------------
Index: CMT/HEAD/mgr/cmt_dependencies.make
===================================================================
--- CMT/HEAD/mgr/cmt_dependencies.make	(revision 44)
+++ CMT/HEAD/mgr/cmt_dependencies.make	(revision 45)
@@ -17,5 +17,5 @@
 cmt_pattern_cxx_dependencies =  ../source/cmt_pattern.cxx   ../source/cmt_std.h   ../source/cmt_string.h   ../source/cmt_vector.h   ../source/cmt_parser.h   ../source/cmt_regexp.h   ../source/cmt_system.h   ../source/cmt.h   ../source/cmt_map.h   ../source/cmt_pattern.h   ../source/cmt_include.h   ../source/cmt_script.h   ../source/cmt_scope_section.h   ../source/cmt_use.h   ../source/cmt_branch.h   ../source/cmt_fragment.h   ../source/cmt_group.h   ../source/cmt_constituent.h   ../source/cmt_language.h   ../source/cmt_tag.h   ../source/cmt_symbol.h   ../source/cmt_awk.h   ../source/cmt_project.h   ../source/cmt_cmtpath_pattern.h   ../source/cmt_database.h   ../source/cmt_error.h   ../source/cmt_syntax.h 
 cmt_language_cxx_dependencies =  ../source/cmt_language.cxx   ../source/cmt_std.h   ../source/cmt_string.h   ../source/cmt_vector.h   ../source/cmt_regexp.h   ../source/cmt_system.h   ../source/cmt.h   ../source/cmt_parser.h   ../source/cmt_fragment.h   ../source/cmt_language.h   ../source/cmt_branch.h   ../source/cmt_group.h   ../source/cmt_constituent.h   ../source/cmt_map.h   ../source/cmt_pattern.h   ../source/cmt_include.h   ../source/cmt_script.h   ../source/cmt_scope_section.h   ../source/cmt_use.h   ../source/cmt_tag.h   ../source/cmt_symbol.h   ../source/cmt_awk.h   ../source/cmt_project.h   ../source/cmt_cmtpath_pattern.h   ../source/cmt_database.h 
-cmt_cvs_cxx_dependencies =  ../source/cmt_cvs.cxx   ../source/cmt_std.h   ../source/cmt_string.h   ../source/cmt_vector.h   ../source/cmt_parser.h   ../source/cmt_regexp.h   ../source/cmt_system.h   ../source/cmt.h   ../source/cmt_cvs.h   ../source/cmt_awk.h   ../source/cmt_map.h   ../source/cmt_include.h   ../source/cmt_script.h   ../source/cmt_pattern.h   ../source/cmt_scope_section.h   ../source/cmt_use.h   ../source/cmt_tag.h   ../source/cmt_symbol.h 
+cmt_cvs_cxx_dependencies =  ../source/cmt_cvs.cxx   ../source/cmt_std.h   ../source/cmt_string.h   ../source/cmt_vector.h   ../source/cmt_parser.h   ../source/cmt_regexp.h   ../source/cmt_system.h   ../source/cmt.h   ../source/cmt_cvs.h   ../source/cmt_awk.h   ../source/cmt_map.h   ../source/cmt_include.h   ../source/cmt_script.h   ../source/cmt_pattern.h   ../source/cmt_scope_section.h   ../source/cmt_use.h   ../source/cmt_tag.h   ../source/cmt_symbol.h   ../source/cmt_project.h 
 cmt_group_cxx_dependencies =  ../source/cmt_group.cxx   ../source/cmt_std.h   ../source/cmt_string.h   ../source/cmt_vector.h   ../source/cmt_regexp.h   ../source/cmt_system.h   ../source/cmt.h   ../source/cmt_parser.h   ../source/cmt_group.h   ../source/cmt_branch.h   ../source/cmt_fragment.h   ../source/cmt_constituent.h   ../source/cmt_language.h   ../source/cmt_map.h   ../source/cmt_pattern.h   ../source/cmt_include.h   ../source/cmt_script.h   ../source/cmt_scope_section.h   ../source/cmt_use.h   ../source/cmt_tag.h   ../source/cmt_symbol.h   ../source/cmt_awk.h   ../source/cmt_project.h   ../source/cmt_cmtpath_pattern.h   ../source/cmt_database.h 
 cmt_database_cxx_dependencies =  ../source/cmt_database.cxx   ../source/cmt_vector.h   ../source/cmt_std.h   ../source/cmt_string.h   ../source/cmt_regexp.h   ../source/cmt_system.h   ../source/cmt.h   ../source/cmt_parser.h   ../source/cmt_branch.h   ../source/cmt_fragment.h   ../source/cmt_group.h   ../source/cmt_constituent.h   ../source/cmt_language.h   ../source/cmt_map.h   ../source/cmt_pattern.h   ../source/cmt_include.h   ../source/cmt_script.h   ../source/cmt_scope_section.h   ../source/cmt_use.h   ../source/cmt_tag.h   ../source/cmt_symbol.h   ../source/cmt_awk.h   ../source/cmt_project.h   ../source/cmt_cmtpath_pattern.h   ../source/cmt_database.h 
Index: CMT/HEAD/mgr/requirements
===================================================================
--- CMT/HEAD/mgr/requirements	(revision 44)
+++ CMT/HEAD/mgr/requirements	(revision 45)
@@ -67,5 +67,5 @@
 tag SunOS          Unix
 
-tag CYGWIN_NT-5.1  Unix CYGWIN Linux
+tag CYGWIN_NT-5.1  Unix CYGWIN
 
 tag alpha          OSF1
@@ -365,4 +365,5 @@
       OSF1          "${CMTROOT}/mgr/cmt_make_shlib_common.sh noextract" \
       Linux         "${CMTROOT}/mgr/cmt_make_shlib_common.sh extract" \
+      CYGWIN        "${CMTROOT}/mgr/cmt_make_shlib_common.sh extract" \
       SunOS         "${CMTROOT}/mgr/cmt_make_shlib_common.sh extract" \
       Darwin        "${CMTROOT}/mgr/cmt_make_shlib_common.sh extract" \
@@ -374,4 +375,5 @@
       SunOS         "so" \
       Linux         "so" \
+      CYGWIN        "dll" \
       Darwin        "dylib" \
       WIN32         "dll"
@@ -382,4 +384,5 @@
       SunOS         "CC" \
       Linux         "g++" \
+      CYGWIN        "g++" \
       Darwin        "c++"
 
@@ -388,4 +391,5 @@
       OSF1          "-shared -expect_unresolved '*'" \
       Linux         "-shared" \
+      CYGWIN        "-shared" \
       SunOS         "$(debug_option)" \
       VisualC       "" \
@@ -437,5 +441,5 @@
 
 macro application_suffix ".exe"
-macro library_prefix "lib" WIN32 ""
+macro library_prefix "lib" WIN32 "" CYGWIN ""
 macro library_suffix ""
 
Index: CMT/HEAD/source/cmt_cvs.cxx
===================================================================
--- CMT/HEAD/source/cmt_cvs.cxx	(revision 44)
+++ CMT/HEAD/source/cmt_cvs.cxx	(revision 45)
@@ -12,4 +12,5 @@
 #include "cmt_awk.h"
 #include "cmt_symbol.h"
+#include "cmt_project.h"
 
 /**
@@ -69,5 +70,5 @@
 /**
 
-      History : maintains the history of checkout packages during a 
+      History : maintains the history of checkouts during a 
                 recursive checkout, so as to avoid double checkouts.
 
@@ -173,28 +174,32 @@
   CvsImplementation ()
   {
-    m_recursive = false;
-    m_head = false;
-    m_cmtcvstest = false;
-    m_verbose = false;
+    clear ();
+  }
+
+  void clear ()
+  {
+    m_recursive  = false;
+    m_head       = false;
+    m_verbose    = false;
     m_simulation = false;
 
-    m_home_dir = "";
+    m_home_dir     = "";
     m_checkout_dir = "";
-    m_offset = "";
-    m_branch_suffix = "";
-
-    m_last_module = "";
-    m_last_cvs_infos = "";
-    structure_info = "";
-    error_info = "";
-    tags_top_info = "";
-    tags_info = "";
+    m_version_dir  = "";
+    m_cvs_offset   = "";
+
+    m_last_module        = "";
+    m_last_cvs_infos     = "";
+    structure_info       = "";
+    error_info           = "";
+    tags_top_info        = "";
+    tags_info            = "";
     cvsversions_top_info = "";
-    cvsversions_info = "";
-    branches_info = "";
-    subpackages_info = "";
-    subprojects_info = "";
-
-    m_protocol_level = "";
+    cvsversions_info     = "";
+    branches_info        = "";
+    subpackages_info     = "";
+    subprojects_info     = "";
+
+    m_protocol_level     = "";
 
     Symbol* symbol = Symbol::find ("cmt_cvs_protocol_level");
@@ -204,4 +209,32 @@
 	Symbol::expand (m_protocol_level);
       }
+  }
+
+  CvsImplementation& operator = (const CvsImplementation& other)
+  {
+    m_recursive  = other.m_recursive;
+    m_head       = other.m_head;
+    m_verbose    = other.m_verbose;
+    m_simulation = other.m_simulation;
+
+    m_home_dir       = other.m_home_dir;
+    m_checkout_dir   = other.m_checkout_dir;
+    m_version_dir    = other.m_version_dir;
+    m_cvs_offset     = other.m_cvs_offset;
+    m_protocol_level = other.m_protocol_level;
+    m_last_module    = other.m_last_module;
+    m_last_cvs_infos = other.m_last_cvs_infos;
+
+    structure_info       = other.structure_info;
+    error_info           = other.error_info;
+    tags_top_info        = other.tags_top_info;
+    tags_info            = other.tags_info;
+    cvsversions_top_info = other.cvsversions_top_info;
+    cvsversions_info     = other.cvsversions_info;
+    branches_info        = other.branches_info;
+    subpackages_info     = other.subpackages_info;
+    subprojects_info     = other.subprojects_info;
+
+    return (*this);
   }
 
@@ -229,4 +262,64 @@
       }
   }
+
+  int execute (const cmt_string& command)
+  {
+    int status = 0;
+
+    if (m_verbose || m_simulation)
+      {
+	cout << "#CMT> Executing [" << command << "]" << endl;
+      }
+    
+    if (!m_simulation)
+      {
+	status = CmtSystem::execute (command);
+      }
+
+    return (status);
+  }
+
+  void execute_and_retry (const cmt_string& command, const cmt_string& message)
+  {
+    int status;
+    int retry = 0;
+
+    for (;;)
+      {
+	status = execute (command);
+        
+	if (status != 0)
+	  {
+	    retry++;
+	    
+	    cout << "# " << message << ": status=" << status << endl;
+	    cout << "#---------------------------------------------------------" << endl;
+	    
+	    if (retry > 5) exit(0);
+	  }
+	else
+	  {
+	    break;
+	  }
+      }
+  }
+
+  int execute (const cmt_string& command, cmt_string& out)
+  {
+    int status = 0;
+
+    if (m_verbose || m_simulation)
+      {
+	cout << "#CMT> Executing [" << command << "]" << endl;
+      }
+    
+    if (!m_simulation)
+      {
+	status = CmtSystem::execute (command, out);
+      }
+
+    return (status);
+  }
+
 
   /**
@@ -272,26 +365,23 @@
     command += " -Q co -p CVSROOT/loginfo ";
 
-    if (m_verbose || m_simulation)
-      {
-	cout << "#CMT> Executing [" << command << "]" << endl;
-      }
-    
-    if (!m_simulation)
-      {
-	found = false;
-
-	cmt_string loginfo;
-
-	CmtSystem::execute (command, loginfo);
-
-	cmt_string pattern = ".cmtcvsinfos/";
-	pattern += m_protocol_level;
-
-	int pos = loginfo.find (pattern);
-
-	if (pos != cmt_string::npos)
-	  {
-	    found = true;
-	  }
+    found = false;
+
+    cmt_string pattern = ".cmtcvsinfos/";
+    pattern += m_protocol_level;
+
+    cmt_string loginfo;
+
+    if (m_simulation)
+      {
+	loginfo = pattern;
+      }
+
+    execute (command, loginfo);
+
+    int pos = loginfo.find (pattern);
+
+    if (pos != cmt_string::npos)
+      {
+	found = true;
       }
 
@@ -353,6 +443,5 @@
 	if (!CmtSystem::mkdir (tmp_dir))
 	  {
-	    cout << "#CMT> Cannot create the temporary directory [" 
-		 << tmp_dir << "]" << endl;
+	    cout << "#CMT> Cannot create the temporary directory [" << tmp_dir << "]" << endl;
 	    return;
 	  }
@@ -380,18 +469,17 @@
       }
     
-    /*
-      #
-      # The script associated to such entries is supposed to :
-      #  1) extract the set of <infos> from ${module}/cmt/requirements
-      #                                  or ${module}/cmt/project.cmt
-      #  2) build an output of the form :
-      #      <infos>=info1 info2 info3 ...
-      #
-      # Currently this script can be found in
-      #
-      # ${CMTROOT}/cmt/cmt_buildcvsinfos2.sh
-      # %CMTROOT%/cmt/cmt_buildcvsinfos.py
-      # There is a C++ implementation as cmtcvs.exe
-      #
+    /**
+       The script associated to such entries is supposed to :
+        1) extract the set of <infos> from ${module}/cmt/requirements
+                                        or ${module}/cmt/project.cmt
+        2) build an output of the form :
+            <infos>=info1 info2 info3 ...
+      
+       Currently this script can be found in
+      
+       ${CMTROOT}/cmt/cmt_buildcvsinfos2.sh
+       %CMTROOT%/cmt/cmt_buildcvsinfos.py
+       There is a C++ implementation as cmtcvs.exe
+      
     */
     
@@ -418,9 +506,4 @@
     
     command += cmtcvsinfos;
-    
-    if (m_cmtcvstest)
-      {
-	command += "/cmtcvstest";
-      }
     
     if (m_protocol_level != "")
@@ -433,11 +516,7 @@
     command += " CMT v1";
     
-    if (m_verbose || m_simulation)
-      {
-	cout << "#CMT> Executing [" << command << "]" << endl;
-      }
-    
     m_last_cvs_infos = "";
-    CmtSystem::execute (command, m_last_cvs_infos);
+
+    execute (command, m_last_cvs_infos);
     
     if (m_verbose)
@@ -467,5 +546,5 @@
        all subprojects installed below the module.
     
-        In principle, only modules corresponding to true CMT packages or projects are considered.
+        In principle, only modules corresponding to true CMT products (packages or projects) are considered.
           o tags are obtained from the requirements or the project file
           o branches are sub-directories which are not themselves packages
@@ -473,5 +552,5 @@
             (a subdirectory is always either a branch or a subpackage)
   */
-  void show_cvs_infos (const cmt_string& module)
+  void get_cvs_infos_with_offset (const cmt_string& module)
   {
     if (!check_protocol ())
@@ -503,13 +582,4 @@
     /**
        Now retrieve all info fields :
-       
-       structure=
-       error=
-       tags_top=
-       tags=
-       branches=
-       subpackages=
-       subprojects=
-       
     */
 
@@ -650,23 +720,13 @@
 	filter_list (cvsversions_info, exp);
       }
-    
-    if (m_cmtcvstest)
-      {
-	cout << "## tags_top_info=" << tags_top_info << endl;
-	cout << "## tags_info=" << tags_info << endl;
-	cout << "## cvsversions_top_info=" << cvsversions_top_info << endl;
-	cout << "## cvsversions_info=" << cvsversions_info << endl;
-      }
-    
-  }
-  
-  void show_cvs_infos (const cmt_string& offset,
-		       const cmt_string& module)
+  }
+  
+  void get_cvs_infos (const cmt_string& cvs_offset, const cmt_string& module)
   {
     cmt_string full_name;
 
-    if (offset != "") 
-      {
-	full_name = offset;
+    if (cvs_offset != "") 
+      {
+	full_name = cvs_offset;
 	full_name += "/";
 	while (full_name.find ("//") != cmt_string::npos)
@@ -678,5 +738,5 @@
     full_name += module;
 
-    show_cvs_infos (full_name);
+    get_cvs_infos_with_offset (full_name);
   }
 
@@ -713,6 +773,6 @@
   }
 
-  bool get_version (const cmt_string& prefix,
-                    const cmt_string& package,
+  bool get_version (const cmt_string& offset,
+                    const cmt_string& product,
                     const cmt_string& version_request,
                     cmt_string& module,
@@ -729,7 +789,7 @@
     module = "";
 
-    if (prefix != "")
-      {
-	module = prefix;
+    if (offset != "")
+      {
+	module = offset;
 	module += "/"; // This is for CVS only thus we don't use the real separator.
 	while (module.find ("//") != cmt_string::npos)
@@ -739,5 +799,5 @@
       }
 
-    module += package;
+    module += product;
 
     /**
@@ -750,6 +810,6 @@
      *     the HEAD) or not. The returned at_head flag will show this.
      *
-     *     then the requested package may either be located in the CVS repository
-     *     under the prefix or not, the returned module will contain the effective
+     *     then the requested product may either be located in the CVS repository
+     *     under the offset or not, the returned module will contain the effective
      *     location where the requested version has been found.
      */
@@ -760,10 +820,10 @@
       }
     
-    show_cvs_infos (module);
+    get_cvs_infos_with_offset (module);
     
     if (error_info != "")
       {
 	versions = "";
-	cout << "#CMT> Package " << package << " not found in ${CVSROOT}" << endl;
+	cout << "#CMT> Product " << product << " not found in ${CVSROOT}" << endl;
 	return (false);
       }
@@ -783,12 +843,8 @@
       }
     
-    if (m_cmtcvstest) cout << "##    (version expression is " << v << ")" << endl;
-	
     cmt_regexp version_exp (v);
     
     if (!match_version_request (versions, version_exp, version))
       {
-	if (m_cmtcvstest) cout << "##    (no match in " << versions << ")" << endl;
-
 	// We try on non-top versions
 
@@ -797,6 +853,4 @@
 	if (!match_version_request (versions, version_exp, version))
 	  {
-	    if (m_cmtcvstest) cout << "##    (no match in " << versions << ")" << endl;
-	    
 	    version = requested_version;
 	    int pos = 0;
@@ -838,6 +892,4 @@
 	else
 	  {
-	    if (m_cmtcvstest) cout << "##    (match in non head " << versions << ")" << endl;
-	    
 	    at_head = false;
 	  }
@@ -845,6 +897,4 @@
     else
       {
-	if (m_cmtcvstest) cout << "##    (match in head " << versions << ")" << endl;
-	
 	at_head = true;
       }
@@ -857,6 +907,9 @@
   }
 
-  cmt_string build_version_directory (const cmt_string& prefix,
-                                      const cmt_string& package,
+  /**
+     Take care of structuring style for packages and of project vs package conventions
+   */
+  cmt_string build_version_directory (const cmt_string& offset,
+                                      const cmt_string& product,
                                       const cmt_string& version)
   {
@@ -865,4 +918,6 @@
     if (m_checkout_dir != "")
       {
+	// consider the usual -d option 
+ 
 	dir += CmtSystem::file_separator ();
 	dir += m_checkout_dir;
@@ -870,9 +925,9 @@
     
     dir += CmtSystem::file_separator ();
-    dir += prefix;
+    dir += offset;
     dir += CmtSystem::file_separator ();
-    dir += package;
-    
-    if (Cmt::get_current_structuring_style () == with_version_directory)
+    dir += product;
+    
+    if ((structure_info == "project") || (Cmt::get_current_structuring_style () == with_version_directory))
       {
 	dir += CmtSystem::file_separator ();
@@ -883,4 +938,176 @@
     
     return (dir);
+  }
+
+  /**
+     Wrapper to mkdir handling simulation and verbose options.
+   */
+  bool mkdir (const cmt_string& dir)
+  {
+    if (m_simulation)
+      {
+	cout << "#CMT> Would create the " << dir << " directory" << endl;
+      }
+    else
+      {
+	if (!CmtSystem::cd (dir))
+	  {
+	    if (m_verbose)
+	      {
+		cout << "#CMT> About to mkdir " << dir << endl;
+	      }
+
+	    CmtSystem::mkdir (dir);
+	    if (!CmtSystem::cd (dir))
+	      {
+		cout << "# Error creating the directory :" << dir << endl;
+		cout << "#---------------------------------------------------------" << endl;
+		return (false);
+	      }
+	  }
+      }
+    return (true);
+  }
+
+  /**
+     When running cmt cvs commands, we stand by definition outside of any existing 
+     package context. Thus it's likely that CMTPATH are not completely defined.
+     This function manually prepends CMTPATH entries to the environment variable.
+   */
+  void add_cmtpath (const cmt_string& dir)
+  {
+    static cmt_string CMTPATH;
+
+    cmt_string cmtpath = CmtSystem::getenv ("CMTPATH");
+
+    if (cmtpath.find (dir) == cmt_string::npos)
+      {
+	CMTPATH = "CMTPATH=";
+	CMTPATH += dir;
+	CMTPATH += ":";
+	CMTPATH += cmtpath;
+	
+	CmtSystem::putenv (CMTPATH);
+      }
+
+    if (m_verbose)
+      {
+	cout << "#CMT> CMTPATH=" << CmtSystem::getenv ("CMTPATH") << endl;
+      }
+  }
+
+  /**
+     Construct CVS management files in the top directory. This is needed
+     if the top directory of a product is empty. (In this case the
+     co -l results in nothing)
+   */
+  void make_management_files (const cmt_string& module,
+			      const cmt_string& entries_text)
+  {
+    if (!CmtSystem::test_directory ("CVS"))
+      {
+	/**
+	 * The CVS repository had not been created (this is generally
+	 * due to the lack of top files)
+	 */
+
+	if (!mkdir ("CVS")) return;
+
+	CmtSystem::cd ("..");
+
+	cmt_string s;
+	
+	// Let's create first the CVS/Root file.
+	
+	CmtSystem::get_cvsroot (s);
+	s += "\n";
+	
+	cmt_string f;
+	
+	f = "CVS";
+	f += CmtSystem::file_separator ();
+	f += "Root";
+	
+	if (m_simulation)
+	  {
+	    cout << "#CMT> Would fill in the CVS/Root file with " << endl;
+	    cout << s << endl;
+	  }
+	else
+	  {
+	    if (m_verbose)
+	      {
+		cout << "#CMT> Fill in the CVS/Root file with " << endl;
+		cout << s << endl;
+	      }
+	    s.write (f);
+	  }
+	
+	// Now we create the CVS/Repository file
+	
+	f = "CVS";
+	f += CmtSystem::file_separator ();
+	f += "Repository";
+	
+	CmtSystem::get_cvsroot (s);
+	if (s[0] == ':')
+	  {
+	    int pos = s.find (1, ":");
+	    s.erase (0, pos+1);
+	    pos = s.find (0, ":");
+	    s.erase (0, pos+1);
+	  }
+	s += "/";
+	s += module;
+	s += "\n";
+	
+	if (m_simulation)
+	  {
+	    cout << "#CMT> Would fill in the CVS/Repository file with " << endl;
+	    cout << s << endl;
+	  }
+	else
+	  {
+	    if (m_verbose)
+	      {
+		cout << "#CMT> Fill in the CVS/Repository file with " << endl;
+		cout << s << endl;
+	      }
+	    s.write (f);
+	  }
+      }
+    
+    if (m_simulation)
+      {
+	cout << "#CMT> Would write the top CVS/Entries file with " << endl;
+	cout << entries_text << endl;
+      }
+    else
+      {
+	cmt_string entries_file_name;
+
+	entries_file_name = "CVS";
+	entries_file_name += CmtSystem::file_separator ();
+	entries_file_name += "Entries";
+    
+	cmt_string text;
+
+	if (!text.read (entries_file_name))
+	  {
+	    // This happens when there were no top files
+	  }
+
+	text += entries_text;
+
+	// Now the CVS/Entries is ready to be created.
+	if (m_verbose)
+	  {
+	    cout << "#CMT> Fill in the top CVS/Entries file with " << endl;
+	    cout << text << endl;
+	  }
+
+	text.write (entries_file_name);
+      }
+
   }
 
@@ -888,7 +1115,8 @@
      Specific checkout of one project
    */
-  bool really_checkout_project_contents (const cmt_string& prefix,
+  bool really_checkout_project_contents (const cmt_string& offset,
 					 const cmt_string& project,
 					 const cmt_string& version,
+					 const cmt_string& tag,
 					 const cmt_string& module,
 					 const cmt_string& basedir,
@@ -900,22 +1128,10 @@
     cout << "  # get project files into " << dir << endl;
 
-    if (m_simulation)
-      {
-	cout << "#CMT> Would mkdir " << version << endl;
-      }
-    else
-      {
-	if (m_verbose)
-	  {
-	    cout << "#CMT> About to mkdir " << version << endl;
-	  }
-
-	CmtSystem::mkdir (version);
-	CmtSystem::cd (version);
-      }
+    cmt_string version_dir = version;
+
+    if (!mkdir (version_dir)) return (false);
 
     dir += CmtSystem::file_separator ();
-    dir += version;
-
+    dir += version_dir;
     
     cmt_string command = "cvs -Q co -P ";
@@ -923,8 +1139,8 @@
       {
 	command += "-r ";
-	command += version;
-      }
-
-    command += "-d cmt ";
+	command += (tag != "") ? tag : version;
+      }
+
+    command += " -d cmt ";
 
     command += " ";
@@ -932,34 +1148,7 @@
     command += "/cmt";
 
-    int status = 0;
-    int retry = 0;
-    
-    for (;;)
-      {
-	if (m_verbose || m_simulation)
-	  {
-	    cout << "#CMT> Executing [" << command << "]" << endl;
-	  }
-	
-	if (!m_simulation)
-	  {
-	    //status = CmtSystem::execute (command, out);
-	    status = CmtSystem::execute (command);
-	  }
-        
-	if (status != 0)
-	  {
-	    retry++;
-	    
-	    cout << "# Error getting project CMT contents: status=" << status << endl;
-	    cout << "#---------------------------------------------------------" << endl;
-	    
-	    if (retry > 5) exit(0);
-	  }
-	else
-	  {
-	    break;
-	  }
-      }
+    execute_and_retry (command, "Error getting project CMT contents");
+
+    make_management_files (module, "D/cmt////\n");
 
     return (true);
@@ -974,5 +1163,5 @@
      4) write the CVS management files if CVS did not do it.
    */
-  bool really_checkout_package_contents (const cmt_string& prefix,
+  bool really_checkout_package_contents (const cmt_string& offset,
 					 const cmt_string& package,
 					 const cmt_string& version,
@@ -1002,4 +1191,8 @@
 	command += " -d ";
 	command += package;
+
+	// Must stand just above the package directory
+	CmtSystem::cd ("..");
+	CmtSystem::dirname (dir, dir);
       }
     
@@ -1007,76 +1200,9 @@
     command += module;
     
-    if (m_cmtcvstest)
-      {
-	cmt_string cvsroot;
-	
-	CmtSystem::get_cvsroot (cvsroot);
-	
-	cout << "## cvsroot=" << cvsroot << " command[" << command << "]" << endl;
-      }
-    
-    int status = 0;
-    int retry = 0;
-    
-    for (;;)
-      {
-	if (m_verbose || m_simulation)
-	  {
-	    cout << "#CMT> Executing [" << command << "]" << endl;
-	  }
-	
-	if (!m_simulation)
-	  {
-	    //status = CmtSystem::execute (command, out);
-	    status = CmtSystem::execute (command);
-	  }
-        
-	if (status != 0)
-	  {
-	    retry++;
-	    
-	    cout << "# Error getting package CMT contents: status=" << status << endl;
-	    cout << "#---------------------------------------------------------" << endl;
-	    
-	    if (retry > 5) exit(0);
-	    
-	  }
-	else
-	  {
-	    break;
-	  }
-      }
+    execute_and_retry (command, "Error getting package CMT contents");
 
     if (Cmt::get_current_structuring_style () == with_version_directory)
       {
-	if (m_simulation)
-	  {
-	    cout << "#CMT> Would mkdir " << version << endl;
-	  }
-	else
-	  {
-	    if (m_verbose)
-	      {
-		cout << "#CMT> About to mkdir " << version << endl;
-	      }
-
-	    if (!CmtSystem::cd (version))
-	      {
-		CmtSystem::mkdir (version);
-		if (!CmtSystem::cd (version))
-		  {
-		    cout << "# Error creating the version directory :" << version << endl;
-		    cout << "#---------------------------------------------------------" << endl;
-		    return (false);
-		  }
-	      }
-	    
-	    /*
-	      if (m_verbose)
-	      {
-	      cout << "#CMT> pwd.2=" << CmtSystem::pwd () << endl;
-	      }
-	    */
-	  }
+	if (!mkdir (version)) return (false);
 	
 	dir += CmtSystem::file_separator ();
@@ -1085,32 +1211,5 @@
     else
       {
-	if (m_simulation)
-	  {
-	    cout << "#CMT> will mkdir " << package << endl;
-	  }
-	else
-	  {
-	    if (!CmtSystem::cd (package))
-	      {
-		if (m_verbose)
-		  {
-		    cout << "#CMT> About to mkdir " << package << endl;
-		  }
-		CmtSystem::mkdir (package);
-		if (!CmtSystem::cd (package))
-		  {
-		    cout << "# Error creating the package directory :" << package << endl;
-		    cout << "#---------------------------------------------------------" << endl;
-		    return (false);
-		  }
-	      }
-	    
-	    /*
-	      if (m_verbose)
-	      {
-	      cout << "#CMT> pwd.3=" << CmtSystem::pwd () << endl;
-	      }
-	    */
-	  }
+	if (!mkdir (package)) return (false);
 	
 	dir += CmtSystem::file_separator ();
@@ -1118,7 +1217,9 @@
       }
     
-    cmt_string entries_file_name;
-    cmt_string text;
-    
+    if (m_verbose)
+      {
+	cout << "#CMT> Now getting subdirectories pwd=" << CmtSystem::pwd () << " dir=" << dir << endl;
+      }
+
     cmt_string branches = CmtSystem::getenv ("CMTCVSBRANCHES");
     
@@ -1132,20 +1233,12 @@
     CmtSystem::split (branches, " \t", branch_vector);
     
+    cout << "  # get branches " << branches << endl;
+    
+    cmt_string text = "";
+    
+    command = "";
+    
     int i;
     
-    cout << "  # get branches " << branches << endl;
-    
-    //command = "(";
-    command = "";
-    
-    entries_file_name = "CVS";
-    entries_file_name += CmtSystem::file_separator ();
-    entries_file_name += "Entries";
-    
-    if (!text.read (entries_file_name))
-      {
-	// This happens when there were no top files
-      }
-    
     for (i = 0; i < branch_vector.size (); i++)
       {
@@ -1157,9 +1250,6 @@
 	  }
 	
-	//command += "cvs -Q co -P ";
 	command += "cvs -Q co ";
 	
-	//            if (branch != "cmt")
-	//              {
 	if (!at_head)
 	  {
@@ -1167,5 +1257,4 @@
 	    command += version;
 	  }
-	//              }
 	
 	command += " -d ";
@@ -1175,5 +1264,4 @@
 	command += "/";    // CVS uses the '/' notation on all platforms!!
 	command += branch;
-	//command += "\n";
 	
 	text += "D/";
@@ -1182,144 +1270,7 @@
       }
     
-    //command += "; echo cmtcvsstatus=$?) 2>&1 ";
-    
-    if (m_cmtcvstest)
-      {
-	cmt_string cvsroot;
-	
-	CmtSystem::get_cvsroot (cvsroot);
-	
-	cout << " cvsroot=" << cvsroot << " command[" << command << "]" << endl;
-      }
-    
-    status = 0;
-    retry = 0;
-    
-    for (;;)
-      {
-	if (m_verbose || m_simulation)
-	  {
-	    cout << "#CMT> Executing [" << command << "]" << endl;
-	  }
-	
-	if (!m_simulation)
-	  {
-	    //status = CmtSystem::execute (command, out);
-	    status = CmtSystem::execute (command);
-	  }
-	
-	if (status != 0)
-	  {
-	    retry++;
-	    
-	    cout << "# Error getting package contents: status=" << status << endl;
-	    cout << "#---------------------------------------------------------" << endl;
-	    
-	    if (retry > 5) exit(0);
-	    
-	  }
-	else
-	  {
-	    break;
-	  }
-      }
-    
-    if (!CmtSystem::test_directory ("CVS"))
-      {
-	/**
-	 * The CVS repository had not been created (this is generally
-	 * due to the lack of top files)
-	 */
-	
-	if (m_simulation)
-	  {
-	    cout << "#CMT> Would create the CVS directory" << endl;
-	  }
-	else
-	  {
-	    if (m_verbose)
-	      {
-		cout << "#CMT> About to mkdir " << "CVS" << endl;
-	      }
-	    CmtSystem::mkdir ("CVS");
-	  }
-	
-	cmt_string s;
-	
-	// Let's create first the CVS/Root file.
-	
-	CmtSystem::get_cvsroot (s);
-	s += "\n";
-	
-	cmt_string f;
-	
-	f = "CVS";
-	f += CmtSystem::file_separator ();
-	f += "Root";
-	
-	if (m_simulation)
-	  {
-	    cout << "#CMT> Would fill in the CVS/Root file with " << endl;
-	    cout << s << endl;
-	  }
-	else
-	  {
-	    if (m_verbose)
-	      {
-		cout << "#CMT> Fill in the CVS/Root file with " << endl;
-		cout << s << endl;
-	      }
-	    s.write (f);
-	  }
-	
-	// Now we create the CVS/Repository file
-	
-	f = "CVS";
-	f += CmtSystem::file_separator ();
-	f += "Repository";
-	
-	CmtSystem::get_cvsroot (s);
-	if (s[0] == ':')
-	  {
-	    int pos = s.find (1, ":");
-	    s.erase (0, pos+1);
-	    pos = s.find (0, ":");
-	    s.erase (0, pos+1);
-	  }
-	s += "/";
-	s += module;
-	s += "\n";
-	
-	if (m_simulation)
-	  {
-	    cout << "#CMT> Would fill in the CVS/Repository file with " << endl;
-	    cout << s << endl;
-	  }
-	else
-	  {
-	    if (m_verbose)
-	      {
-		cout << "#CMT> Fill in the CVS/Repository file with " << endl;
-		cout << s << endl;
-	      }
-	    s.write (f);
-	  }
-      }
-    
-    if (m_simulation)
-      {
-	cout << "#CMT> Would write the top CVS/Entries file with " << endl;
-	cout << text << endl;
-      }
-    else
-      {
-	// Now the CVS/Entries is ready to be created.
-	if (m_verbose)
-	  {
-	    cout << "#CMT> Fill in the top CVS/Entries file with " << endl;
-	    cout << text << endl;
-	  }
-	text.write (entries_file_name);
-      }
+    execute_and_retry (command, "Error getting package contents");
+
+    make_management_files (module, text);
 
     return (true);
@@ -1329,7 +1280,8 @@
      Effective checkout of a package or a project
    */
-  bool really_checkout (const cmt_string& prefix,
-			const cmt_string& package,
+  bool really_checkout (const cmt_string& offset,
+			const cmt_string& product,
 			const cmt_string& version,
+			const cmt_string& tag,
 			const cmt_string& module,
 			const cmt_string& basedir,
@@ -1339,60 +1291,36 @@
     cmt_string out;
     
-    cout << "# ================= working on " << structure_info << " " << package 
+    cout << "# ================= working on " << structure_info << " " << product 
 	 << " version " << version;
 
     if (at_head) cout << " (At head) ";
 
-    cmt_string full_prefix;
-
-    full_prefix = m_offset;
-    full_prefix += prefix;
+    cmt_string full_offset;
+
+    full_offset = m_cvs_offset;
+    full_offset += offset;
 
     cmt_string echo_ppath;
         
-    if (prefix != "")
+    if (offset != "")
       {
 	echo_ppath = " path ";
-	echo_ppath += prefix;
-      }
-    
-    cout << echo_ppath << endl;
-
-    CmtSystem::dirname (dir, dir);
-
-    //if (Cmt::get_current_structuring_style () == with_version_directory)
-
-    if (m_simulation)
-      {
-	cout << "#CMT> Would mkdir " << dir << endl;
-      }
-    else
-      {
-	if (m_verbose)
-	  {
-	    cout << "#CMT> About to mkdir " << dir << endl;
-	  }
-	
-	if (!CmtSystem::mkdir (dir))
-	  {
-	    cout << "# Error creating the base directory :" << dir << endl;
-	    cout << "#---------------------------------------------------------" << endl;
-	    return (false);
-	  }
-	
-	CmtSystem::cd (dir);
-	
-	/*
-	  if (m_verbose)
-	  {
-	  cout << "#CMT> pwd.1=" << CmtSystem::pwd () << endl;
-	  }
-	*/
-      }
+	echo_ppath += offset;
+      }
+    
+    cout << echo_ppath << " in " << dir << endl;
+
+    if ((structure_info == "project") || (Cmt::get_current_structuring_style () == with_version_directory))
+      {
+	// Move back to the product name.
+	CmtSystem::dirname (dir, dir);
+      }
+
+    if (!mkdir (dir)) return (false);
 	
     if (structure_info == "package")
       {
-	really_checkout_package_contents (prefix,
-					  package,
+	really_checkout_package_contents (offset,
+					  product,
 					  version,
 					  module,
@@ -1403,7 +1331,8 @@
     else if (structure_info == "project")
       {
-	really_checkout_project_contents (prefix,
-					  package,
+	really_checkout_project_contents (offset,
+					  product,
 					  version,
+					  tag,
 					  module,
 					  basedir,
@@ -1416,69 +1345,55 @@
 
   cmt_string find_matching_version (const cmt_string& expression)
-      {
-        cmt_string result;
-
-          //
-          // Here expression takes the form
-          //   <some path>/<expression with wild-card>
-          //
-
-        cmt_string dir;
-        CmtSystem::dirname (expression, dir);
-        dir += CmtSystem::file_separator ();
-
-        cmt_string version;
-        CmtSystem::basename (expression, version);
-
-        if (version.find ("*") == cmt_string::npos)
-          {
-              // there is no wildcarding here. A simple test is enough.
-            if (CmtSystem::test_directory (expression))
-              {
-                if (m_cmtcvstest) cout << "## Found direct match with " << version << endl;
-                result = version;
-              }
-            else
-              {
-                if (m_cmtcvstest) cout << "## Explicit version " << version 
-                                       << " has no direct match" << endl;
-              }
-          }
-        else
-          {
-            version.replace ("*", ".*");
-
-            cmt_regexp exp (version);
-
-            CmtSystem::cmt_string_vector list;
-
-            if (m_cmtcvstest) cout << "## Trying scan_dir dir=" << dir
-                                   << " exp=" << version << endl;
-
-            CmtSystem::scan_dir (dir, exp, list);
-
-            if (list.size () > 0)
-              {
-                result = list[0];
-
-                if (m_cmtcvstest) cout << "## At least one version is matching " << version 
-                                       << "(" << list.size () << " matches) " << result << endl;
-
-                CmtSystem::basename (result, result);
-              }
-            else
-              {
-                if (m_cmtcvstest) cout << "## There is no version matching " << version << endl;
-              }
-          }
-
-        return (result);
-      }
-
+  {
+    cmt_string result;
+
+    //
+    // Here expression takes the form
+    //   <some path>/<expression with wild-card>
+    //
+
+    cmt_string dir;
+    CmtSystem::dirname (expression, dir);
+    dir += CmtSystem::file_separator ();
+    
+    cmt_string version;
+    CmtSystem::basename (expression, version);
+
+    if (version.find ("*") == cmt_string::npos)
+      {
+	// there is no wildcarding here. A simple test is enough.
+	if (CmtSystem::test_directory (expression))
+	  {
+	    result = version;
+	  }
+      }
+    else
+      {
+	version.replace ("*", ".*");
+	
+	cmt_regexp exp (version);
+	
+	CmtSystem::cmt_string_vector list;
+	
+	CmtSystem::scan_dir (dir, exp, list);
+	
+	if (list.size () > 0)
+	  {
+	    result = list[0];
+	    
+	    CmtSystem::basename (result, result);
+	  }
+      }
+    
+    return (result);
+  }
+  
   /**
    *   We provide a path to a requirements file. From it we read the use 
    *  statements, and we try to checkout the corresponding packages.
+   *
+   *   A boolean return tells if any recursion occurred.
    */
-  void checkout_from_requirements (const cmt_string& requirements_path)
+  bool checkout_from_requirements (const cmt_string& requirements_path)
   {
     static cmt_regexp expression ("^[ \t]*use[ \t]");
@@ -1491,6 +1406,9 @@
     p1.run (text, expression);
 
+    bool result = (p1.result () != "");
     RecursivePass2 p2 (*this);
     p2.run (p1.result ());
+
+    return (result);
   }
 
@@ -1507,4 +1425,9 @@
     text.read (file_name);
 
+    CvsImplementation& me = *this;
+    CvsImplementation saved;
+    saved = me;
+    cmt_string here = CmtSystem::pwd ();
+
     RecursivePass3 p3;
     p3.run (text, expression);
@@ -1512,4 +1435,31 @@
     RecursivePass4 p4 (*this);
     p4.run (p3.result ());
+
+    Grep grep;
+
+    grep.run (text, "container");
+    cmt_string container = grep.result ();
+
+    if (container != "")
+      {
+	static cmt_regexp container_expression ("^[ \t]*container[ \t]");
+
+	add_cmtpath (here);
+
+	cout << "  # --> now getting project packages from the " << container << " " << here << endl;
+
+	CmtSystem::cd (here);
+
+	RecursivePass1 p1;
+	p1.run (text, container_expression);
+
+	RecursivePass2 p2 (*this);
+
+	m_home_dir = CmtSystem::pwd ();
+	p2.run (p1.result ());
+      }
+
+    CmtSystem::cd (here);
+    me = saved;
   }
 
@@ -1525,14 +1475,16 @@
      - the CVS tag
    */
-  void do_checkout (const cmt_string& prefix,
-		    const cmt_string& package,
-		    const cmt_string& specified_version,
-		    const cmt_string& tag)
+  void do_checkout_phase2 (const cmt_string& offset,
+			   const cmt_string& product,
+			   const cmt_string& specified_version,
+			   const cmt_string& tag)
   {
     if (m_verbose)
       {
-	cout << "#CMT> checkout_package> prefix=" << prefix
-	     << " " << structure_info << "=" << package
+	cout << "#CMT> do_checkout_phase2> offset=" << offset
+	     << " " << structure_info << "=" << product
 	     << " specified_version=" << specified_version
+	     << " tag=" << tag
+	     << " pwd=" << CmtSystem::pwd ()
 	     << endl;
       }
@@ -1540,20 +1492,20 @@
     cmt_string version = specified_version;
     cmt_string empty;
-    cmt_string full_prefix;
-    
-    full_prefix = m_offset;
-    full_prefix += prefix;
+    cmt_string full_offset;
+
+    full_offset = m_cvs_offset;
+    full_offset += offset;
     
     cmt_string echo_ppath;
     
-    if (prefix != "")
+    if (offset != "")
       {
 	echo_ppath = " path ";
-	echo_ppath += prefix;
+	echo_ppath += offset;
       }
     
     if (version == "")
       {
-	cout << "# ================= No version specified for " << structure_info << " " << package << endl;
+	cout << "# ================= No version specified for " << structure_info << " " << product << endl;
 	return;
       }
@@ -1561,5 +1513,5 @@
     //
     //  First make an attempt to locate the specified version of
-    //  this package "as-it-is" in the work area.
+    //  this product "as-it-is" in the work area.
     //   Since 'version' may contain wild-card, it's likely that
     //  we should not simply use CmtSystem::test_directory but
@@ -1569,20 +1521,8 @@
     cmt_string dir;
     
-    dir = build_version_directory (prefix, package, version);
-    
-    if (m_cmtcvstest) 
-      cout << "## (testing dir= " << dir << ")" << endl;
+    dir = build_version_directory (offset, product, version);
     
     bool recursive = m_recursive;
     
-    /*
-      if (m_cmtcvstest)
-      {
-      cmt_string v = find_matching_version (dir);
-      
-      cout << "---> v=" << v << endl;
-      }
-    */
-    
     cmt_string effective_version = find_matching_version (dir);
     
@@ -1591,7 +1531,7 @@
 	version = effective_version;
 	
-	dir = build_version_directory (prefix, package, version);
-	
-	cout << "# ================= " << structure_info << " " << package 
+	dir = build_version_directory (offset, product, version);
+	
+	cout << "# ================= " << structure_info << " " << product 
 	     << " version " << version << echo_ppath 
 	     << " already installed in " << dir << endl;
@@ -1603,4 +1543,5 @@
 	bool at_head = false;
 	cmt_string module;
+	cmt_string cvs_tag = (tag != "") ? tag : version;
 	
 	//
@@ -1612,21 +1553,17 @@
 	//
 	
-	if (version.find ("*") != cmt_string::npos)
-	  {
-	    cout << "# ================= " << structure_info << " " << package 
-		 << " version " << version << echo_ppath 
+	if (cvs_tag.find ("*") != cmt_string::npos)
+	  {
+	    cout << "# ================= " << structure_info << " " << product 
+		 << " version " << cvs_tag << echo_ppath 
 		 << " has wild cards and will not be considered." << endl;
 	    return;
 	  }
 	
-	if (!get_version (full_prefix, package, version, 
-			  module, version, at_head))
+	if (!get_version (full_offset, product, cvs_tag,
+			  module, cvs_tag, at_head))
 	  {
 	    return;
 	  }
-	
-	//cout << " full_prefix=[" << full_prefix << "] module=[" << module << "]" << endl;
-	
-	if (m_cmtcvstest) cout << "## after get_version at_head=" << at_head << " m_head=" << m_head << endl;
 	
 	if (m_head)
@@ -1642,13 +1579,20 @@
 	
 	//
-	// Make a second try after having selected a version from all the
-	// available versions compatible with the specified version
+	// Make a second try after having selected a CVS tag from all the
+	// available tags compatible with the specified version
 	//
-	
-	dir = build_version_directory (prefix, package, version);
-	
+
+	if (tag == "")
+	  {
+	    // If tag was not specified, then the version directory has to match the CVS tag
+	    // Otherwise the original version specification is kept for the directory.
+
+	    version = cvs_tag;
+	    dir = build_version_directory (offset, product, version);
+	  }
+
 	if (CmtSystem::test_directory (dir))
 	  {
-	    cout << "# ================= " << structure_info << " " << package 
+	    cout << "# ================= " << structure_info << " " << product 
 		 << " version " << version << echo_ppath 
 		 << " already installed." << endl;
@@ -1662,7 +1606,7 @@
 	    // 
 	    
-	    if (!really_checkout (prefix, package, version, module, dir, at_head))
+	    if (!really_checkout (offset, product, version, cvs_tag, module, dir, at_head))
 	      {
-		cout << "# bad return from really_checkout_package" << endl;
+		cout << "# bad return from really_checkout_product" << endl;
 		return;
 	      }
@@ -1670,13 +1614,6 @@
       }
     
-    /*
-      if (m_verbose)
-      {
-      cout << "#CMT> pwd.4=" << CmtSystem::pwd () << " structure=" << structure_info << endl;
-      }
-    */
-    
     //
-    //  Now reach the newly checked out package.
+    //  Now reach the newly checked out product.
     //
     
@@ -1690,13 +1627,6 @@
 	  {
 	    cout << "#CMT> Package directory not created " << dir << endl;
-	  }
-	
-	
-	/*
-	  if (m_verbose)
-	  {
-	  cout << "#CMT> pwd.4=" << CmtSystem::pwd () << endl;
-	  }
-	*/
+	    return;
+	  }
 	
 	// Check if it is a true CMT package.
@@ -1713,11 +1643,4 @@
 	    dir += "cmt";
 	    CmtSystem::cd ("cmt");
-	    
-	    /*
-	      if (m_verbose)
-	      {
-	      cout << "#CMT> pwd.5=" << CmtSystem::pwd () << endl;
-	      }
-	    */
 	    
 	    if (Cmt::get_current_structuring_style () == without_version_directory)
@@ -1739,24 +1662,21 @@
 		dir += "mgr";
 		CmtSystem::cd ("mgr");
-		
-		/*
-		  if (m_verbose)
-		  {
-		  cout << "#CMT> pwd.6=" << CmtSystem::pwd () << endl;
-		  }
-		*/
 	      }
 	    else
 	      {
-		cout << "# " << package << " not a CMT package" << endl;
+		cout << "# " << product << " not a CMT package" << endl;
 		return;
 	      }
 	  }
 	
-	//cout << "#   (recursive is " << recursive << ")" << endl;
-	
 	if (recursive)
 	  {
-	    checkout_from_requirements ("requirements");
+	    cmt_string here = CmtSystem::pwd ();
+
+	    bool did_recurse = checkout_from_requirements ("requirements");
+
+	    CmtSystem::cd (here);
+
+	    if (did_recurse) execute ("cmt -quiet broadcast cmt -quiet config");
 	  }
       }
@@ -1772,4 +1692,5 @@
 	  {
 	    cout << "#CMT> Project directory not created " << dir << endl;
+	    return;
 	  }
 	
@@ -1782,5 +1703,5 @@
 	if (!CmtSystem::test_file (file_name))
 	  {
-	    cout << "# " << package << " not a CMT project" << endl;
+	    cout << "# " << product << " not a CMT project" << endl;
 	    return;
 	  }
@@ -1790,4 +1711,7 @@
 	    checkout_from_project_file (file_name);
 	  }
+
+	cout << "# ================= Project " << product << " completed" << endl;
+
       }
   }
@@ -1803,7 +1727,9 @@
 
    */
-  void do_checkout (const cmt_string& module, const cmt_string& version_tag)
-  {
-    //CMTPATH=${CMTPATH}:${m_home_dir}; export CMTPATH
+  void do_checkout_phase1 (const cmt_string& module, 
+			   const cmt_string& version_dir, 
+			   const cmt_string& version_tag)
+  {
+    add_cmtpath (m_home_dir);
 
     History& h = History::instance ();
@@ -1820,7 +1746,8 @@
       }
 
-    cmt_string prefix;
-    cmt_string package;
+    cmt_string offset;
+    cmt_string product;
     cmt_string version;
+    cmt_string tag;
     
     if (version_tag == "")
@@ -1829,8 +1756,8 @@
         
         cmt_string m;
-        m = m_offset;
+        m = m_cvs_offset;
         m += module;
         
-        show_cvs_infos (m);
+        get_cvs_infos_with_offset (m);
         
         if (error_info != "")
@@ -1840,22 +1767,20 @@
           }
 
-        if (tags_top_info != "") version = tags_top_info;
-        else version = tags_info;
+        if (tags_top_info != "") tag = tags_top_info;
+        else tag = tags_info;
         
-          //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "version=" << version << endl;
-
-        cut.run (version);
+        cut.run (tag);
         
-        version = cut.result ();
-
-          //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "version=" << version << endl;
+        tag = cut.result ();
       }
     else
       {
-        version = version_tag;
-      }
-
-    CmtSystem::dirname (module, prefix);
-    CmtSystem::basename (module, package);
+	tag = version_tag;
+      }
+
+    version = (version_dir == "") ? tag : version_dir;
+
+    CmtSystem::dirname (module, offset);
+    CmtSystem::basename (module, product);
     
     cmt_string top_dir;
@@ -1865,7 +1790,7 @@
     top_dir += m_checkout_dir;
     top_dir += CmtSystem::file_separator ();
-    top_dir += prefix;
+    top_dir += offset;
     top_dir += CmtSystem::file_separator ();
-    top_dir += package;
+    top_dir += product;
     top_dir += CmtSystem::file_separator ();
     top_dir += version;
@@ -1876,26 +1801,13 @@
       {
 	cout << "#CMT> about to checkout " << structure_info
-	     << " " << package << " version " << version << " into " << top_dir << endl;
-      }
-    
-    do_checkout (prefix, package, version, "");
-
-    /*
-    if (m_verbose)
-      {
-	cout << "#CMT> after do_checkout pwd.7=" << CmtSystem::pwd () << " top_dir=" << top_dir << endl;
-      }
-    */
+	     << " " << product << " version " << version << " into " << top_dir << endl;
+      }
+
+    static const cmt_string empty;
+    do_checkout_phase2 (offset, product, version, tag);
 
     if (m_simulation) return;
 
     if (!CmtSystem::cd (top_dir)) return;
-
-    /*
-    if (m_verbose)
-      {
-	cout << "#CMT> pwd.8=" << CmtSystem::pwd () << endl;
-      }
-    */
 
     if (structure_info == "project")
@@ -1907,11 +1819,7 @@
 	file_name += "project.cmt";
 	
-	if (CmtSystem::test_file (file_name))
-	  {
-	    cout << "#CMT> project " << package << " has been checked out" << endl;
-	  }
-	else
-	  {
-	    cout << "# " << package << " was not properly checked out and is missing its cmt/project.cmt file" << endl;
+	if (!CmtSystem::test_file (file_name))
+	  {
+	    cout << "# " << product << " was not properly checked out and is missing its cmt/project.cmt file" << endl;
 	    return;
 	  }
@@ -1930,11 +1838,4 @@
 	    top_dir += "cmt";
 	    CmtSystem::cd ("cmt");
-	    
-	    /*
-	      if (m_verbose)
-	      {
-	      cout << "#CMT> pwd.9=" << CmtSystem::pwd () << endl;
-	      }
-	    */
 	  }
 	else
@@ -1949,15 +1850,8 @@
 		top_dir += "mgr";
 		CmtSystem::cd ("mgr");
-		
-		/*
-		  if (m_verbose)
-		  {
-		  cout << "#CMT> pwd.10=" << CmtSystem::pwd () << endl;
-		  }
-		*/
 	      }
 	    else
 	      {
-		cout << "# " << package << " was not properly checked out and is missing its cmt/requirements file" << endl;
+		cout << "# " << product << " was not properly checked out and is missing its cmt/requirements file" << endl;
 		return;
 	      }
@@ -1966,30 +1860,10 @@
 	if (m_verbose)
 	  {
-	    cout << "#CMT> package " << package << " has been checked out" << endl;
-	  }
-	
-	if (m_recursive)
-	  {
-	    if (m_verbose || m_simulation)
-	      {
-		cout << "#CMT> Executing [" << "cmt -quiet broadcast cmt -quiet config" << "]" << endl;
-	      }
-	    
-	    if (!m_simulation)
-	      {
-		CmtSystem::execute ("cmt -quiet broadcast cmt -quiet config");
-	      }
-	  }
-	else
-	  {
-	    if (m_verbose || m_simulation)
-	      {
-		cout << "#CMT> Executing [" << "cmt -quiet config" << "]" << endl;
-	      }
-        
-	    if (!m_simulation)
-	      {
-		CmtSystem::execute ("cmt -quiet config");
-	      }
+	    cout << "#CMT> product " << product << " has been checked out" << endl;
+	  }
+	
+	if (!m_recursive)
+	  {
+	    execute ("cmt -quiet config");
 	  }
       }
@@ -2003,6 +1877,7 @@
     cout << "   modifier :" << endl;
     cout << "   -l        Do not process used packages (default)." << endl;
-    cout << "   -R        Process used packages recursively." << endl;
+    cout << "   -R        Process used products recursively." << endl;
     cout << "   -r rev    Check out version tag. (is sticky)" << endl;
+    cout << "   -vd dir   Use this version directory instead of CVS tag." << endl;
     cout << "   -d dir    Check out into dir instead of module name." << endl;
     cout << "   -o offset Offset in the CVS repository" << endl;
@@ -2036,18 +1911,9 @@
       }
     
-    if (CmtSystem::getenv ("CMTCVSTEST") != "")
-      {
-	m_cmtcvstest = true;
-      }
-    else
-      {
-	m_cmtcvstest = false;
-      }
-    
-    m_offset = CmtSystem::getenv ("CMTCVSOFFSET");
-    if (m_offset != "") 
-      {
-	m_offset += "/";
-	m_offset.replace_all ("//", "/");
+    m_cvs_offset = CmtSystem::getenv ("CMTCVSOFFSET");
+    if (m_cvs_offset != "") 
+      {
+	m_cvs_offset += "/";
+	m_cvs_offset.replace_all ("//", "/");
       }
     
@@ -2064,5 +1930,5 @@
 	else
 	  {
-	    show_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), option);
+	    get_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), option);
 	    
 	    if (error_info != "")
@@ -2108,5 +1974,5 @@
     cmt_string out;
     
-    show_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), module);
+    get_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), module);
     
     if (error_info != "")
@@ -2128,5 +1994,5 @@
     cmt_string out;
     
-    show_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), (module == "") ? "." : module);
+    get_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), (module == "") ? "." : module);
     
     if (error_info != "")
@@ -2148,5 +2014,5 @@
     cmt_string out;
     
-    show_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), (module == "") ? "." : module);
+    get_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), (module == "") ? "." : module);
     
     if (error_info != "")
@@ -2179,18 +2045,9 @@
       }
     
-    if (CmtSystem::getenv ("CMTCVSTEST") != "")
-      {
-	m_cmtcvstest = true;
-      }
-    else
-      {
-	m_cmtcvstest = false;
-      }
-    
     m_home_dir = CmtSystem::pwd ();
     m_checkout_dir = "";
-    m_offset = "";
-    m_branch_suffix = "";
-    
+    m_version_dir = "";
+    m_cvs_offset = "";
+
     cmt_string module;
     
@@ -2201,6 +2058,7 @@
     
     bool need_checkout_dir = false;
-    bool need_offset = false;
+    bool need_cvs_offset = false;
     bool need_requirements_file = false;
+    bool need_version_dir = false;
     
     m_simulation = false;
@@ -2208,13 +2066,11 @@
     m_verbose = false;
     
-    bool need_branch_suffix = false;
-    
     m_head = true;
     
-    m_offset = CmtSystem::getenv ("CMTCVSOFFSET");
-    if (m_offset != "") 
-      {
-	m_offset += "/";
-	m_offset.replace_all ("//", "/");
+    m_cvs_offset = CmtSystem::getenv ("CMTCVSOFFSET");
+    if (m_cvs_offset != "") 
+      {
+	m_cvs_offset += "/";
+	m_cvs_offset.replace_all ("//", "/");
       }
     
@@ -2241,16 +2097,15 @@
 	    m_checkout_dir = option;
 	  }
-	else if (need_offset)
-	  {
-	    need_offset = false;
-	    m_offset = option;
-	    m_offset += '/';
-	    m_offset.replace_all ("//", "/");
-	  }
-	else if (need_branch_suffix)
-	  {
-	    need_branch_suffix = false;
-	    m_branch_suffix = "-";
-	    m_branch_suffix += option;
+	else if (need_version_dir)
+	  {
+	    need_version_dir = false;
+	    m_version_dir = option;
+	  }
+	else if (need_cvs_offset)
+	  {
+	    need_cvs_offset = false;
+	    m_cvs_offset = option;
+	    m_cvs_offset += '/';
+	    m_cvs_offset.replace_all ("//", "/");
 	  }
 	else if (need_requirements_file)
@@ -2281,5 +2136,5 @@
 	    else if (option == "-o")
 	      {
-		need_offset = true;
+		need_cvs_offset = true;
 	      }
 	    else if (option == "-n")
@@ -2291,7 +2146,7 @@
 		m_verbose = true;
 	      }
-	    else if (option == "-branch")
+	    else if (option == "-vd")
 	      {
-		need_branch_suffix = true;
+		need_version_dir = true;
 	      }
 	    else if (option == "-requirements")
@@ -2311,5 +2166,5 @@
 	    else
 	      {
-		do_checkout (option, version_tag);
+		do_checkout_phase1 (option, m_version_dir, version_tag);
 	      }
 	  }
@@ -2321,5 +2176,4 @@
   bool m_recursive;
   bool m_head;
-  bool m_cmtcvstest;
   bool m_verbose;
   bool m_simulation;
@@ -2327,6 +2181,6 @@
   cmt_string m_home_dir;
   cmt_string m_checkout_dir;
-  cmt_string m_offset;
-  cmt_string m_branch_suffix;
+  cmt_string m_version_dir;
+  cmt_string m_cvs_offset;
 
   cmt_string m_protocol_level;
@@ -2599,5 +2453,6 @@
   else
     {
-      m_cvs.do_checkout (path, package, version, "");
+      static const cmt_string empty;
+      m_cvs.do_checkout_phase2 (path, package, version, empty);
     }
 }
@@ -2678,5 +2533,5 @@
     }
   
-  cout << "  #     " << project << " " << version << endl;
+  cout << "  #     " << project << " " << version << " " << tag << endl;
 }
 
@@ -2760,5 +2615,6 @@
   else
     {
-      m_cvs.do_checkout ("", project, version, tag);
+      static const cmt_string empty;
+      m_cvs.do_checkout_phase2 (empty, project, version, tag);
     }
 }
Index: CMT/HEAD/src/setup.tcsh
===================================================================
--- CMT/HEAD/src/setup.tcsh	(revision 44)
+++ CMT/HEAD/src/setup.tcsh	(revision 45)
@@ -5,5 +5,5 @@
 #-----------------------------------------------------------
 
-complete cmt p/1/'(broadcast build check check_files checkout co cleanup config create expand filter help lock remove run setup show system unlock version cvstags cvsbranches cvssubpackages)'/ \
+complete cmt p/1/'(broadcast build check check_files checkout co cleanup config create expand filter help lock remove run setup show system unlock version cvstags cvsbranches cvssubpackages cvssubprojects)'/ \
  n/build/'(CMT_pacman constituent_makefile constituents_makefile dependencies library_links make_setup msdev os9_makefile prototype readme tag_makefile temporary_name triggers win_makefile)'/ \
  n/show/'(action action_names action_value actions all_tags applied_patterns author branches clients cmtpath_patterns constituent constituent_names constituents cycles fragment fragments groups include_dirs language languages macro macro_names macro_value macros manager packages path pattern patterns projects pwd set set_names set_value sets strategies tags use_paths uses versions)'/ \
Index: CMT/HEAD/src/setup.zsh
===================================================================
--- CMT/HEAD/src/setup.zsh	(revision 44)
+++ CMT/HEAD/src/setup.zsh	(revision 45)
@@ -12,5 +12,5 @@
    function cmt_default_path { d=`dirname ${CMTROOT}`; reply=(`dirname ${d}`) }; \
    function cmt_patterns { reply=(`cmt -quiet show pattern_names`) }; \
-   compctl -k '(broadcast,build,check,check_files,checkout,co,cleanup,config,create,create_project,expand,filter,help,lock,remove,run,setup,show,system,unlock,version,cvstags,cvsbranches,cvssubpackages)' -x \
+   compctl -k '(broadcast,build,check,check_files,checkout,co,cleanup,config,create,create_project,expand,filter,help,lock,remove,run,setup,show,system,unlock,version,cvstags,cvsbranches,cvssubpackages,cvssubprojects)' -x \
    'c[-1,broadcast]' -k '(-begin=,-select=,-exclude=,-local,-global,-depth=)' - \
    's[build],c[-1,build]' -k '(CMT_pacman, constituent_makefile,constituents_makefile,dependencies,library_links,make_setup,msdev,os9_makefile,prototype,readme,tag_makefile,temporary_name,triggers,win_makefile)' - \
