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 // arnault@lal.in2p3.fr
00004 // See the complete license in cmt_license.txt "http://www.cecill.info". 
00005 //-----------------------------------------------------------
00006 
00007 #include <stdlib.h>
00008 #include <stdio.h>
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 = "<package>";
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   bool get_version (const cmt_string& offset,
00776                     const cmt_string& product,
00777                     const cmt_string& version_request,
00778                     cmt_string& module,
00779                     cmt_string& version,
00780                     bool& at_head)
00781   {
00782     Grep grep;
00783     cmt_string topversions;
00784     cmt_string versions;
00785     cmt_string requested_version = version_request;
00786     
00787     at_head = false;
00788             
00789     module = "";
00790 
00791     if (offset != "")
00792       {
00793         module = offset;
00794         module += "/"; // This is for CVS only thus we don't use the real separator.
00795         while (module.find ("//") != cmt_string::npos)
00796           {
00797             module.replace_all ("//", "/");
00798           }
00799       }
00800 
00801     module += product;
00802 
00817     if (m_verbose)
00818       {
00819         cout << "#CMT> requesting cvs infos onto module " << module << endl;
00820       }
00821     
00822     get_cvs_infos_with_offset (module);
00823     
00824     if (error_info != "")
00825       {
00826         versions = "";
00827         cout << "#CMT> Product " << product << " not found in ${CVSROOT}" << endl;
00828         return (false);
00829       }
00830 
00831     versions = tags_top_info;
00832 
00833     cmt_string v = version_request;
00834     
00835     if (version_request.find ("*") != cmt_string::npos)
00836       {
00837         v.replace_all ("*", ".*");
00838       }
00839     else
00840       {
00841         // this is an exact match to the end of the word since there is no wild card
00842         v += "$";
00843       }
00844     
00845     cmt_regexp version_exp (v);
00846     
00847     if (!match_version_request (versions, version_exp, version))
00848       {
00849         // We try on non-top versions
00850 
00851         versions = tags_info;
00852 
00853         if (!match_version_request (versions, version_exp, version))
00854           {
00855             version = requested_version;
00856             int pos = 0;
00857             if ((pos = version.find ("*")) != cmt_string::npos)
00858               {
00859                 //
00860                 //  There was a wild card but the expression does not match
00861                 // any of the existing tags in CVS.
00862                 //  Things will be retreived from HEAD but we have to build
00863                 // a reasonable version tag from the wild card expression.
00864                 //  If the letter before the * was a digit, then simply remove
00865                 // the * (v5* -> v5) otherwise add a zero (v5r* -> v5r0)
00866                 //
00867                 if (pos > 0)
00868                   {
00869                     char letter = version[pos-1];
00870                     
00871                     static const cmt_string digits = "0123456789";
00872                     
00873                     if (digits.find (letter) == cmt_string::npos)
00874                       {
00875                         // "v5r*" -> "v5r0"
00876                         version.replace ("*", "0");
00877                       }
00878                     else
00879                       {
00880                         // "v5*" -> "v5"
00881                         version.replace ("*", "");
00882                       }
00883                   }
00884                 else
00885                   {
00886                     // The expression was simply "*" !!!
00887                     version = "v0";
00888                   }
00889               }
00890             at_head = true;
00891           }
00892         else
00893           {
00894             at_head = false;
00895           }
00896       }
00897     else
00898       {
00899         at_head = true;
00900       }
00901     
00906     return (true);
00907   }
00908 
00912   cmt_string build_version_directory (const cmt_string& offset,
00913                                       const cmt_string& product,
00914                                       const cmt_string& version)
00915   {
00916     cmt_string dir = m_home_dir;
00917     
00918     if (m_checkout_dir != "")
00919       {
00920         // consider the usual -d option 
00921  
00922         dir += CmtSystem::file_separator ();
00923         dir += m_checkout_dir;
00924       }
00925     
00926     dir += CmtSystem::file_separator ();
00927     dir += offset;
00928     dir += CmtSystem::file_separator ();
00929     dir += product;
00930     
00931     if ((structure_info == "project") || (Cmt::get_current_structuring_style () == with_version_directory))
00932       {
00933         dir += CmtSystem::file_separator ();
00934         dir += version;
00935       }
00936     
00937     CmtSystem::reduce_file_separators (dir);
00938     
00939     return (dir);
00940   }
00941 
00945   bool mkdir (const cmt_string& dir)
00946   {
00947     if (m_simulation)
00948       {
00949         cout << "#CMT> Would create the " << dir << " directory" << endl;
00950       }
00951     else
00952       {
00953         if (!CmtSystem::cd (dir))
00954           {
00955             if (m_verbose)
00956               {
00957                 cout << "#CMT> About to mkdir " << dir << endl;
00958               }
00959 
00960             CmtSystem::mkdir (dir);
00961             if (!CmtSystem::cd (dir))
00962               {
00963                 cout << "# Error creating the directory :" << dir << endl;
00964                 cout << "#---------------------------------------------------------" << endl;
00965                 return (false);
00966               }
00967           }
00968       }
00969     return (true);
00970   }
00971 
00977   void add_cmtpath (const cmt_string& dir)
00978   {
00979     static cmt_string CMTPATH;
00980 
00981     cmt_string cmtpath = CmtSystem::getenv ("CMTPATH");
00982 
00983     if (cmtpath.find (dir) == cmt_string::npos)
00984       {
00985         CMTPATH = "CMTPATH=";
00986         CMTPATH += dir;
00987         CMTPATH += ":";
00988         CMTPATH += cmtpath;
00989         
00990         CmtSystem::putenv (CMTPATH);
00991       }
00992 
00993     if (m_verbose)
00994       {
00995         cout << "#CMT> CMTPATH=" << CmtSystem::getenv ("CMTPATH") << endl;
00996       }
00997   }
00998 
01004   void make_management_files (const cmt_string& module,
01005                               const cmt_string& entries_text)
01006   {
01007     if (!CmtSystem::test_directory ("CVS"))
01008       {
01014         if (!mkdir ("CVS")) return;
01015 
01016         CmtSystem::cd ("..");
01017 
01018         cmt_string s;
01019         
01020         // Let's create first the CVS/Root file.
01021         
01022         CmtSystem::get_cvsroot (s);
01023         s += "\n";
01024         
01025         cmt_string f;
01026         
01027         f = "CVS";
01028         f += CmtSystem::file_separator ();
01029         f += "Root";
01030         
01031         if (m_simulation)
01032           {
01033             cout << "#CMT> Would fill in the CVS/Root file with " << endl;
01034             cout << s << endl;
01035           }
01036         else
01037           {
01038             if (m_verbose)
01039               {
01040                 cout << "#CMT> Fill in the CVS/Root file with " << endl;
01041                 cout << s << endl;
01042               }
01043             s.write (f);
01044           }
01045         
01046         // Now we create the CVS/Repository file
01047         
01048         f = "CVS";
01049         f += CmtSystem::file_separator ();
01050         f += "Repository";
01051         
01052         CmtSystem::get_cvsroot (s);
01053         if (s[0] == ':')
01054           {
01055             int pos = s.find (1, ":");
01056             s.erase (0, pos+1);
01057             pos = s.find (0, ":");
01058             s.erase (0, pos+1);
01059           }
01060         s += "/";
01061         s += module;
01062         s += "\n";
01063         
01064         if (m_simulation)
01065           {
01066             cout << "#CMT> Would fill in the CVS/Repository file with " << endl;
01067             cout << s << endl;
01068           }
01069         else
01070           {
01071             if (m_verbose)
01072               {
01073                 cout << "#CMT> Fill in the CVS/Repository file with " << endl;
01074                 cout << s << endl;
01075               }
01076             s.write (f);
01077           }
01078       }
01079     
01080     if (m_simulation)
01081       {
01082         cout << "#CMT> Would write the top CVS/Entries file with " << endl;
01083         cout << entries_text << endl;
01084       }
01085     else
01086       {
01087         cmt_string entries_file_name;
01088 
01089         entries_file_name = "CVS";
01090         entries_file_name += CmtSystem::file_separator ();
01091         entries_file_name += "Entries";
01092     
01093         cmt_string text;
01094 
01095         if (!text.read (entries_file_name))
01096           {
01097             // This happens when there were no top files
01098           }
01099 
01100         text += entries_text;
01101 
01102         // Now the CVS/Entries is ready to be created.
01103         if (m_verbose)
01104           {
01105             cout << "#CMT> Fill in the top CVS/Entries file with " << endl;
01106             cout << text << endl;
01107           }
01108 
01109         text.write (entries_file_name);
01110       }
01111 
01112   }
01113 
01117   bool really_checkout_project_contents (const cmt_string& offset,
01118                                          const cmt_string& project,
01119                                          const cmt_string& version,
01120                                          const cmt_string& tag,
01121                                          const cmt_string& module,
01122                                          const cmt_string& basedir,
01123                                          bool at_head,
01124                                          const cmt_string& currentdir)
01125   {
01126     cmt_string dir = currentdir;
01127 
01128     cout << "  # get project files into " << dir << endl;
01129 
01130     cmt_string version_dir = version;
01131 
01132     if (!mkdir (version_dir)) return (false);
01133 
01134     dir += CmtSystem::file_separator ();
01135     dir += version_dir;
01136     
01137     cmt_string command = "cvs -Q co -P ";
01138     if (!at_head)
01139       {
01140         command += "-r ";
01141         command += (tag != "") ? tag : version;
01142       }
01143 
01144     command += " -d cmt ";
01145 
01146     command += " ";
01147     command += module;
01148     command += "/cmt";
01149 
01150     execute_and_retry (command, "Error getting project CMT contents");
01151 
01152     make_management_files (module, "D/cmt////\n");
01153 
01154     return (true);
01155   }
01156 
01165   bool really_checkout_package_contents (const cmt_string& offset,
01166                                          const cmt_string& package,
01167                                          const cmt_string& version,
01168                                          const cmt_string& module,
01169                                          const cmt_string& basedir,
01170                                          bool at_head,
01171                                          const cmt_string& currentdir)
01172   {
01173     cmt_string dir = currentdir;
01174 
01175     cout << "  # get top files " << endl;
01176             
01177     cmt_string command = "cvs -Q co -P -l ";
01178     if (!at_head)
01179       {
01180         command += "-r ";
01181         command += version;
01182       }
01183     
01184     if (Cmt::get_current_structuring_style () == with_version_directory)
01185       {
01186         command += " -d ";
01187         command += version;
01188       }
01189     else
01190       {
01191         command += " -d ";
01192         command += package;
01193 
01194         // Must stand just above the package directory
01195         CmtSystem::cd ("..");
01196         CmtSystem::dirname (dir, dir);
01197       }
01198     
01199     command += " ";
01200     command += module;
01201     
01202     execute_and_retry (command, "Error getting package CMT contents");
01203 
01204     if (Cmt::get_current_structuring_style () == with_version_directory)
01205       {
01206         if (!mkdir (version)) return (false);
01207         
01208         dir += CmtSystem::file_separator ();
01209         dir += version;
01210       }
01211     else
01212       {
01213         if (!mkdir (package)) return (false);
01214         
01215         dir += CmtSystem::file_separator ();
01216         dir += package;
01217       }
01218     
01219     if (m_verbose)
01220       {
01221         cout << "#CMT> Now getting subdirectories pwd=" << CmtSystem::pwd () << " dir=" << dir << endl;
01222       }
01223 
01224     cmt_string branches = CmtSystem::getenv ("CMTCVSBRANCHES");
01225     
01226     if (branches == "")
01227       {
01228         branches = branches_info;
01229       }
01230     
01231     CmtSystem::cmt_string_vector branch_vector;
01232     
01233     CmtSystem::split (branches, " \t", branch_vector);
01234     
01235     cout << "  # get branches " << branches << endl;
01236     
01237     cmt_string text = "";
01238     
01239     command = "";
01240     
01241     int i;
01242     
01243     for (i = 0; i < branch_vector.size (); i++)
01244       {
01245         cmt_string& branch = branch_vector[i];
01246         
01247         if (i > 0)
01248           {
01249             command += CmtSystem::command_separator ();
01250           }
01251         
01252         command += "cvs -Q co ";
01253         
01254         if (!at_head)
01255           {
01256             command += "-r ";
01257             command += version;
01258           }
01259         
01260         command += " -d ";
01261         command += branch;
01262         command += " ";
01263         command += module;
01264         command += "/";    // CVS uses the '/' notation on all platforms!!
01265         command += branch;
01266         
01267         text += "D/";
01268         text += branch;
01269         text += "
01270       }
01271     
01272     execute_and_retry (command, "Error getting package contents");
01273 
01274     make_management_files (module, text);
01275 
01276     return (true);
01277   }
01278 
01282   bool really_checkout (const cmt_string& offset,
01283                         const cmt_string& product,
01284                         const cmt_string& version,
01285                         const cmt_string& tag,
01286                         const cmt_string& module,
01287                         const cmt_string& basedir,
01288                         bool at_head)
01289   {
01290     cmt_string dir = basedir;
01291     cmt_string out;
01292     
01293     cout << "# ================= working on " << structure_info << " " << product 
01294          << " version " << version;
01295 
01296     if (at_head) cout << " (At head) ";
01297 
01298     cmt_string full_offset;
01299 
01300     full_offset = m_cvs_offset;
01301     full_offset += offset;
01302 
01303     cmt_string echo_ppath;
01304         
01305     if (offset != "")
01306       {
01307         echo_ppath = " path ";
01308         echo_ppath += offset;
01309       }
01310     
01311     cout << echo_ppath << " in " << dir << endl;
01312 
01313     if ((structure_info == "project") || (Cmt::get_current_structuring_style () == with_version_directory))
01314       {
01315         // Move back to the product name.
01316         CmtSystem::dirname (dir, dir);
01317       }
01318 
01319     if (!mkdir (dir)) return (false);
01320         
01321     if (structure_info == "package")
01322       {
01323         really_checkout_package_contents (offset,
01324                                           product,
01325                                           version,
01326                                           module,
01327                                           basedir,
01328                                           at_head,
01329                                           dir);
01330       }
01331     else if (structure_info == "project")
01332       {
01333         really_checkout_project_contents (offset,
01334                                           product,
01335                                           version,
01336                                           tag,
01337                                           module,
01338                                           basedir,
01339                                           at_head,
01340                                           dir);
01341       }
01342 
01343     return (true);
01344   }
01345 
01346   cmt_string find_matching_version (const cmt_string& expression)
01347   {
01348     cmt_string result;
01349 
01350     //
01351     // Here expression takes the form
01352     //   <some path>/<expression with wild-card>
01353     //
01354 
01355     cmt_string dir;
01356     CmtSystem::dirname (expression, dir);
01357     dir += CmtSystem::file_separator ();
01358     
01359     cmt_string version;
01360     CmtSystem::basename (expression, version);
01361 
01362     if (version.find ("*") == cmt_string::npos)
01363       {
01364         // there is no wildcarding here. A simple test is enough.
01365         if (CmtSystem::test_directory (expression))
01366           {
01367             result = version;
01368           }
01369       }
01370     else
01371       {
01372         version.replace ("*", ".*");
01373         
01374         cmt_regexp exp (version);
01375         
01376         CmtSystem::cmt_string_vector list;
01377         
01378         CmtSystem::scan_dir (dir, exp, list);
01379         
01380         if (list.size () > 0)
01381           {
01382             result = list[0];
01383             
01384             CmtSystem::basename (result, result);
01385           }
01386       }
01387     
01388     return (result);
01389   }
01390   
01397   bool checkout_from_requirements (const cmt_string& requirements_path)
01398   {
01399     static cmt_regexp expression ("^[ \t]*use[ \t]");
01400 
01401     cmt_string text;
01402 
01403     text.read (requirements_path);
01404 
01405     RecursivePass1 p1;
01406     p1.run (text, expression);
01407 
01408     bool result = (p1.result () != "");
01409     RecursivePass2 p2 (*this);
01410     p2.run (p1.result ());
01411 
01412     return (result);
01413   }
01414 
01419   void checkout_from_project_file (const cmt_string& file_name)
01420   {
01421     static cmt_regexp expression ("^[ \t]*use[ \t]");
01422 
01423     cmt_string text;
01424 
01425     text.read (file_name);
01426 
01427     CvsImplementation& me = *this;
01428     CvsImplementation saved;
01429     saved = me;
01430     cmt_string here = CmtSystem::pwd ();
01431 
01432     RecursivePass3 p3;
01433     p3.run (text, expression);
01434 
01435     RecursivePass4 p4 (*this);
01436     p4.run (p3.result ());
01437 
01438     Grep grep;
01439 
01440     grep.run (text, "container");
01441     cmt_string container = grep.result ();
01442 
01443     if (container != "")
01444       {
01445         static cmt_regexp container_expression ("^[ \t]*container[ \t]");
01446 
01447         add_cmtpath (here);
01448 
01449         cout << "  # --> now getting project packages from the " << container << " " << here << endl;
01450 
01451         CmtSystem::cd (here);
01452 
01453         RecursivePass1 p1;
01454         p1.run (text, container_expression);
01455 
01456         RecursivePass2 p2 (*this);
01457 
01458         m_home_dir = CmtSystem::pwd ();
01459         p2.run (p1.result ());
01460       }
01461 
01462     CmtSystem::cd (here);
01463     me = saved;
01464   }
01465 
01477   void do_checkout_phase2 (const cmt_string& offset,
01478                            const cmt_string& product,
01479                            const cmt_string& specified_version,
01480                            const cmt_string& tag)
01481   {
01482     if (m_verbose)
01483       {
01484         cout << "#CMT> do_checkout_phase2> offset=" << offset
01485              << " " << structure_info << "=" << product
01486              << " specified_version=" << specified_version
01487              << " tag=" << tag
01488              << " pwd=" << CmtSystem::pwd ()
01489              << endl;
01490       }
01491     
01492     cmt_string version = specified_version;
01493     cmt_string empty;
01494     cmt_string full_offset;
01495 
01496     full_offset = m_cvs_offset;
01497     full_offset += offset;
01498     
01499     cmt_string echo_ppath;
01500     
01501     if (offset != "")
01502       {
01503         echo_ppath = " path ";
01504         echo_ppath += offset;
01505       }
01506     
01507     if (version == "")
01508       {
01509         cout << "# ================= No version specified for " << structure_info << " " << product << endl;
01510         return;
01511       }
01512     
01513     //
01514     //  First make an attempt to locate the specified version of
01515     //  this product "as-it-is" in the work area.
01516     //   Since 'version' may contain wild-card, it's likely that
01517     //  we should not simply use CmtSystem::test_directory but
01518     //  use the wild-card search.
01519     //
01520     
01521     cmt_string dir;
01522     
01523     dir = build_version_directory (offset, product, version);
01524     
01525     bool recursive = m_recursive;
01526     
01527     cmt_string effective_version = find_matching_version (dir);
01528     
01529     if (effective_version != "")
01530       {
01531         version = effective_version;
01532         
01533         dir = build_version_directory (offset, product, version);
01534         
01535         cout << "# ================= " << structure_info << " " << product 
01536              << " version " << version << echo_ppath 
01537              << " already installed in " << dir << endl;
01538         
01539         recursive = false;
01540       }
01541     else
01542       {
01543         bool at_head = false;
01544         cmt_string module;
01545         cmt_string cvs_tag = (tag != "") ? tag : version;
01546         
01547         //
01548         // get_version attempts to find the most appropriate version
01549         // tag matching the specification FROM the repository. However,
01550         // we should take into account situations where some versions have
01551         // already been checked out, in which case they might be sufficient
01552         // (or preferred?)
01553         //
01554         
01555         if (cvs_tag.find ("*") != cmt_string::npos)
01556           {
01557             cout << "# ================= " << structure_info << " " << product 
01558                  << " version " << cvs_tag << echo_ppath 
01559                  << " has wild cards and will not be considered." << endl;
01560             return;
01561           }
01562         
01563         if (!get_version (full_offset, product, cvs_tag,
01564                           module, cvs_tag, at_head))
01565           {
01566             return;
01567           }
01568         
01569         if (m_head)
01570           {
01571             m_head = false;
01572             
01573             at_head = true;
01574           }
01575         else
01576           {
01577             at_head = false;
01578           }
01579         
01580         //
01581         // Make a second try after having selected a CVS tag from all the
01582         // available tags compatible with the specified version
01583         //
01584 
01585         if (tag == "")
01586           {
01587             // If tag was not specified, then the version directory has to match the CVS tag
01588             // Otherwise the original version specification is kept for the directory.
01589 
01590             version = cvs_tag;
01591             dir = build_version_directory (offset, product, version);
01592           }
01593 
01594         if (CmtSystem::test_directory (dir))
01595           {
01596             cout << "# ================= " << structure_info << " " << product 
01597                  << " version " << version << echo_ppath 
01598                  << " already installed." << endl;
01599             
01600             recursive = false;
01601           }
01602         else
01603           {
01604             //
01605             // Now we can say that we have to perform the real checkout.
01606             // 
01607             
01608             if (!really_checkout (offset, product, version, cvs_tag, module, dir, at_head))
01609               {
01610                 cout << "# bad return from really_checkout_product" << endl;
01611                 return;
01612               }
01613           }
01614       }
01615     
01616     //
01617     //  Now reach the newly checked out product.
01618     //
01619     
01620     if (m_simulation)
01621       {
01622         cout << "#CMT> " << structure_info << " directory not really created " << dir << endl;
01623       }
01624     else if (structure_info == "package")
01625       {
01626         if (!CmtSystem::cd (dir))
01627           {
01628             cout << "#CMT> Package directory not created " << dir << endl;
01629             return;
01630           }
01631         
01632         // Check if it is a true CMT package.
01633         
01634         cmt_string file_name;
01635         
01636         file_name = "cmt";
01637         file_name += CmtSystem::file_separator ();
01638         file_name += "requirements";
01639         
01640         if (CmtSystem::test_file (file_name))
01641           {
01642             dir += CmtSystem::file_separator ();
01643             dir += "cmt";
01644             CmtSystem::cd ("cmt");
01645             
01646             if (Cmt::get_current_structuring_style () == without_version_directory)
01647               {
01648                 cmt_string text = version;
01649                 text += "\n";
01650                 text.write ("version.cmt");
01651               }
01652           }
01653         else
01654           {
01655             file_name = "mgr";
01656             file_name += CmtSystem::file_separator ();
01657             file_name += "requirements";
01658             
01659             if (CmtSystem::test_file (file_name))
01660               {
01661                 dir += CmtSystem::file_separator ();
01662                 dir += "mgr";
01663                 CmtSystem::cd ("mgr");
01664               }
01665             else
01666               {
01667                 cout << "# " << product << " not a CMT package" << endl;
01668                 return;
01669               }
01670           }
01671         
01672         if (recursive)
01673           {
01674             cmt_string here = CmtSystem::pwd ();
01675 
01676             bool did_recurse = checkout_from_requirements ("requirements");
01677 
01678             CmtSystem::cd (here);
01679 
01680             if (did_recurse) execute ("cmt -quiet broadcast cmt -quiet config");
01681           }
01682       }
01683     else if (structure_info == "project")
01684       {
01685         
01686         if (m_verbose)
01687           {
01688             cout << "#CMT> dir=" << dir << endl;
01689           }
01690         
01691         if (!CmtSystem::cd (dir))
01692           {
01693             cout << "#CMT> Project directory not created " << dir << endl;
01694             return;
01695           }
01696         
01697         cmt_string file_name;
01698         
01699         file_name = "cmt";
01700         file_name += CmtSystem::file_separator ();
01701         file_name += "project.cmt";
01702         
01703         if (!CmtSystem::test_file (file_name))
01704           {
01705             cout << "# " << product << " not a CMT project" << endl;
01706             return;
01707           }
01708         
01709         if (recursive)
01710           {
01711             checkout_from_project_file (file_name);
01712           }
01713 
01714         cout << "# ================= Project " << product << " completed" << endl;
01715 
01716       }
01717   }
01718   
01729   void do_checkout_phase1 (const cmt_string& module, 
01730                            const cmt_string& version_dir, 
01731                            const cmt_string& version_tag)
01732   {
01733     add_cmtpath (m_home_dir);
01734 
01735     History& h = History::instance ();
01736 
01737     h.clear ();
01738 
01739     if (module == "")
01740       {
01741         if (m_verbose)
01742           {
01743             cout << "#CMT> Missing module name" << endl;
01744           }
01745         return;
01746       }
01747 
01748     cmt_string offset;
01749     cmt_string product;
01750     cmt_string version;
01751     cmt_string tag;
01752     
01753     if (version_tag == "")
01754       {
01755         Cut cut (0);
01756         
01757         cmt_string m;
01758         m = m_cvs_offset;
01759         m += module;
01760         
01761         get_cvs_infos_with_offset (m);
01762         
01763         if (error_info != "")
01764           {
01765             cout << error_info << endl;
01766             return;
01767           }
01768 
01769         if (tags_top_info != "") tag = tags_top_info;
01770         else tag = tags_info;
01771         
01772         cut.run (tag);
01773         
01774         tag = cut.result ();
01775       }
01776     else
01777       {
01778         tag = version_tag;
01779       }
01780 
01781     version = (version_dir == "") ? tag : version_dir;
01782 
01783     CmtSystem::dirname (module, offset);
01784     CmtSystem::basename (module, product);
01785     
01786     cmt_string top_dir;
01787         
01788     top_dir = m_home_dir;
01789     top_dir += CmtSystem::file_separator ();
01790     top_dir += m_checkout_dir;
01791     top_dir += CmtSystem::file_separator ();
01792     top_dir += offset;
01793     top_dir += CmtSystem::file_separator ();
01794     top_dir += product;
01795     top_dir += CmtSystem::file_separator ();
01796     top_dir += version;
01797 
01798     CmtSystem::reduce_file_separators (top_dir);
01799 
01800     if (m_verbose)
01801       {
01802         cout << "#CMT> about to checkout " << structure_info
01803              << " " << product << " version " << version << " into " << top_dir << endl;
01804       }
01805 
01806     static const cmt_string empty;
01807     do_checkout_phase2 (offset, product, version, tag);
01808 
01809     if (m_simulation) return;
01810 
01811     if (!CmtSystem::cd (top_dir)) return;
01812 
01813     if (structure_info == "project")
01814       {
01815         cmt_string file_name;
01816     
01817         file_name = "cmt";
01818         file_name += CmtSystem::file_separator ();
01819         file_name += "project.cmt";
01820         
01821         if (!CmtSystem::test_file (file_name))
01822           {
01823             cout << "# " << product << " was not properly checked out and is missing its cmt/project.cmt file" << endl;
01824             return;
01825           }
01826       }
01827     else
01828       {
01829         cmt_string file_name;
01830     
01831         file_name = "cmt";
01832         file_name += CmtSystem::file_separator ();
01833         file_name += "requirements";
01834         
01835         if (CmtSystem::test_file (file_name))
01836           {
01837             top_dir += CmtSystem::file_separator ();
01838             top_dir += "cmt";
01839             CmtSystem::cd ("cmt");
01840           }
01841         else
01842           {
01843             file_name = "mgr";
01844             file_name += CmtSystem::file_separator ();
01845             file_name += "requirements";
01846             
01847             if (CmtSystem::test_file (file_name))
01848               {
01849                 top_dir += CmtSystem::file_separator ();
01850                 top_dir += "mgr";
01851                 CmtSystem::cd ("mgr");
01852               }
01853             else
01854               {
01855                 cout << "# " << product << " was not properly checked out and is missing its cmt/requirements file" << endl;
01856                 return;
01857               }
01858           }
01859         
01860         if (m_verbose)
01861           {
01862             cout << "#CMT> product " << product << " has been checked out" << endl;
01863           }
01864         
01865         if (!m_recursive)
01866           {
01867             execute ("cmt -quiet config");
01868           }
01869       }
01870   }
01871 
01872   void help ()
01873   {
01874     cout << "> cd <some work area>" << endl;
01875     cout << "> cmt checkout [modifier ...] <package|project>" << endl;
01876     cout << "" << endl;
01877     cout << "   modifier :" << endl;
01878     cout << "   -l        Do not process used packages (default)." << endl;
01879     cout << "   -R        Process used products recursively." << endl;
01880     cout << "   -r rev    Check out version tag. (is sticky)" << endl;
01881     cout << "   -vd dir   Use this version directory instead of CVS tag." << endl;
01882     cout << "   -d dir    Check out into dir instead of module name." << endl;
01883     cout << "   -o offset Offset in the CVS repository" << endl;
01884     cout << "   -requirements <requirements file path>  Check out packages referenced in this requirements file" << endl;
01885     cout << "   -n        simulation mode on" << endl;
01886     cout << "   -v        verbose mode on" << endl;
01887     cout << "   --help    print this help" << endl;
01888     cout << "" << endl;
01889     cout << "> cmt cvstags <package|project>" << endl;
01890     cout << "> cmt cvssubpackages <directory>" << endl;
01891     cout << "> cmt cvssubprojects <directory>" << endl;
01892     cout << "" << endl;
01893   }
01894 
01899   void tags (const CmtSystem::cmt_string_vector& arguments)
01900   {
01901     if (arguments.size () < 1)
01902       {
01903         help ();
01904         return;
01905       }
01906     
01907     if (CmtSystem::getenv ("CVSROOT") == "")
01908       {
01909         cout << "# Please set CVSROOT first !" << endl;
01910         return;
01911       }
01912     
01913     m_cvs_offset = CmtSystem::getenv ("CMTCVSOFFSET");
01914     if (m_cvs_offset != "") 
01915       {
01916         m_cvs_offset += "/";
01917         m_cvs_offset.replace_all ("//", "/");
01918       }
01919     
01920     bool all = false;
01921     
01922     for (int arg = 0; arg < arguments.size (); arg++)
01923       {
01924         const cmt_string& option = arguments[arg];
01925         
01926         if (option == "-all")
01927           {
01928             all = true;
01929           }
01930         else
01931           {
01932             get_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), option);
01933             
01934             if (error_info != "")
01935               {
01936                 cout << error_info << endl;
01937               }
01938             else
01939               {
01940                 cmt_string tags;
01941                 
01942                 if (all)
01943                   {
01944                     tags = cvsversions_top_info;
01945                     tags += " ";
01946                     tags += cvsversions_info;
01947                   }
01948                 else
01949                   {
01950                     tags = tags_top_info;
01951                     tags += " ";
01952                     tags += tags_info;
01953                   }
01954                 
01955                 CmtSystem::cmt_string_vector v;
01956                 
01957                 CmtSystem::split (tags, " \t", v);
01958                 for (int i = 0; i < v.size (); i++)
01959                   {
01960                     const cmt_string& s = v[i];
01961                     cout << s << endl;
01962                   }
01963               }
01964           }
01965       }
01966   }
01967 
01972   void branches (const cmt_string& module)
01973   {
01974     cmt_string out;
01975     
01976     get_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), module);
01977     
01978     if (error_info != "")
01979       {
01980         cout << error_info << endl;
01981       }
01982     else
01983       {
01984         cout << branches_info << endl;
01985       }
01986   }
01987 
01992   void subpackages (const cmt_string& module)
01993   {
01994     cmt_string out;
01995     
01996     get_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), (module == "") ? "." : module);
01997     
01998     if (error_info != "")
01999       {
02000         cout << error_info << endl;
02001       }
02002     else
02003       {
02004         cout << subpackages_info << endl;
02005       }
02006   }
02007   
02012   void subprojects (const cmt_string& module)
02013   {
02014     cmt_string out;
02015     
02016     get_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), (module == "") ? "." : module);
02017     
02018     if (error_info != "")
02019       {
02020         cout << error_info << endl;
02021       }
02022     else
02023       {
02024         cout << subprojects_info << endl;
02025       }
02026   }
02027 
02033   void checkout (const CmtSystem::cmt_string_vector& arguments)
02034   {
02035     if (arguments.size () < 1)
02036       {
02037         help ();
02038         return;
02039       }
02040     
02041     if (CmtSystem::getenv ("CVSROOT") == "")
02042       {
02043         cout << "# Please set CVSROOT first !" << endl;
02044         return;
02045       }
02046     
02047     m_home_dir = CmtSystem::pwd ();
02048     m_checkout_dir = "";
02049     m_version_dir = "";
02050     m_cvs_offset = "";
02051 
02052     cmt_string module;
02053     
02054     m_recursive = false;
02055     
02056     bool need_version_tag = false;
02057     cmt_string version_tag;
02058     
02059     bool need_checkout_dir = false;
02060     bool need_cvs_offset = false;
02061     bool need_requirements_file = false;
02062     bool need_version_dir = false;
02063     
02064     m_simulation = false;
02065     //m_verbose = true;
02066     m_verbose = false;
02067     
02068     m_head = true;
02069     
02070     m_cvs_offset = CmtSystem::getenv ("CMTCVSOFFSET");
02071     if (m_cvs_offset != "") 
02072       {
02073         m_cvs_offset += "/";
02074         m_cvs_offset.replace_all ("//", "/");
02075       }
02076     
02077     for (int arg = 0; arg < arguments.size (); arg++)
02078       {
02079         const cmt_string& option = arguments[arg];
02080         
02081         if (need_version_tag)
02082           {
02083             need_version_tag = false;
02084             
02085             if (option == "HEAD")
02086               {
02087                 m_head = true;
02088               }
02089             else
02090               {
02091                 version_tag = option;
02092               }
02093           }
02094         else if (need_checkout_dir)
02095           {
02096             need_checkout_dir = false;
02097             m_checkout_dir = option;
02098           }
02099         else if (need_version_dir)
02100           {
02101             need_version_dir = false;
02102             m_version_dir = option;
02103           }
02104         else if (need_cvs_offset)
02105           {
02106             need_cvs_offset = false;
02107             m_cvs_offset = option;
02108             m_cvs_offset += '/';
02109             m_cvs_offset.replace_all ("//", "/");
02110           }
02111         else if (need_requirements_file)
02112           {
02113             need_requirements_file = false;
02114             m_head = false;
02115             checkout_from_requirements (option);
02116           }
02117         else
02118           {
02119             if (option == "-R")
02120               {
02121                 m_recursive = true;
02122               }
02123             else if (option == "-l")
02124               {
02125                 m_recursive = false;
02126               }
02127             else if (option == "-r")
02128               {
02129                 need_version_tag = true;
02130                 m_head = false;
02131               }
02132             else if (option == "-d")
02133               {
02134                 need_checkout_dir = true;
02135               }
02136             else if (option == "-o")
02137               {
02138                 need_cvs_offset = true;
02139               }
02140             else if (option == "-n")
02141               {
02142                 m_simulation = true;
02143               }
02144             else if (option == "-v")
02145               {
02146                 m_verbose = true;
02147               }
02148             else if (option == "-vd")
02149               {
02150                 need_version_dir = true;
02151               }
02152             else if (option == "-requirements")
02153               {
02154                 need_requirements_file = true;
02155               }
02156             else if (option == "--help")
02157               {
02158                 help ();
02159                 return;
02160               }
02161             else if (option[0] == '-')
02162               {
02163                 help ();
02164                 return;
02165               }
02166             else
02167               {
02168                 do_checkout_phase1 (option, m_version_dir, version_tag);
02169               }
02170           }
02171       }
02172   }
02173 
02174 private:
02175 
02176   bool m_recursive;
02177   bool m_head;
02178   bool m_verbose;
02179   bool m_simulation;
02180 
02181   cmt_string m_home_dir;
02182   cmt_string m_checkout_dir;
02183   cmt_string m_version_dir;
02184   cmt_string m_cvs_offset;
02185 
02186   cmt_string m_protocol_level;
02187   cmt_string m_last_module;
02188   cmt_string m_last_cvs_infos;
02189   cmt_string structure_info;
02190   cmt_string error_info;
02191   cmt_string tags_top_info;
02192   cmt_string tags_info;
02193   cmt_string cvsversions_top_info;
02194   cmt_string cvsversions_info;
02195   cmt_string branches_info;
02196   cmt_string subpackages_info;
02197   cmt_string subprojects_info;
02198 };
02199 
02200 //--------------------------------------------------------------------
02201 
02202 void Grep::begin ()
02203 {
02204   m_result = "";
02205 }
02206 
02207 void Grep::filter (const cmt_string& line)
02208 {
02209     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "Grep::filter" << endl;
02210 
02211   if (m_result != "") m_result += " ";
02212   m_result += line;
02213 }
02214 
02215 const cmt_string& Grep::result () const
02216 {
02217   return (m_result);
02218 }
02219 
02220 //--------------------------------------------------------------------
02221 
02222 Cut::Cut (int field)
02223 {
02224   m_field = field;
02225 }
02226 
02227 void Cut::begin ()
02228 {
02229     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "Cut::begin" << endl;
02230   m_result = "";
02231 }
02232 
02233 void Cut::filter (const cmt_string& line)
02234 {
02235     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "Cut::filter" << endl;
02236 
02237   static CmtSystem::cmt_string_vector words;
02238   
02239   CmtSystem::split (line, " \t", words);
02240   
02241   if (words.size () <= m_field) return;
02242   
02243   if (m_result != "") m_result += " ";
02244   m_result += words[m_field];
02245 }
02246 
02247 const cmt_string& Cut::result () const
02248 {
02249   return (m_result);
02250 }
02251 
02252 //--------------------------------------------------------------------
02253 //--------------------------------------------------------------------
02254 
02255 History& History::instance ()
02256 {
02257   static History h;
02258   return (h);
02259 }
02260 
02261 void History::clear ()
02262 {
02263   m_installed = "";
02264 }
02265 
02266 void History::install (const cmt_string& line)
02267 {
02268   m_installed += "|";
02269   m_installed += line;
02270   m_installed += "|";
02271 }
02272 
02273 bool History::is_installed (const cmt_string& line)
02274 {
02275   if (m_installed.find (line) != cmt_string::npos)
02276     {
02277       return (true);
02278     }
02279   
02280   return (false);
02281 }
02282 
02283 History::History ()
02284 {
02285 }
02286 
02287 
02288 //--------------------------------------------------------------------
02289 
02290 void RecursivePass1::begin ()
02291 {
02292   m_first = true;
02293   m_result = "";
02294 }
02295 
02296 void RecursivePass1::filter (const cmt_string& line)
02297 {
02298     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "RecursivePass1::filter> " 
02299     //                                          << "line=[" << line << "]" << endl;
02300 
02301   if (line.find ("use CMT") != cmt_string::npos) return;
02302   if (line.find ("use cmt") != cmt_string::npos) return;
02303   
02304   History& h = History::instance ();
02305   
02306   if (h.is_installed (line)) return;
02307   
02308   CmtSystem::cmt_string_vector words;
02309   
02310   CmtSystem::split (line, " \t", words);
02311 
02312   enum
02313   {
02314     need_package,
02315     need_version,
02316     need_path,
02317     no_need
02318   } state = need_package;
02319 
02320   cmt_string package;
02321   cmt_string version;
02322   cmt_string path;
02323 
02324   for (int i = 1; i < words.size (); i++)
02325     {
02326       const cmt_string& s = words[i];
02327 
02328       if (s[0] == '-') continue;
02329 
02330       switch (state)
02331         {
02332           case need_package:
02333             package = s;
02334             state = need_version;
02335             break;
02336           case need_version:
02337             version = s;
02338             state = need_path;
02339             break;
02340           case need_path:
02341             path = s;
02342             state = no_need;
02343             break;
02344         }
02345     }
02346   
02347   if (version.find ("*") != cmt_string::npos)
02348     {
02349         /*
02350       cout << "# ================= Package " << package 
02351            << " version " << version << " " << path 
02352            << " has wild cards and will not be considered." << endl;
02353         */
02354       return;
02355     }
02356 
02362   m_result += line;
02363   m_result += "\n";
02364   
02365   if (m_first)
02366     {
02367       m_first = false;
02368       cout << "  # --> now propagate cmt checkout to :" << endl;
02369     }
02370   
02371   cout << "  #     " << package << " " << version << " " << path << endl;
02372 }
02373 
02374 const cmt_string& RecursivePass1::result () const
02375 {
02376   return (m_result);
02377 }
02378 
02379 //--------------------------------------------------------------------
02380 
02381 RecursivePass2::RecursivePass2 (CvsImplementation& cvs) : m_cvs (cvs)
02382 {
02383 }
02384 
02385 void RecursivePass2::begin ()
02386 {
02387 }
02388 
02389 void RecursivePass2::filter (const cmt_string& line)
02390 {
02391     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "RecursivePass2::filter> " 
02392     //                                          << "line=[" << line << "]" << endl;
02393 
02400   History& h = History::instance ();
02401   
02402   if (h.is_installed (line)) return;
02403   
02404   h.install (line);
02405   
02406   CmtSystem::cmt_string_vector words;
02407   
02408   CmtSystem::split (line, " \t", words);
02409 
02410   enum
02411   {
02412     need_package,
02413     need_version,
02414     need_path,
02415     no_need
02416   } state = need_package;
02417 
02418   cmt_string package;
02419   cmt_string version;
02420   cmt_string path;
02421 
02422   for (int i = 1; i < words.size (); i++)
02423     {
02424       const cmt_string& s = words[i];
02425 
02426       if (s[0] == '-') continue;
02427 
02428       switch (state)
02429         {
02430           case need_package:
02431             package = s;
02432             state = need_version;
02433             break;
02434           case need_version:
02435             version = s;
02436             state = need_path;
02437             break;
02438           case need_path:
02439             path = s;
02440             state = no_need;
02441             break;
02442         }
02443     }
02444 
02445   if (version.find ("*") != cmt_string::npos)
02446     {
02447         /*
02448       cout << "# ================= Package " << package 
02449            << " version " << version << " " << path 
02450            << " has wild cards and will not be considered." << endl;
02451         */
02452     }
02453   else
02454     {
02455       static const cmt_string empty;
02456       m_cvs.do_checkout_phase2 (path, package, version, empty);
02457     }
02458 }
02459 
02460 //--------------------------------------------------------------------
02461 
02462 void RecursivePass3::begin ()
02463 {
02464   m_first = true;
02465   m_result = "";
02466 }
02467 
02468 void RecursivePass3::filter (const cmt_string& line)
02469 {
02470   History& h = History::instance ();
02471   
02472   if (h.is_installed (line)) return;
02473   
02474   CmtSystem::cmt_string_vector words;
02475   
02476   CmtSystem::split (line, " \t", words);
02477 
02478   enum
02479   {
02480     need_project,
02481     need_version,
02482     need_tag,
02483     no_need
02484   } state = need_project;
02485 
02486   cmt_string project;
02487   cmt_string version;
02488   cmt_string tag;
02489 
02490   for (int i = 1; i < words.size (); i++)
02491     {
02492       const cmt_string& s = words[i];
02493 
02494       switch (state)
02495         {
02496           case need_project:
02497             project = s;
02498             state = need_version;
02499             break;
02500           case need_version:
02501             version = s;
02502             state = need_tag;
02503             break;
02504           case need_tag:
02505             tag = s;
02506             state = no_need;
02507             break;
02508         }
02509     }
02510   
02511   if (version.find ("*") != cmt_string::npos)
02512     {
02513         /*
02514       cout << "# ================= Project " << project 
02515            << " version " << version << " " << path 
02516            << " has wild cards and will not be considered." << endl;
02517         */
02518       return;
02519     }
02520 
02526   m_result += line;
02527   m_result += "\n";
02528   
02529   if (m_first)
02530     {
02531       m_first = false;
02532       cout << "  # --> now propagate cmt checkout to :" << endl;
02533     }
02534   
02535   cout << "  #     " << project << " " << version << " " << tag << endl;
02536 }
02537 
02538 const cmt_string& RecursivePass3::result () const
02539 {
02540   return (m_result);
02541 }
02542 
02543 //--------------------------------------------------------------------
02544 
02545 RecursivePass4::RecursivePass4 (CvsImplementation& cvs) : m_cvs (cvs)
02546 {
02547 }
02548 
02549 void RecursivePass4::begin ()
02550 {
02551 }
02552 
02553 void RecursivePass4::filter (const cmt_string& line)
02554 {
02555     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "RecursivePass4::filter> " 
02556     //                                          << "line=[" << line << "]" << endl;
02557 
02564   History& h = History::instance ();
02565   
02566   if (h.is_installed (line)) return;
02567   
02568   h.install (line);
02569   
02570   CmtSystem::cmt_string_vector words;
02571   
02572   CmtSystem::split (line, " \t", words);
02573 
02574   enum
02575   {
02576     need_project,
02577     need_version,
02578     need_tag,
02579     no_need
02580   } state = need_project;
02581 
02582   cmt_string project;
02583   cmt_string version;
02584   cmt_string tag;
02585 
02586   for (int i = 1; i < words.size (); i++)
02587     {
02588       const cmt_string& s = words[i];
02589 
02590       switch (state)
02591         {
02592           case need_project:
02593             project = s;
02594             state = need_version;
02595             break;
02596           case need_version:
02597             version = s;
02598             state = need_tag;
02599             break;
02600           case need_tag:
02601             tag = s;
02602             state = no_need;
02603             break;
02604         }
02605     }
02606 
02607   if (version.find ("*") != cmt_string::npos)
02608     {
02609         /*
02610       cout << "# ================= Project " << project 
02611            << " version " << version
02612            << " has wild cards and will not be considered." << endl;
02613         */
02614     }
02615   else
02616     {
02617       static const cmt_string empty;
02618       m_cvs.do_checkout_phase2 (empty, project, version, tag);
02619     }
02620 }
02621 
02622 //--------------------------------------------------------------------
02623 
02624 void Cvs::tags (const CmtSystem::cmt_string_vector& arguments)
02625 {
02626   CvsImplementation cvs;
02627 
02628   cvs.tags (arguments);
02629 }
02630 
02631 void Cvs::branches (const cmt_string& module)
02632 {
02633   CvsImplementation cvs;
02634 
02635   cvs.branches (module);
02636 }
02637 
02638 void Cvs::subpackages (const cmt_string& module)
02639 {
02640   CvsImplementation cvs;
02641 
02642   cvs.subpackages (module);
02643 }
02644 
02645 void Cvs::subprojects (const cmt_string& module)
02646 {
02647   CvsImplementation cvs;
02648 
02649   cvs.subprojects (module);
02650 }
02651 
02652 void Cvs::checkout (const CmtSystem::cmt_string_vector& arguments)
02653 {
02654   CvsImplementation cvs;
02655 
02656   cvs.checkout (arguments);
02657 }
02658 

Generated on Mon May 2 10:25:04 2005 for CMT by doxygen 1.3.5