Main?Page | Class?Hierarchy | Class?List | File?List | Class?Members | File?Members

cmt_cvs.cxx

Go to the documentation of this file.
00001 //-----------------------------------------------------------
00002 // Copyright Christian Arnault LAL-Orsay CNRS
00003 // 
00004 // See the complete license in cmt_license.txt "http://www.cecill.info". 
00005 //-----------------------------------------------------------
00006 
00007 #include 
00008 #include 
00009 
00010 #include "cmt.h"
00011 #include "cmt_cvs.h"
00012 #include "cmt_awk.h"
00013 #include "cmt_symbol.h"
00014 #include "cmt_project.h"
00015 
00033 class Grep : public Awk
00034 {
00035 public:
00036 
00037   void begin ();
00038   void filter (const cmt_string& line);
00039   const cmt_string& result () const;
00040 
00041 private:
00042   cmt_string m_result;
00043 };
00044 
00057 class Cut : public Awk
00058 {
00059 public:
00060   Cut (int field);
00061   void begin ();
00062   void filter (const cmt_string& line);
00063   const cmt_string& result () const;
00064 
00065 private:
00066   cmt_string m_result;
00067   int m_field;
00068 };
00069 
00076 class History
00077 {
00078 public:
00079   static History& instance ();
00080   void clear ();
00081   void install (const cmt_string& line);
00082   bool is_installed (const cmt_string& line);
00083 
00084 private:
00085   History ();
00086 
00087   cmt_string m_installed;
00088 };
00089 
00096 class RecursivePass1 : public Awk
00097 {
00098 public:
00099 
00100   void begin ();
00101   void filter (const cmt_string& line);
00102   const cmt_string& result () const;
00103 
00104 private:
00105   cmt_string m_result;
00106   bool m_first;
00107 };
00108 
00115 class CvsImplementation;
00116 class RecursivePass2 : public Awk
00117 {
00118 public:
00119   RecursivePass2 (CvsImplementation& cvs);
00120   void begin ();
00121   void filter (const cmt_string& line);
00122 
00123 private:
00124   CvsImplementation& m_cvs;
00125 };
00126 
00133 class RecursivePass3 : public Awk
00134 {
00135 public:
00136 
00137   void begin ();
00138   void filter (const cmt_string& line);
00139   const cmt_string& result () const;
00140 
00141 private:
00142   cmt_string m_result;
00143   bool m_first;
00144 };
00145 
00152 class CvsImplementation;
00153 class RecursivePass4 : public Awk
00154 {
00155 public:
00156   RecursivePass4 (CvsImplementation& cvs);
00157   void begin ();
00158   void filter (const cmt_string& line);
00159 
00160 private:
00161   CvsImplementation& m_cvs;
00162 };
00163 
00170 class CvsImplementation
00171 {
00172 public:
00173 
00174   CvsImplementation ()
00175   {
00176     clear ();
00177   }
00178 
00179   void clear ()
00180   {
00181     m_recursive  = false;
00182     m_head       = false;
00183     m_verbose    = false;
00184     m_simulation = false;
00185 
00186     m_home_dir     = "";
00187     m_checkout_dir = "";
00188     m_version_dir  = "";
00189     m_cvs_offset   = "";
00190 
00191     m_last_module        = "";
00192     m_last_cvs_infos     = "";
00193     structure_info       = "";
00194     error_info           = "";
00195     tags_top_info        = "";
00196     tags_info            = "";
00197     cvsversions_top_info = "";
00198     cvsversions_info     = "";
00199     branches_info        = "";
00200     subpackages_info     = "";
00201     subprojects_info     = "";
00202 
00203     m_protocol_level     = "";
00204 
00205     Symbol* symbol = Symbol::find ("cmt_cvs_protocol_level");
00206     if (symbol != 0)
00207       {
00208         m_protocol_level = symbol->build_macro_value ();
00209         Symbol::expand (m_protocol_level);
00210       }
00211   }
00212 
00213   CvsImplementation& operator = (const CvsImplementation& other)
00214   {
00215     m_recursive  = other.m_recursive;
00216     m_head       = other.m_head;
00217     m_verbose    = other.m_verbose;
00218     m_simulation = other.m_simulation;
00219 
00220     m_home_dir       = other.m_home_dir;
00221     m_checkout_dir   = other.m_checkout_dir;
00222     m_version_dir    = other.m_version_dir;
00223     m_cvs_offset     = other.m_cvs_offset;
00224     m_protocol_level = other.m_protocol_level;
00225     m_last_module    = other.m_last_module;
00226     m_last_cvs_infos = other.m_last_cvs_infos;
00227 
00228     structure_info       = other.structure_info;
00229     error_info           = other.error_info;
00230     tags_top_info        = other.tags_top_info;
00231     tags_info            = other.tags_info;
00232     cvsversions_top_info = other.cvsversions_top_info;
00233     cvsversions_info     = other.cvsversions_info;
00234     branches_info        = other.branches_info;
00235     subpackages_info     = other.subpackages_info;
00236     subprojects_info     = other.subprojects_info;
00237 
00238     return (*this);
00239   }
00240 
00244   void filter_list (cmt_string& text, const cmt_regexp& exp)
00245   {
00246     CmtSystem::cmt_string_vector list;
00247 
00248     CmtSystem::split (text, " ", list);
00249 
00250     int i;
00251 
00252     text = "";
00253 
00254     for (i = 0; i < list.size (); i++)
00255       {
00256         const cmt_string& s = list[i];
00257         if (exp.match (s))
00258           {
00259             if (i > 0) text += " ";
00260             text += s;
00261           }
00262       }
00263   }
00264 
00265   int execute (const cmt_string& command)
00266   {
00267     int status = 0;
00268 
00269     if (m_verbose || m_simulation)
00270       {
00271         cout << "#CMT> Executing [" << command << "]" << endl;
00272       }
00273     
00274     if (!m_simulation)
00275       {
00276         status = CmtSystem::execute (command);
00277       }
00278 
00279     return (status);
00280   }
00281 
00282   void execute_and_retry (const cmt_string& command, const cmt_string& message)
00283   {
00284     int status;
00285     int retry = 0;
00286 
00287     for (;;)
00288       {
00289         status = execute (command);
00290         
00291         if (status != 0)
00292           {
00293             retry++;
00294             
00295             cout << "# " << message << ": status=" << status << endl;
00296             cout << "#---------------------------------------------------------" << endl;
00297             
00298             if (retry > 5) exit(0);
00299           }
00300         else
00301           {
00302             break;
00303           }
00304       }
00305   }
00306 
00307   int execute (const cmt_string& command, cmt_string& out)
00308   {
00309     int status = 0;
00310 
00311     if (m_verbose || m_simulation)
00312       {
00313         cout << "#CMT> Executing [" << command << "]" << endl;
00314       }
00315     
00316     if (!m_simulation)
00317       {
00318         status = CmtSystem::execute (command, out);
00319       }
00320 
00321     return (status);
00322   }
00323 
00324 
00345   bool check_protocol ()
00346   {
00347     static bool done = false;
00348     static bool found = true;
00349 
00350     if (done) return (found);
00351     done = true;
00352 
00353     cmt_string cvsroot;
00354         
00355     CmtSystem::get_cvsroot (cvsroot);
00356         
00357     cmt_string command;
00358         
00359     command = "cvs";
00360     if (cvsroot != "") 
00361       {
00362         command += " -d ";
00363         command += cvsroot;
00364       }
00365     command += " -Q co -p CVSROOT/loginfo ";
00366 
00367     found = false;
00368 
00369     cmt_string pattern = ".cmtcvsinfos/";
00370     pattern += m_protocol_level;
00371 
00372     cmt_string loginfo;
00373 
00374     if (m_simulation)
00375       {
00376         loginfo = pattern;
00377       }
00378 
00379     execute (command, loginfo);
00380 
00381     int pos = loginfo.find (pattern);
00382 
00383     if (pos != cmt_string::npos)
00384       {
00385         found = true;
00386       }
00387 
00388     if (m_verbose)
00389       {
00390         if (found)
00391           {
00392             cout << "#CMT> Protocol level " << m_protocol_level << endl;
00393           }
00394         else
00395           {
00396             cout << "#CMT> The CVS pluggin is not installed or is not at protocol level " << m_protocol_level << endl;
00397           }
00398       }
00399     
00400     return (found);
00401   }
00402 
00410   void retreive_cvs_infos (const cmt_string& module)
00411   {
00412     static const cmt_string cmtcvsinfos = ".cmtcvsinfos";
00413 
00414     cmt_string home_dir = CmtSystem::pwd ();
00415         
00416     //
00417     // Activities related with .cmtcvsinfos will occur in a temporary directory
00418     //
00419     cmt_string tmp_dir = CmtSystem::getenv ("TMPDIR");
00420     if (tmp_dir == "")
00421       {
00422         tmp_dir = CmtSystem::file_separator ();
00423         tmp_dir += "tmp";
00424       }
00425     
00426     if (!CmtSystem::cd (tmp_dir))
00427       {
00428         tmp_dir = home_dir;
00429       }
00430     
00431     tmp_dir += CmtSystem::file_separator ();
00432     tmp_dir += "cmtcvs";
00433     {
00434       cmt_string temp = CmtSystem::get_temporary_name ();
00435       CmtSystem::basename (temp, temp);
00436       // Suppress dots for Windows
00437       temp.replace_all (".", "");
00438       tmp_dir += temp;
00439     }
00440     
00441     if (!CmtSystem::test_directory (tmp_dir))
00442       {
00443         if (!CmtSystem::mkdir (tmp_dir))
00444           {
00445             cout << "#CMT> Cannot create the temporary directory [" << tmp_dir << "]" << endl;
00446             return;
00447           }
00448       }
00449     
00450     //trap "rm -rf ${tmp_dir}" 0 1 2 15
00451     
00452     if (!CmtSystem::cd (tmp_dir))
00453       {
00454         cout << "#CMT> Cannot move to the temporary directory " << tmp_dir << endl;
00455         
00456         if (m_verbose)
00457           {
00458             cout << "#CMT> now removing tmp_dir " << tmp_dir << " home=" << home_dir << endl;
00459           }
00460         
00461         CmtSystem::remove_directory (tmp_dir);
00462         
00463         return;
00464       }
00465     
00466     if (m_verbose)
00467       {
00468         cout << "#CMT> cvs infos are now obtained from the temporary directory " << CmtSystem::pwd () << endl;  
00469       }
00470     
00486     if (!CmtSystem::test_directory (cmtcvsinfos))
00487       {
00488         CmtSystem::mkdir (cmtcvsinfos);
00489       }
00490     
00491     CmtSystem::cd (cmtcvsinfos);
00492     
00493     cmt_string cvsroot;
00494     
00495     CmtSystem::get_cvsroot (cvsroot);
00496     
00497     cmt_string command;
00498     
00499     command = "cvs";
00500     if (cvsroot != "") 
00501       {
00502         command += " -d ";
00503         command += cvsroot;
00504       }
00505     command += " -Q import -m cmt ";
00506     
00507     command += cmtcvsinfos;
00508     
00509     if (m_protocol_level != "")
00510       {
00511         command += "/";
00512         command += m_protocol_level;
00513       }
00514     command += "/";
00515     command += module;
00516     command += " CMT v1";
00517     
00518     m_last_cvs_infos = "";
00519 
00520     execute (command, m_last_cvs_infos);
00521     
00522     if (m_verbose)
00523       {
00524         cout << "#CMT> now removing tmp_dir " << tmp_dir << " home=" << home_dir << endl;
00525       }
00526     
00527     CmtSystem::cd (home_dir);
00528     CmtSystem::remove_directory (tmp_dir);      
00529   }
00530 
00554   void get_cvs_infos_with_offset (const cmt_string& module)
00555   {
00556     if (!check_protocol ())
00557       {
00558         cout << "#CMT> The CVS pluggin is not installed or is not at protocol level " << m_protocol_level << endl;
00559         return;
00560       }
00561 
00562     if (module == "")
00563       {
00564         cout << "#CMT> cmt cvs needs a module name" << endl;
00565         return;
00566       }
00567 
00568     if (module == m_last_module)
00569       {
00570         if (m_verbose)
00571           {
00572             cout << "#CMT> cvs infos for module " << module << " already there" << endl;
00573           }
00574       }
00575     else
00576       {
00577         m_last_module = module;
00578         
00579         retreive_cvs_infos (module);
00580       }
00581     
00586     Grep grep;
00587 
00588     grep.run (m_last_cvs_infos, "structure=");
00589     
00590     if (grep.result () != "")
00591       {
00592         structure_info = grep.result ();
00593         structure_info.replace ("structure=", "");
00594       }
00595     else
00596       {
00597         // This may happen for old protocol level < v1r1
00598         structure_info = "package";
00599       }
00600     
00601     grep.run (m_last_cvs_infos, "error=");
00602     
00603     if (grep.result () != "")
00604       {
00605         error_info = grep.result ();
00606         error_info.replace ("error=", "");
00607       }
00608     else
00609       {
00610         error_info = "";
00611       }
00612     
00613     grep.run (m_last_cvs_infos, "tags_top=");
00614     
00615     if (grep.result () != "")
00616       {
00617         tags_top_info = grep.result ();
00618         tags_top_info.replace ("tags_top=", "");
00619       }
00620     else
00621       {
00622         tags_top_info = "";
00623       }
00624     
00625     grep.run (m_last_cvs_infos, "tags=");
00626     
00627     if (grep.result () != "")
00628       {
00629         tags_info = grep.result ();
00630         tags_info.replace ("tags=", "");
00631       }
00632     else
00633       {
00634         tags_info = "";
00635       }
00636     
00637     grep.run (m_last_cvs_infos, "cvsversions_top=");
00638     
00639     if (grep.result () != "")
00640       {
00641         cvsversions_top_info = grep.result ();
00642         cvsversions_top_info.replace ("cvsversions_top=", "");
00643       }
00644     else
00645       {
00646         cvsversions_top_info = "";
00647       }
00648     
00649     grep.run (m_last_cvs_infos, "cvsversions=");
00650     
00651     if (grep.result () != "")
00652       {
00653         cvsversions_info = grep.result ();
00654         cvsversions_info.replace ("cvsversions=", "");
00655       }
00656     else
00657       {
00658         cvsversions_info = "";
00659       }
00660     
00661     grep.run (m_last_cvs_infos, "branches=");
00662     
00663     if (grep.result () != "")
00664       {
00665         branches_info = grep.result ();
00666         branches_info.replace ("branches=", "");
00667       }
00668     else
00669       {
00670         branches_info = "";
00671       }
00672     
00673     grep.run (m_last_cvs_infos, "subpackages=");
00674     
00675     if (grep.result () != "")
00676       {
00677         subpackages_info = grep.result ();
00678         subpackages_info.replace ("subpackages=", "");
00679       }
00680     else
00681       {
00682         subpackages_info = "";
00683       }
00684     
00685     grep.run (m_last_cvs_infos, "subprojects=");
00686 
00687     if (grep.result () != "")
00688       {
00689         subprojects_info = grep.result ();
00690         subprojects_info.replace ("subprojects=", "");
00691       }
00692     else
00693       {
00694         subprojects_info = "";
00695       }
00696 
00702     cmt_string tag_filter = CmtSystem::getenv ("CMTCVSTAGFILTER");
00703     
00704     if (tag_filter != "")
00705       {
00706         cmt_string package;
00707         CmtSystem::basename (module, package);
00708         
00709         cmt_string pattern = "";
00710         
00711         tag_filter.replace_all (pattern, package);
00712         
00713         cmt_regexp exp (tag_filter);
00714         
00715         cmt_string text;
00716         
00717         filter_list (tags_top_info, exp);
00718         filter_list (tags_info, exp);
00719         filter_list (cvsversions_top_info, exp);
00720         filter_list (cvsversions_info, exp);
00721       }
00722   }
00723   
00724   void get_cvs_infos (const cmt_string& cvs_offset, const cmt_string& module)
00725   {
00726     cmt_string full_name;
00727 
00728     if (cvs_offset != "") 
00729       {
00730         full_name = cvs_offset;
00731         full_name += "/";
00732         while (full_name.find ("//") != cmt_string::npos)
00733           {
00734             full_name.replace_all ("//", "/");
00735           }
00736       }
00737 
00738     full_name += module;
00739 
00740     get_cvs_infos_with_offset (full_name);
00741   }
00742 
00751   bool match_version_request (const cmt_string& text, 
00752                               const cmt_regexp& version_exp,
00753                               cmt_string& version)
00754   {
00755     CmtSystem::cmt_string_vector vs;
00756       
00757     CmtSystem::split (text, " \t", vs);
00758 
00759     version = "";
00760 
00761     for (int i = 0; i < vs.size (); i++)
00762       {
00763         const cmt_string& vv = vs[i];
00764         
00765         if (version_exp.match (vv))
00766           {
00767             version = vv;
00768             return (true);
00769           }
00770       }
00771 
00772     return (false);
00773   }
00774 
00775   void get_module (const cmt_string& offset,
00776                    const cmt_string& product,
00777                    cmt_string& module)
00778   {
00779     module = "";
00780 
00781     if (offset != "")
00782       {
00783         module = offset;
00784         module += "/"; // This is for CVS only thus we don't use the real separator.
00785         while (module.find ("//") != cmt_string::npos)
00786           {
00787             module.replace_all ("//", "/");
00788           }
00789       }
00790 
00791     module += product;
00792   }
00793 
00794   bool get_version (const cmt_string& offset,
00795                     const cmt_string& product,
00796                     const cmt_string& version_request,
00797                     const cmt_string& module,
00798                     cmt_string& version,
00799                     bool& at_head)
00800   {
00801     Grep grep;
00802     cmt_string topversions;
00803     cmt_string versions;
00804     cmt_string requested_version = version_request;
00805     
00806     at_head = false;
00807             
00822     if (m_verbose)
00823       {
00824         cout << "#CMT> requesting cvs infos onto module " << module << endl;
00825       }
00826     
00827     get_cvs_infos_with_offset (module);
00828     
00829     if (error_info != "")
00830       {
00831         versions = "";
00832         cout << "#CMT> Product " << product << " not found in ${CVSROOT}" << endl;
00833         return (false);
00834       }
00835 
00836     versions = tags_top_info;
00837 
00838     cmt_string v = version_request;
00839     
00840     if (version_request.find ("*") != cmt_string::npos)
00841       {
00842         v.replace_all ("*", ".*");
00843       }
00844     else
00845       {
00846         // this is an exact match to the end of the word since there is no wild card
00847         v += "$";
00848       }
00849     
00850     cmt_regexp version_exp (v);
00851     
00852     if (!match_version_request (versions, version_exp, version))
00853       {
00854         // We try on non-top versions
00855 
00856         versions = tags_info;
00857 
00858         if (!match_version_request (versions, version_exp, version))
00859           {
00860             version = requested_version;
00861             int pos = 0;
00862             if ((pos = version.find ("*")) != cmt_string::npos)
00863               {
00864                 //
00865                 //  There was a wild card but the expression does not match
00866                 // any of the existing tags in CVS.
00867                 //  Things will be retreived from HEAD but we have to build
00868                 // a reasonable version tag from the wild card expression.
00869                 //  If the letter before the * was a digit, then simply remove
00870                 // the * (v5* -> v5) otherwise add a zero (v5r* -> v5r0)
00871                 //
00872                 if (pos > 0)
00873                   {
00874                     char letter = version[pos-1];
00875                     
00876                     static const cmt_string digits = "0123456789";
00877                     
00878                     if (digits.find (letter) == cmt_string::npos)
00879                       {
00880                         // "v5r*" -> "v5r0"
00881                         version.replace ("*", "0");
00882                       }
00883                     else
00884                       {
00885                         // "v5*" -> "v5"
00886                         version.replace ("*", "");
00887                       }
00888                   }
00889                 else
00890                   {
00891                     // The expression was simply "*" !!!
00892                     version = "v0";
00893                   }
00894               }
00895             at_head = true;
00896           }
00897         else
00898           {
00899             at_head = false;
00900           }
00901       }
00902     else
00903       {
00904         at_head = true;
00905       }
00906     
00911     return (true);
00912   }
00913 
00914   bool do_need_version ()
00915   {
00916     bool need_version = false;
00917 
00918     if (structure_info == "project")
00919       {
00920         need_version = true;
00921       }
00922     else
00923       {
00924         CmtStructuringStyle style = Cmt::get_current_structuring_style ();
00925 
00926         if (style == default_structuring_style)
00927           {
00928             Use& current_use = Use::current ();
00929             if (current_use.get_strategy ("VersionDirectory"))
00930               {
00931                 need_version = true;
00932               }
00933           }
00934         else if (style == with_version_directory)
00935           {
00936             need_version = true;
00937           }
00938       }
00939 
00940     return (need_version);
00941   }
00942 
00946   cmt_string build_version_directory (const cmt_string& offset,
00947                                       const cmt_string& product,
00948                                       const cmt_string& version)
00949   {
00950     cmt_string dir = m_home_dir;
00951     
00952     if (m_checkout_dir != "")
00953       {
00954         // consider the usual -d option 
00955  
00956         dir += CmtSystem::file_separator ();
00957         dir += m_checkout_dir;
00958       }
00959     
00960     dir += CmtSystem::file_separator ();
00961     dir += offset;
00962     dir += CmtSystem::file_separator ();
00963     dir += product;
00964 
00965     if (do_need_version ())
00966       {
00967         dir += CmtSystem::file_separator ();
00968         dir += version;
00969       }
00970     
00971     CmtSystem::reduce_file_separators (dir);
00972     
00973     return (dir);
00974   }
00975 
00979   bool mkdir (const cmt_string& dir)
00980   {
00981     if (m_simulation)
00982       {
00983         cout << "#CMT> Would create the " << dir << " directory" << endl;
00984       }
00985     else
00986       {
00987         if (!CmtSystem::cd (dir))
00988           {
00989             if (m_verbose)
00990               {
00991                 cout << "#CMT> About to mkdir " << dir << endl;
00992               }
00993 
00994             CmtSystem::mkdir (dir);
00995             if (!CmtSystem::cd (dir))
00996               {
00997                 cout << "# Error creating the directory :" << dir << endl;
00998                 cout << "#---------------------------------------------------------" << endl;
00999                 return (false);
01000               }
01001           }
01002       }
01003     return (true);
01004   }
01005 
01011   void add_cmtpath (const cmt_string& dir)
01012   {
01013     static cmt_string CMTPATH;
01014 
01015     cmt_string cmtpath = CmtSystem::getenv ("CMTPATH");
01016 
01017     if (cmtpath.find (dir) == cmt_string::npos)
01018       {
01019         CMTPATH = "CMTPATH=";
01020         CMTPATH += dir;
01021         CMTPATH += ":";
01022         CMTPATH += cmtpath;
01023         
01024         CmtSystem::putenv (CMTPATH);
01025       }
01026 
01027     if (m_verbose)
01028       {
01029         cout << "#CMT> CMTPATH=" << CmtSystem::getenv ("CMTPATH") << endl;
01030       }
01031   }
01032 
01038   void make_management_files (const cmt_string& module,
01039                               const cmt_string& entries_text)
01040   {
01041     if (!CmtSystem::test_directory ("CVS"))
01042       {
01048         if (!mkdir ("CVS")) return;
01049 
01050         CmtSystem::cd ("..");
01051 
01052         cmt_string s;
01053         
01054         // Let's create first the CVS/Root file.
01055         
01056         CmtSystem::get_cvsroot (s);
01057         s += "\n";
01058         
01059         cmt_string f;
01060         
01061         f = "CVS";
01062         f += CmtSystem::file_separator ();
01063         f += "Root";
01064         
01065         if (m_simulation)
01066           {
01067             cout << "#CMT> Would fill in the CVS/Root file with " << endl;
01068             cout << s << endl;
01069           }
01070         else
01071           {
01072             if (m_verbose)
01073               {
01074                 cout << "#CMT> Fill in the CVS/Root file with " << endl;
01075                 cout << s << endl;
01076               }
01077             s.write (f);
01078           }
01079         
01080         // Now we create the CVS/Repository file
01081         
01082         f = "CVS";
01083         f += CmtSystem::file_separator ();
01084         f += "Repository";
01085         
01086         CmtSystem::get_cvsroot (s);
01087         if (s[0] == ':')
01088           {
01089             int pos = s.find (1, ":");
01090             s.erase (0, pos+1);
01091             pos = s.find (0, ":");
01092             s.erase (0, pos+1);
01093           }
01094         s += "/";
01095         s += module;
01096         s += "\n";
01097         
01098         if (m_simulation)
01099           {
01100             cout << "#CMT> Would fill in the CVS/Repository file with " << endl;
01101             cout << s << endl;
01102           }
01103         else
01104           {
01105             if (m_verbose)
01106               {
01107                 cout << "#CMT> Fill in the CVS/Repository file with " << endl;
01108                 cout << s << endl;
01109               }
01110             s.write (f);
01111           }
01112       }
01113     
01114     if (m_simulation)
01115       {
01116         cout << "#CMT> Would write the top CVS/Entries file with " << endl;
01117         cout << entries_text << endl;
01118       }
01119     else
01120       {
01121         cmt_string entries_file_name;
01122 
01123         entries_file_name = "CVS";
01124         entries_file_name += CmtSystem::file_separator ();
01125         entries_file_name += "Entries";
01126     
01127         cmt_string text;
01128 
01129         if (!text.read (entries_file_name))
01130           {
01131             // This happens when there were no top files
01132           }
01133 
01134         text += entries_text;
01135 
01136         // Now the CVS/Entries is ready to be created.
01137         if (m_verbose)
01138           {
01139             cout << "#CMT> Fill in the top CVS/Entries file with " << endl;
01140             cout << text << endl;
01141           }
01142 
01143         text.write (entries_file_name);
01144       }
01145 
01146   }
01147 
01151   bool really_checkout_project_contents (const cmt_string& offset,
01152                                          const cmt_string& project,
01153                                          const cmt_string& version,
01154                                          const cmt_string& tag,
01155                                          const cmt_string& module,
01156                                          const cmt_string& basedir,
01157                                          bool at_head,
01158                                          const cmt_string& currentdir)
01159   {
01160     cmt_string dir = currentdir;
01161 
01162     cout << "  # get project files into " << dir << endl;
01163 
01164     cmt_string version_dir = version;
01165 
01166     if (!mkdir (version_dir)) return (false);
01167 
01168     dir += CmtSystem::file_separator ();
01169     dir += version_dir;
01170     
01171     cmt_string command = "cvs -Q co -P ";
01172     if (!at_head)
01173       {
01174         command += "-r ";
01175         command += (tag != "") ? tag : version;
01176       }
01177 
01178     command += " -d cmt ";
01179 
01180     command += " ";
01181     command += module;
01182     command += "/cmt";
01183 
01184     execute_and_retry (command, "Error getting project CMT contents");
01185 
01186     make_management_files (module, "D/cmt////\n");
01187 
01188     return (true);
01189   }
01190 
01199   bool really_checkout_package_contents (const cmt_string& offset,
01200                                          const cmt_string& package,
01201                                          const cmt_string& version,
01202                                          const cmt_string& module,
01203                                          const cmt_string& basedir,
01204                                          bool at_head,
01205                                          const cmt_string& currentdir)
01206   {
01207     cmt_string dir = currentdir;
01208 
01209     cout << "  # get top files " << endl;
01210             
01211     cmt_string command = "cvs -Q co -P -l ";
01212     if (!at_head)
01213       {
01214         command += "-r ";
01215         command += version;
01216       }
01217 
01218     bool need_version = do_need_version ();
01219 
01220     if (need_version)
01221       {
01222         command += " -d ";
01223         command += version;
01224       }
01225     else
01226       {
01227         command += " -d ";
01228         command += package;
01229 
01230         // Must stand just above the package directory
01231         CmtSystem::cd ("..");
01232         CmtSystem::dirname (dir, dir);
01233       }
01234     
01235     command += " ";
01236     command += module;
01237     
01238     execute_and_retry (command, "Error getting package CMT contents");
01239 
01240     if (need_version)
01241       {
01242         if (!mkdir (version)) return (false);
01243         
01244         dir += CmtSystem::file_separator ();
01245         dir += version;
01246       }
01247     else
01248       {
01249         if (!mkdir (package)) return (false);
01250         
01251         dir += CmtSystem::file_separator ();
01252         dir += package;
01253       }
01254     
01255     if (m_verbose)
01256       {
01257         cout << "#CMT> Now getting subdirectories pwd=" << CmtSystem::pwd () << " dir=" << dir << endl;
01258       }
01259 
01260     cmt_string branches = CmtSystem::getenv ("CMTCVSBRANCHES");
01261     
01262     if (branches == "")
01263       {
01264         branches = branches_info;
01265       }
01266     
01267     CmtSystem::cmt_string_vector branch_vector;
01268     
01269     CmtSystem::split (branches, " \t", branch_vector);
01270     
01271     cout << "  # get branches " << branches << endl;
01272     
01273     cmt_string text = "";
01274     
01275     command = "";
01276     
01277     int i;
01278     
01279     for (i = 0; i < branch_vector.size (); i++)
01280       {
01281         cmt_string& branch = branch_vector[i];
01282         
01283         if (i > 0)
01284           {
01285             command += CmtSystem::command_separator ();
01286           }
01287         
01288         command += "cvs -Q co ";
01289         
01290         if (!at_head)
01291           {
01292             command += "-r ";
01293             command += version;
01294           }
01295         
01296         command += " -d ";
01297         command += branch;
01298         command += " ";
01299         command += module;
01300         command += "/";    // CVS uses the '/' notation on all platforms!!
01301         command += branch;
01302         
01303         text += "D/";
01304         text += branch;
01305         text += "
01306       }
01307     
01308     execute_and_retry (command, "Error getting package contents");
01309 
01310     make_management_files (module, text);
01311 
01312     return (true);
01313   }
01314 
01318   bool really_checkout (const cmt_string& offset,
01319                         const cmt_string& product,
01320                         const cmt_string& version,
01321                         const cmt_string& tag,
01322                         const cmt_string& module,
01323                         const cmt_string& basedir,
01324                         bool at_head)
01325   {
01326     cmt_string dir = basedir;
01327     cmt_string out;
01328     
01329     cout << "# ================= working on " << structure_info << " " << product 
01330          << " version " << version;
01331 
01332     if (at_head) cout << " (At head) ";
01333 
01334     cmt_string full_offset;
01335 
01336     full_offset = m_cvs_offset;
01337     full_offset += offset;
01338 
01339     cmt_string echo_ppath;
01340         
01341     if (offset != "")
01342       {
01343         echo_ppath = " path ";
01344         echo_ppath += offset;
01345       }
01346     
01347     cout << echo_ppath << " in " << dir << endl;
01348 
01349     if (do_need_version ())
01350       {
01351         // Move back to the product name.
01352         CmtSystem::dirname (dir, dir);
01353       }
01354 
01355     if (!mkdir (dir)) return (false);
01356         
01357     if (structure_info == "package")
01358       {
01359         really_checkout_package_contents (offset,
01360                                           product,
01361                                           version,
01362                                           module,
01363                                           basedir,
01364                                           at_head,
01365                                           dir);
01366       }
01367     else if (structure_info == "project")
01368       {
01369         really_checkout_project_contents (offset,
01370                                           product,
01371                                           version,
01372                                           tag,
01373                                           module,
01374                                           basedir,
01375                                           at_head,
01376                                           dir);
01377       }
01378 
01379     return (true);
01380   }
01381 
01389   cmt_string find_matching_version (const cmt_string& expression)
01390   {
01391     cmt_string result;
01392 
01393     //
01394     // Here expression takes the form
01395     //   /
01396     //
01397 
01398     cmt_string dir;
01399     CmtSystem::dirname (expression, dir);
01400     dir += CmtSystem::file_separator ();
01401     
01402     cmt_string version;
01403     CmtSystem::basename (expression, version);
01404 
01405     if (version.find ("*") == cmt_string::npos)
01406       {
01407         // there is no wildcarding here. A simple test is enough.
01408         if (CmtSystem::test_directory (expression))
01409           {
01410             result = version;
01411           }
01412       }
01413     else
01414       {
01415         version.replace ("*", ".*");
01416         
01417         cmt_regexp exp (version);
01418         
01419         CmtSystem::cmt_string_vector list;
01420         
01421         CmtSystem::scan_dir (dir, exp, list);
01422         
01423         if (list.size () > 0)
01424           {
01425             result = list[0];
01426             
01427             CmtSystem::basename (result, result);
01428           }
01429       }
01430     
01431     return (result);
01432   }
01433   
01440   bool checkout_from_requirements (const cmt_string& requirements_path)
01441   {
01442     static cmt_regexp expression ("^[ \t]*use[ \t]");
01443 
01444     cmt_string text;
01445 
01446     text.read (requirements_path);
01447 
01448     RecursivePass1 p1;
01449     p1.run (text, expression);
01450 
01451     bool result = (p1.result () != "");
01452     RecursivePass2 p2 (*this);
01453     p2.run (p1.result ());
01454 
01455     return (result);
01456   }
01457 
01462   void checkout_from_project_file (const cmt_string& file_name)
01463   {
01464     static cmt_regexp expression ("^[ \t]*use[ \t]");
01465 
01466     cmt_string text;
01467 
01468     text.read (file_name);
01469 
01470     CvsImplementation& me = *this;
01471     CvsImplementation saved;
01472     saved = me;
01473     cmt_string here = CmtSystem::pwd ();
01474 
01475     RecursivePass3 p3;
01476     p3.run (text, expression);
01477 
01478     RecursivePass4 p4 (*this);
01479     p4.run (p3.result ());
01480 
01481     Grep grep;
01482 
01483     grep.run (text, "container");
01484     cmt_string container = grep.result ();
01485 
01486     if (container != "")
01487       {
01488         static cmt_regexp container_expression ("^[ \t]*container[ \t]");
01489 
01490         add_cmtpath (here);
01491 
01492         cout << "  # --> now getting project packages from the " << container << " " << here << endl;
01493 
01494         CmtSystem::cd (here);
01495 
01496         RecursivePass1 p1;
01497         p1.run (text, container_expression);
01498 
01499         RecursivePass2 p2 (*this);
01500 
01501         m_home_dir = CmtSystem::pwd ();
01502         p2.run (p1.result ());
01503       }
01504 
01505     CmtSystem::cd (here);
01506     me = saved;
01507   }
01508 
01513   bool check_structure (const cmt_string& dir)
01514   {
01515     bool result = false;
01516 
01517     if (!CmtSystem::test_directory (dir))
01518       {
01519         return (false);
01520       }
01521 
01522     if (structure_info == "package")
01523       {
01524         // Check if it is a true CMT package.
01525         
01526         cmt_string file_name;
01527         
01528         file_name = dir;
01529         file_name += CmtSystem::file_separator ();
01530         file_name += "cmt";
01531         file_name += CmtSystem::file_separator ();
01532         file_name += "requirements";
01533         
01534         if (CmtSystem::test_file (file_name))
01535           {
01536             result = true;
01537           }
01538         else
01539           {
01540             file_name = dir;
01541             file_name += CmtSystem::file_separator ();
01542             file_name += "mgr";
01543             file_name += CmtSystem::file_separator ();
01544             file_name += "requirements";
01545             
01546             if (CmtSystem::test_file (file_name))
01547               {
01548                 result = true;
01549               }
01550           }
01551       }
01552     else if (structure_info == "project")
01553       {
01554         cmt_string file_name;
01555         
01556         file_name = dir;
01557         file_name += CmtSystem::file_separator ();
01558         file_name += "cmt";
01559         file_name += CmtSystem::file_separator ();
01560         file_name += "project.cmt";
01561         
01562         if (CmtSystem::test_file (file_name))
01563           {
01564             result = true;
01565           }
01566       }
01567 
01568     return (result);
01569   }
01570 
01582   void do_checkout_phase2 (const cmt_string& offset,
01583                            const cmt_string& product,
01584                            const cmt_string& specified_version,
01585                            const cmt_string& tag)
01586   {
01587     if (m_verbose)
01588       {
01589         cout << "#CMT> do_checkout_phase2> offset=" << offset
01590              << " " << structure_info << "=" << product
01591              << " specified_version=" << specified_version
01592              << " tag=" << tag
01593              << " pwd=" << CmtSystem::pwd ()
01594              << endl;
01595       }
01596     
01597     cmt_string version = specified_version;
01598     cmt_string empty;
01599     cmt_string full_offset;
01600 
01601     full_offset = m_cvs_offset;
01602     full_offset += offset;
01603     
01604     cmt_string echo_ppath;
01605     
01606     if (offset != "")
01607       {
01608         echo_ppath = " path ";
01609         echo_ppath += offset;
01610       }
01611     
01612     if (version == "")
01613       {
01614         cout << "# ================= No version specified for " << structure_info << " " << product << endl;
01615         return;
01616       }
01617     
01618     //
01619     //  First make an attempt to locate the specified version of
01620     //  this product "as-it-is" in the work area.
01621     //   Since 'version' may contain wild-card, it's likely that
01622     //  we should not simply use CmtSystem::test_directory but
01623     //  use the wild-card search.
01624     //
01625     
01626     cmt_string dir;
01627     
01628     dir = build_version_directory (offset, product, version);
01629     
01630     bool recursive = m_recursive;
01631     
01632     cmt_string effective_version = find_matching_version (dir);
01633     
01634     cmt_string module;
01635     get_module (full_offset, product, module);
01636 
01637     cmt_string cvs_tag = (tag != "") ? tag : version;
01638     bool at_head = false;
01639 
01640     if (effective_version != "")
01641       {
01642         version = effective_version;
01643       }
01644     else
01645       {
01646         //
01647         // get_version attempts to find the most appropriate version
01648         // tag matching the specification FROM the repository. However,
01649         // we should take into account situations where some versions have
01650         // already been checked out, in which case they might be sufficient
01651         // (or preferred?)
01652         //
01653         
01654         if (cvs_tag.find ("*") != cmt_string::npos)
01655           {
01656             cout << "# ================= " << structure_info << " " << product 
01657                  << " version " << cvs_tag << echo_ppath 
01658                  << " has wild cards and will not be considered." << endl;
01659             return;
01660           }
01661         
01662         if (!get_version (full_offset, product, cvs_tag, module,
01663                           cvs_tag, at_head))
01664           {
01665             return;
01666           }
01667         
01668         if (m_head)
01669           {
01670             m_head = false;
01671             
01672             at_head = true;
01673           }
01674         else
01675           {
01676             at_head = false;
01677           }
01678         
01679         //
01680         // Make a second try after having selected a CVS tag from all the
01681         // available tags compatible with the specified version
01682         //
01683 
01684         if (tag == "")
01685           {
01686             // If tag was not specified, then the version directory has to match the CVS tag
01687             // Otherwise the original version specification is kept for the directory.
01688 
01689             version = cvs_tag;
01690             dir = build_version_directory (offset, product, version);
01691           }
01692       }
01693     
01694 
01695     if (check_structure (dir))
01696       {
01697         cout << "# ================= " << structure_info << " " << product 
01698              << " version " << version << echo_ppath 
01699              << " already installed." << endl;
01700         
01701         recursive = false;
01702       }
01703     else
01704       {
01705         //
01706         // Now we can say that we have to perform the real checkout.
01707         // 
01708         
01709         if (!really_checkout (offset, product, version, cvs_tag, module, dir, at_head))
01710           {
01711             cout << "# bad return from really_checkout_product" << endl;
01712             return;
01713           }
01714       }
01715 
01716     //
01717     //  Now reach the newly checked out product.
01718     //
01719     
01720     if (m_simulation)
01721       {
01722         cout << "#CMT> " << structure_info << " directory not really created " << dir << endl;
01723       }
01724     else if (structure_info == "package")
01725       {
01726         if (!CmtSystem::cd (dir))
01727           {
01728             cout << "#CMT> Package directory not created " << dir << endl;
01729             return;
01730           }
01731         
01732         // Check if it is a true CMT package.
01733         
01734         cmt_string file_name;
01735         
01736         file_name = "cmt";
01737         file_name += CmtSystem::file_separator ();
01738         file_name += "requirements";
01739         
01740         if (CmtSystem::test_file (file_name))
01741           {
01742             dir += CmtSystem::file_separator ();
01743             dir += "cmt";
01744             CmtSystem::cd ("cmt");
01745             
01746             if (do_need_version ())
01747               {
01748                 cmt_string text = version;
01749                 text += "\n";
01750                 text.write ("version.cmt");
01751               }
01752           }
01753         else
01754           {
01755             file_name = "mgr";
01756             file_name += CmtSystem::file_separator ();
01757             file_name += "requirements";
01758             
01759             if (CmtSystem::test_file (file_name))
01760               {
01761                 dir += CmtSystem::file_separator ();
01762                 dir += "mgr";
01763                 CmtSystem::cd ("mgr");
01764               }
01765             else
01766               {
01767                 cout << "# " << product << " not a CMT package" << endl;
01768                 return;
01769               }
01770           }
01771         
01772         if (recursive)
01773           {
01774             cmt_string here = CmtSystem::pwd ();
01775 
01776             bool did_recurse = checkout_from_requirements ("requirements");
01777 
01778             CmtSystem::cd (here);
01779 
01780             if (did_recurse) execute ("cmt -quiet broadcast cmt -quiet config");
01781           }
01782       }
01783     else if (structure_info == "project")
01784       {
01785         
01786         if (m_verbose)
01787           {
01788             cout << "#CMT> dir=" << dir << endl;
01789           }
01790         
01791         if (!CmtSystem::cd (dir))
01792           {
01793             cout << "#CMT> Project directory not created " << dir << endl;
01794             return;
01795           }
01796         
01797         cmt_string file_name;
01798         
01799         file_name = "cmt";
01800         file_name += CmtSystem::file_separator ();
01801         file_name += "project.cmt";
01802         
01803         if (!CmtSystem::test_file (file_name))
01804           {
01805             cout << "# " << product << " not a CMT project" << endl;
01806             return;
01807           }
01808         
01809         if (recursive)
01810           {
01811             checkout_from_project_file (file_name);
01812           }
01813 
01814         cout << "# ================= Project " << product << " completed" << endl;
01815 
01816       }
01817   }
01818   
01829   void do_checkout_phase1 (const cmt_string& module, 
01830                            const cmt_string& version_dir, 
01831                            const cmt_string& version_tag)
01832   {
01833     add_cmtpath (m_home_dir);
01834 
01835     History& h = History::instance ();
01836 
01837     h.clear ();
01838 
01839     if (module == "")
01840       {
01841         if (m_verbose)
01842           {
01843             cout << "#CMT> Missing module name" << endl;
01844           }
01845         return;
01846       }
01847 
01848     cmt_string offset;
01849     cmt_string product;
01850     cmt_string version;
01851     cmt_string tag;
01852     
01853     {
01854       cmt_string m;
01855       m = m_cvs_offset;
01856       m += module;
01857         
01858       get_cvs_infos_with_offset (m);
01859         
01860       if (error_info != "")
01861         {
01862           cout << error_info << endl;
01863           return;
01864         }
01865     }
01866 
01867     if (version_tag == "")
01868       {
01869         Cut cut (0);
01870         
01871         if (tags_top_info != "") tag = tags_top_info;
01872         else tag = tags_info;
01873         
01874         cut.run (tag);
01875         
01876         tag = cut.result ();
01877       }
01878     else
01879       {
01880         tag = version_tag;
01881       }
01882 
01883     version = (version_dir == "") ? tag : version_dir;
01884 
01885     CmtSystem::dirname (module, offset);
01886     CmtSystem::basename (module, product);
01887     
01888     cmt_string top_dir;
01889         
01890     top_dir = m_home_dir;
01891     top_dir += CmtSystem::file_separator ();
01892     top_dir += m_checkout_dir;
01893     top_dir += CmtSystem::file_separator ();
01894     top_dir += offset;
01895     top_dir += CmtSystem::file_separator ();
01896     top_dir += product;
01897     top_dir += CmtSystem::file_separator ();
01898     top_dir += version;
01899 
01900     CmtSystem::reduce_file_separators (top_dir);
01901 
01902     if (m_verbose)
01903       {
01904         cout << "#CMT> about to checkout " << structure_info
01905              << " " << product << " version " << version << " into " << top_dir << endl;
01906       }
01907 
01908     static const cmt_string empty;
01909     do_checkout_phase2 (offset, product, version, tag);
01910 
01911     if (m_simulation) return;
01912 
01913     if (!CmtSystem::cd (top_dir)) return;
01914 
01915     if (structure_info == "project")
01916       {
01917         cmt_string file_name;
01918     
01919         file_name = "cmt";
01920         file_name += CmtSystem::file_separator ();
01921         file_name += "project.cmt";
01922         
01923         if (!CmtSystem::test_file (file_name))
01924           {
01925             cout << "# " << product << " was not properly checked out and is missing its cmt/project.cmt file" << endl;
01926             return;
01927           }
01928       }
01929     else
01930       {
01931         cmt_string file_name;
01932     
01933         file_name = "cmt";
01934         file_name += CmtSystem::file_separator ();
01935         file_name += "requirements";
01936         
01937         if (CmtSystem::test_file (file_name))
01938           {
01939             top_dir += CmtSystem::file_separator ();
01940             top_dir += "cmt";
01941             CmtSystem::cd ("cmt");
01942           }
01943         else
01944           {
01945             file_name = "mgr";
01946             file_name += CmtSystem::file_separator ();
01947             file_name += "requirements";
01948             
01949             if (CmtSystem::test_file (file_name))
01950               {
01951                 top_dir += CmtSystem::file_separator ();
01952                 top_dir += "mgr";
01953                 CmtSystem::cd ("mgr");
01954               }
01955             else
01956               {
01957                 cout << "# " << product << " was not properly checked out and is missing its cmt/requirements file" << endl;
01958                 return;
01959               }
01960           }
01961         
01962         if (m_verbose)
01963           {
01964             cout << "#CMT> product " << product << " has been checked out" << endl;
01965           }
01966         
01967         if (!m_recursive)
01968           {
01969             execute ("cmt -quiet config");
01970           }
01971       }
01972   }
01973 
01974   void help ()
01975   {
01976     cout << "> cd " << endl;
01977     cout << "> cmt checkout [modifier ...] " << endl;
01978     cout << "" << endl;
01979     cout << "   modifier :" << endl;
01980     cout << "   -l        Do not process used packages (default)." << endl;
01981     cout << "   -R        Process used products recursively." << endl;
01982     cout << "   -r rev    Check out version tag. (is sticky)" << endl;
01983     cout << "   -vd dir   Use this version directory instead of CVS tag." << endl;
01984     cout << "   -d dir    Check out into dir instead of module name." << endl;
01985     cout << "   -o offset Offset in the CVS repository" << endl;
01986     cout << "   -requirements   Check out packages referenced in this requirements file" << endl;
01987     cout << "   -n        simulation mode on" << endl;
01988     cout << "   -v        verbose mode on" << endl;
01989     cout << "   --help    print this help" << endl;
01990     cout << "" << endl;
01991     cout << "> cmt cvstags " << endl;
01992     cout << "> cmt cvssubpackages " << endl;
01993     cout << "> cmt cvssubprojects " << endl;
01994     cout << "" << endl;
01995   }
01996 
02001   void tags (const CmtSystem::cmt_string_vector& arguments)
02002   {
02003     if (arguments.size () < 1)
02004       {
02005         help ();
02006         return;
02007       }
02008     
02009     if (CmtSystem::getenv ("CVSROOT") == "")
02010       {
02011         cout << "# Please set CVSROOT first !" << endl;
02012         return;
02013       }
02014     
02015     m_cvs_offset = CmtSystem::getenv ("CMTCVSOFFSET");
02016     if (m_cvs_offset != "") 
02017       {
02018         m_cvs_offset += "/";
02019         m_cvs_offset.replace_all ("//", "/");
02020       }
02021     
02022     bool all = false;
02023     
02024     for (int arg = 0; arg < arguments.size (); arg++)
02025       {
02026         const cmt_string& option = arguments[arg];
02027         
02028         if (option == "-all")
02029           {
02030             all = true;
02031           }
02032         else
02033           {
02034             get_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), option);
02035             
02036             if (error_info != "")
02037               {
02038                 cout << error_info << endl;
02039               }
02040             else
02041               {
02042                 cmt_string tags;
02043                 
02044                 if (all)
02045                   {
02046                     tags = cvsversions_top_info;
02047                     tags += " ";
02048                     tags += cvsversions_info;
02049                   }
02050                 else
02051                   {
02052                     tags = tags_top_info;
02053                     tags += " ";
02054                     tags += tags_info;
02055                   }
02056                 
02057                 CmtSystem::cmt_string_vector v;
02058                 
02059                 CmtSystem::split (tags, " \t", v);
02060                 for (int i = 0; i < v.size (); i++)
02061                   {
02062                     const cmt_string& s = v[i];
02063                     cout << s << endl;
02064                   }
02065               }
02066           }
02067       }
02068   }
02069 
02074   void branches (const cmt_string& module)
02075   {
02076     cmt_string out;
02077     
02078     get_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), module);
02079     
02080     if (error_info != "")
02081       {
02082         cout << error_info << endl;
02083       }
02084     else
02085       {
02086         cout << branches_info << endl;
02087       }
02088   }
02089 
02094   void subpackages (const cmt_string& module)
02095   {
02096     cmt_string out;
02097     
02098     get_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), (module == "") ? "." : module);
02099     
02100     if (error_info != "")
02101       {
02102         cout << error_info << endl;
02103       }
02104     else
02105       {
02106         cout << subpackages_info << endl;
02107       }
02108   }
02109   
02114   void subprojects (const cmt_string& module)
02115   {
02116     cmt_string out;
02117     
02118     get_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), (module == "") ? "." : module);
02119     
02120     if (error_info != "")
02121       {
02122         cout << error_info << endl;
02123       }
02124     else
02125       {
02126         cout << subprojects_info << endl;
02127       }
02128   }
02129 
02135   void checkout (const CmtSystem::cmt_string_vector& arguments)
02136   {
02137     if (arguments.size () < 1)
02138       {
02139         help ();
02140         return;
02141       }
02142     
02143     if (CmtSystem::getenv ("CVSROOT") == "")
02144       {
02145         cout << "# Please set CVSROOT first !" << endl;
02146         return;
02147       }
02148     
02149     m_home_dir = CmtSystem::pwd ();
02150     m_checkout_dir = "";
02151     m_version_dir = "";
02152     m_cvs_offset = "";
02153 
02154     cmt_string module;
02155     
02156     m_recursive = false;
02157     
02158     bool need_version_tag = false;
02159     cmt_string version_tag;
02160     
02161     bool need_checkout_dir = false;
02162     bool need_cvs_offset = false;
02163     bool need_requirements_file = false;
02164     bool need_version_dir = false;
02165     
02166     m_simulation = false;
02167     //m_verbose = true;
02168     m_verbose = false;
02169     
02170     m_head = true;
02171     
02172     m_cvs_offset = CmtSystem::getenv ("CMTCVSOFFSET");
02173     if (m_cvs_offset != "") 
02174       {
02175         m_cvs_offset += "/";
02176         m_cvs_offset.replace_all ("//", "/");
02177       }
02178     
02179     for (int arg = 0; arg < arguments.size (); arg++)
02180       {
02181         const cmt_string& option = arguments[arg];
02182         
02183         if (need_version_tag)
02184           {
02185             need_version_tag = false;
02186             
02187             if (option == "HEAD")
02188               {
02189                 m_head = true;
02190               }
02191             else
02192               {
02193                 version_tag = option;
02194               }
02195           }
02196         else if (need_checkout_dir)
02197           {
02198             need_checkout_dir = false;
02199             m_checkout_dir = option;
02200           }
02201         else if (need_version_dir)
02202           {
02203             need_version_dir = false;
02204             m_version_dir = option;
02205           }
02206         else if (need_cvs_offset)
02207           {
02208             need_cvs_offset = false;
02209             m_cvs_offset = option;
02210             m_cvs_offset += '/';
02211             m_cvs_offset.replace_all ("//", "/");
02212           }
02213         else if (need_requirements_file)
02214           {
02215             need_requirements_file = false;
02216             m_head = false;
02217             checkout_from_requirements (option);
02218           }
02219         else
02220           {
02221             if (option == "-R")
02222               {
02223                 m_recursive = true;
02224               }
02225             else if (option == "-l")
02226               {
02227                 m_recursive = false;
02228               }
02229             else if (option == "-r")
02230               {
02231                 need_version_tag = true;
02232                 m_head = false;
02233               }
02234             else if (option == "-d")
02235               {
02236                 need_checkout_dir = true;
02237               }
02238             else if (option == "-o")
02239               {
02240                 need_cvs_offset = true;
02241               }
02242             else if (option == "-n")
02243               {
02244                 m_simulation = true;
02245               }
02246             else if (option == "-v")
02247               {
02248                 m_verbose = true;
02249               }
02250             else if (option == "-vd")
02251               {
02252                 need_version_dir = true;
02253               }
02254             else if (option == "-requirements")
02255               {
02256                 need_requirements_file = true;
02257               }
02258             else if (option == "--help")
02259               {
02260                 help ();
02261                 return;
02262               }
02263             else if (option[0] == '-')
02264               {
02265                 help ();
02266                 return;
02267               }
02268             else
02269               {
02270                 do_checkout_phase1 (option, m_version_dir, version_tag);
02271               }
02272           }
02273       }
02274   }
02275 
02276 private:
02277 
02278   bool m_recursive;
02279   bool m_head;
02280   bool m_verbose;
02281   bool m_simulation;
02282 
02283   cmt_string m_home_dir;
02284   cmt_string m_checkout_dir;
02285   cmt_string m_version_dir;
02286   cmt_string m_cvs_offset;
02287 
02288   cmt_string m_protocol_level;
02289   cmt_string m_last_module;
02290   cmt_string m_last_cvs_infos;
02291   cmt_string structure_info;
02292   cmt_string error_info;
02293   cmt_string tags_top_info;
02294   cmt_string tags_info;
02295   cmt_string cvsversions_top_info;
02296   cmt_string cvsversions_info;
02297   cmt_string branches_info;
02298   cmt_string subpackages_info;
02299   cmt_string subprojects_info;
02300 };
02301 
02302 //--------------------------------------------------------------------
02303 
02304 void Grep::begin ()
02305 {
02306   m_result = "";
02307 }
02308 
02309 void Grep::filter (const cmt_string& line)
02310 {
02311     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "Grep::filter" << endl;
02312 
02313   if (m_result != "") m_result += " ";
02314   m_result += line;
02315 }
02316 
02317 const cmt_string& Grep::result () const
02318 {
02319   return (m_result);
02320 }
02321 
02322 //--------------------------------------------------------------------
02323 
02324 Cut::Cut (int field)
02325 {
02326   m_field = field;
02327 }
02328 
02329 void Cut::begin ()
02330 {
02331     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "Cut::begin" << endl;
02332   m_result = "";
02333 }
02334 
02335 void Cut::filter (const cmt_string& line)
02336 {
02337     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "Cut::filter" << endl;
02338 
02339   static CmtSystem::cmt_string_vector words;
02340   
02341   CmtSystem::split (line, " \t", words);
02342   
02343   if (words.size () <= m_field) return;
02344   
02345   if (m_result != "") m_result += " ";
02346   m_result += words[m_field];
02347 }
02348 
02349 const cmt_string& Cut::result () const
02350 {
02351   return (m_result);
02352 }
02353 
02354 //--------------------------------------------------------------------
02355 //--------------------------------------------------------------------
02356 
02357 History& History::instance ()
02358 {
02359   static History h;
02360   return (h);
02361 }
02362 
02363 void History::clear ()
02364 {
02365   m_installed = "";
02366 }
02367 
02368 void History::install (const cmt_string& line)
02369 {
02370   m_installed += "|";
02371   m_installed += line;
02372   m_installed += "|";
02373 }
02374 
02375 bool History::is_installed (const cmt_string& line)
02376 {
02377   if (m_installed.find (line) != cmt_string::npos)
02378     {
02379       return (true);
02380     }
02381   
02382   return (false);
02383 }
02384 
02385 History::History ()
02386 {
02387 }
02388 
02389 
02390 //--------------------------------------------------------------------
02391 
02392 void RecursivePass1::begin ()
02393 {
02394   m_first = true;
02395   m_result = "";
02396 }
02397 
02398 void RecursivePass1::filter (const cmt_string& line)
02399 {
02400     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "RecursivePass1::filter> " 
02401     //                                          << "line=[" << line << "]" << endl;
02402 
02403   if (line.find ("use CMT") != cmt_string::npos) return;
02404   if (line.find ("use cmt") != cmt_string::npos) return;
02405   
02406   History& h = History::instance ();
02407   
02408   if (h.is_installed (line)) return;
02409   
02410   CmtSystem::cmt_string_vector words;
02411   
02412   CmtSystem::split (line, " \t", words);
02413 
02414   enum
02415   {
02416     need_package,
02417     need_version,
02418     need_path,
02419     no_need
02420   } state = need_package;
02421 
02422   cmt_string package;
02423   cmt_string version;
02424   cmt_string path;
02425 
02426   for (int i = 1; i < words.size (); i++)
02427     {
02428       const cmt_string& s = words[i];
02429 
02430       if (s[0] == '-') continue;
02431 
02432       switch (state)
02433         {
02434           case need_package:
02435             package = s;
02436             state = need_version;
02437             break;
02438           case need_version:
02439             version = s;
02440             state = need_path;
02441             break;
02442           case need_path:
02443             path = s;
02444             state = no_need;
02445             break;
02446         }
02447     }
02448   
02449   if (version.find ("*") != cmt_string::npos)
02450     {
02451         /*
02452       cout << "# ================= Package " << package 
02453            << " version " << version << " " << path 
02454            << " has wild cards and will not be considered." << endl;
02455         */
02456       return;
02457     }
02458 
02464   m_result += line;
02465   m_result += "\n";
02466   
02467   if (m_first)
02468     {
02469       m_first = false;
02470       cout << "  # --> now propagate cmt checkout to :" << endl;
02471     }
02472   
02473   cout << "  #     " << package << " " << version << " " << path << endl;
02474 }
02475 
02476 const cmt_string& RecursivePass1::result () const
02477 {
02478   return (m_result);
02479 }
02480 
02481 //--------------------------------------------------------------------
02482 
02483 RecursivePass2::RecursivePass2 (CvsImplementation& cvs) : m_cvs (cvs)
02484 {
02485 }
02486 
02487 void RecursivePass2::begin ()
02488 {
02489 }
02490 
02491 void RecursivePass2::filter (const cmt_string& line)
02492 {
02493     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "RecursivePass2::filter> " 
02494     //                                          << "line=[" << line << "]" << endl;
02495 
02502   History& h = History::instance ();
02503   
02504   if (h.is_installed (line)) return;
02505   
02506   h.install (line);
02507   
02508   CmtSystem::cmt_string_vector words;
02509   
02510   CmtSystem::split (line, " \t", words);
02511 
02512   enum
02513   {
02514     need_package,
02515     need_version,
02516     need_path,
02517     no_need
02518   } state = need_package;
02519 
02520   cmt_string package;
02521   cmt_string version;
02522   cmt_string path;
02523 
02524   for (int i = 1; i < words.size (); i++)
02525     {
02526       const cmt_string& s = words[i];
02527 
02528       if (s[0] == '-') continue;
02529 
02530       switch (state)
02531         {
02532           case need_package:
02533             package = s;
02534             state = need_version;
02535             break;
02536           case need_version:
02537             version = s;
02538             state = need_path;
02539             break;
02540           case need_path:
02541             path = s;
02542             state = no_need;
02543             break;
02544         }
02545     }
02546 
02547   if (version.find ("*") != cmt_string::npos)
02548     {
02549         /*
02550       cout << "# ================= Package " << package 
02551            << " version " << version << " " << path 
02552            << " has wild cards and will not be considered." << endl;
02553         */
02554     }
02555   else
02556     {
02557       static const cmt_string empty;
02558       m_cvs.do_checkout_phase2 (path, package, version, empty);
02559     }
02560 }
02561 
02562 //--------------------------------------------------------------------
02563 
02564 void RecursivePass3::begin ()
02565 {
02566   m_first = true;
02567   m_result = "";
02568 }
02569 
02570 void RecursivePass3::filter (const cmt_string& line)
02571 {
02572   History& h = History::instance ();
02573   
02574   if (h.is_installed (line)) return;
02575   
02576   CmtSystem::cmt_string_vector words;
02577   
02578   CmtSystem::split (line, " \t", words);
02579 
02580   enum
02581   {
02582     need_project,
02583     need_version,
02584     need_tag,
02585     no_need
02586   } state = need_project;
02587 
02588   cmt_string project;
02589   cmt_string version;
02590   cmt_string tag;
02591 
02592   for (int i = 1; i < words.size (); i++)
02593     {
02594       const cmt_string& s = words[i];
02595 
02596       switch (state)
02597         {
02598           case need_project:
02599             project = s;
02600             state = need_version;
02601             break;
02602           case need_version:
02603             version = s;
02604             state = need_tag;
02605             break;
02606           case need_tag:
02607             tag = s;
02608             state = no_need;
02609             break;
02610         }
02611     }
02612   
02613   if (version.find ("*") != cmt_string::npos)
02614     {
02615         /*
02616       cout << "# ================= Project " << project 
02617            << " version " << version << " " << path 
02618            << " has wild cards and will not be considered." << endl;
02619         */
02620       return;
02621     }
02622 
02628   m_result += line;
02629   m_result += "\n";
02630   
02631   if (m_first)
02632     {
02633       m_first = false;
02634       cout << "  # --> now propagate cmt checkout to :" << endl;
02635     }
02636   
02637   cout << "  #     " << project << " " << version << " " << tag << endl;
02638 }
02639 
02640 const cmt_string& RecursivePass3::result () const
02641 {
02642   return (m_result);
02643 }
02644 
02645 //--------------------------------------------------------------------
02646 
02647 RecursivePass4::RecursivePass4 (CvsImplementation& cvs) : m_cvs (cvs)
02648 {
02649 }
02650 
02651 void RecursivePass4::begin ()
02652 {
02653 }
02654 
02655 void RecursivePass4::filter (const cmt_string& line)
02656 {
02657     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "RecursivePass4::filter> " 
02658     //                                          << "line=[" << line << "]" << endl;
02659 
02666   History& h = History::instance ();
02667   
02668   if (h.is_installed (line)) return;
02669   
02670   h.install (line);
02671   
02672   CmtSystem::cmt_string_vector words;
02673   
02674   CmtSystem::split (line, " \t", words);
02675 
02676   enum
02677   {
02678     need_project,
02679     need_version,
02680     need_tag,
02681     no_need
02682   } state = need_project;
02683 
02684   cmt_string project;
02685   cmt_string version;
02686   cmt_string tag;
02687 
02688   for (int i = 1; i < words.size (); i++)
02689     {
02690       const cmt_string& s = words[i];
02691 
02692       switch (state)
02693         {
02694           case need_project:
02695             project = s;
02696             state = need_version;
02697             break;
02698           case need_version:
02699             version = s;
02700             state = need_tag;
02701             break;
02702           case need_tag:
02703             tag = s;
02704             state = no_need;
02705             break;
02706         }
02707     }
02708 
02709   if (version.find ("*") != cmt_string::npos)
02710     {
02711         /*
02712       cout << "# ================= Project " << project 
02713            << " version " << version
02714            << " has wild cards and will not be considered." << endl;
02715         */
02716     }
02717   else
02718     {
02719       static const cmt_string empty;
02720       m_cvs.do_checkout_phase2 (empty, project, version, tag);
02721     }
02722 }
02723 
02724 //--------------------------------------------------------------------
02725 
02726 void Cvs::tags (const CmtSystem::cmt_string_vector& arguments)
02727 {
02728   CvsImplementation cvs;
02729 
02730   cvs.tags (arguments);
02731 }
02732 
02733 void Cvs::branches (const cmt_string& module)
02734 {
02735   CvsImplementation cvs;
02736 
02737   cvs.branches (module);
02738 }
02739 
02740 void Cvs::subpackages (const cmt_string& module)
02741 {
02742   CvsImplementation cvs;
02743 
02744   cvs.subpackages (module);
02745 }
02746 
02747 void Cvs::subprojects (const cmt_string& module)
02748 {
02749   CvsImplementation cvs;
02750 
02751   cvs.subprojects (module);
02752 }
02753 
02754 void Cvs::checkout (const CmtSystem::cmt_string_vector& arguments)
02755 {
02756   CvsImplementation cvs;
02757 
02758   cvs.checkout (arguments);
02759 }
02760 

Generated on Mon Sep 5 16:30:47 2005 for CMT by 1.3.5