Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

cmt_cvs.cxx

Go to the documentation of this file.
00001 #include <stdlib.h>
00002 #include <stdio.h>
00003 
00004 #include "cmt_cvs.h"
00005 #include "cmt_awk.h"
00006 
00024 class Grep : public Awk
00025 {
00026 public:
00027 
00028   void begin ();
00029   void filter (const cmt_string& line);
00030   const cmt_string& result () const;
00031 
00032 private:
00033   cmt_string m_result;
00034 };
00035 
00048 class Cut : public Awk
00049 {
00050 public:
00051   Cut (int field);
00052   void begin ();
00053   void filter (const cmt_string& line);
00054   const cmt_string& result () const;
00055 
00056 private:
00057   cmt_string m_result;
00058   int m_field;
00059 };
00060 
00067 class History
00068 {
00069 public:
00070   static History& instance ();
00071   void clear ();
00072   void install (const cmt_string& line);
00073   bool is_installed (const cmt_string& line);
00074 
00075 private:
00076   History ();
00077 
00078   cmt_string m_installed;
00079 };
00080 
00087 class RecursivePass1 : public Awk
00088 {
00089 public:
00090 
00091   void begin ();
00092   void filter (const cmt_string& line);
00093   const cmt_string& result () const;
00094 
00095 private:
00096   cmt_string m_result;
00097   bool m_first;
00098 };
00099 
00106 class CvsImplementation;
00107 class RecursivePass2 : public Awk
00108 {
00109 public:
00110   RecursivePass2 (CvsImplementation& cvs);
00111   void begin ();
00112   void filter (const cmt_string& line);
00113 
00114 private:
00115   CvsImplementation& m_cvs;
00116 };
00117 
00124 class CvsImplementation
00125 {
00126 public:
00127 
00128   void filter_list (cmt_string& text, const cmt_regexp& exp)
00129       {
00130         CmtSystem::cmt_string_vector list;
00131 
00132         CmtSystem::split (text, " ", list);
00133 
00134         int i;
00135 
00136         text = "";
00137 
00138         for (i = 0; i < list.size (); i++)
00139           {
00140             const cmt_string& s = list[i];
00141             if (exp.match (s))
00142               {
00143                 if (i > 0) text += " ";
00144                 text += s;
00145               }
00146           }
00147       }
00148 
00149     //
00150     // This method exploits the hook installed into the loginfo script.
00151     // A communication is setup with a dummy CVS module named .cmtcvsinfos/<module>
00152     //
00153     //  At import time, the contents of the file will be used to parameterize
00154     // the script named cmt_buildcvsinfos2.sh (referenced in the loginfo script)
00155     //
00156     //  This script performs a scan in the CVS repository for currently 4 types of
00157     // information :
00158     //
00159     //   all top symbolic tags installed for the module
00160     //   all symbolic tags installed for the module
00161     //   all branches available below this module
00162     //   all subpackages installed below the module.
00163     //
00164     //    In principle, only modules corresponding to true CMT packages are considered.
00165     //      o tags are obtained from the requirements file
00166     //      o branches are sub-directories which are not themselves packages
00167     //      o subpackages are sub-directories which are CMT packages
00168     //        (a subdirectory is always either a branch or a subpackage)
00169     //
00170   void show_cvs_infos (const cmt_string& module)
00171       {
00172         cmt_string out;
00173 
00174         if (module == "")
00175           {
00176             cout << "# cmt cvs needs a module name" << endl;
00177             return;
00178           }
00179         
00180         cmt_string home_dir = CmtSystem::pwd ();
00181 
00182           //
00183           // Activities related with .cmtcvsinfos will occur in a temporary directory
00184           //
00185         cmt_string tmp_dir = CmtSystem::getenv ("TMPDIR");
00186         if (tmp_dir == "")
00187           {
00188             tmp_dir = CmtSystem::file_separator ();
00189             tmp_dir += "tmp";
00190           }
00191         
00192         if (!CmtSystem::cd (tmp_dir))
00193           {
00194             tmp_dir = home_dir;
00195           }
00196 
00197         tmp_dir += CmtSystem::file_separator ();
00198         tmp_dir += "cmtcvs";
00199         {
00200           cmt_string temp = CmtSystem::get_temporary_name ();
00201           CmtSystem::basename (temp, temp);
00202           tmp_dir += temp;
00203         }
00204         
00205         if (!CmtSystem::test_directory (tmp_dir))
00206           {
00207             if (!CmtSystem::mkdir (tmp_dir))
00208               {
00209                 cout << "# Cannot create the temporary directory [" 
00210                      << tmp_dir << "]" << endl;
00211                 return;
00212               }
00213           }
00214         
00215           //trap "rm -rf ${tmp_dir}" 0 1 2 15
00216         
00217         if (!CmtSystem::cd (tmp_dir))
00218           {
00219             cout << "# Cannot move to the temporary directory " << tmp_dir << endl;
00220             return;
00221           }
00222         
00223           /*
00224             #
00225             # The script associated to such entries is supposed to :
00226             #  1) extract the set of <infos> from the ${module}/cmt/requirements file
00227             #  2) build an output of the form :
00228             #      <infos>=info1 info2 info3 ...
00229             #
00230             # Currently this script can be found in
00231             #
00232             # ${CMTROOT}/cmt/cmt_buildcvsinfos2.sh
00233             # %CMTROOT%/cmt/cmt_buildcvsinfos.py
00234             #
00235           */
00236 
00237         if (!CmtSystem::test_directory (".cmtcvsinfos"))
00238           {
00239             CmtSystem::mkdir (".cmtcvsinfos");
00240           }
00241 
00242         CmtSystem::cd (".cmtcvsinfos");
00243 
00244         cmt_string cvsroot;
00245 
00246         CmtSystem::get_cvsroot (cvsroot);
00247 
00248         cmt_string command;
00249 
00250         command = "cvs";
00251         if (cvsroot != "") 
00252           {
00253             command += " -d ";
00254             command += cvsroot;
00255           }
00256         command += " -Q import -m cmt ";
00257         if (m_cmtcvstest)
00258           {
00259             command += ".cmtcvsinfos/cmtcvstest";
00260           }
00261         else
00262           {
00263             command += ".cmtcvsinfos";
00264           }
00265         command += "/";
00266         command += module;
00267         command += " CMT v1";
00268         
00269         CmtSystem::execute (command, out);
00270 
00271           //cout << "# after cvsinfos out=[" << out << "]" << endl;
00272 
00284         Grep grep;
00285 
00286         grep.run (out, "error=");
00287 
00288         if (grep.result () != "")
00289           {
00290             error_info = grep.result ();
00291             error_info.replace ("error=", "");
00292           }
00293         else
00294           {
00295             error_info = "";
00296           }
00297 
00298         grep.run (out, "tags_top=");
00299 
00300         if (grep.result () != "")
00301           {
00302             tags_top_info = grep.result ();
00303             tags_top_info.replace ("tags_top=", "");
00304           }
00305         else
00306           {
00307             tags_top_info = "";
00308           }
00309 
00310         grep.run (out, "tags=");
00311 
00312         if (grep.result () != "")
00313           {
00314             tags_info = grep.result ();
00315             tags_info.replace ("tags=", "");
00316           }
00317         else
00318           {
00319             tags_info = "";
00320           }
00321 
00322         grep.run (out, "cvsversions_top=");
00323 
00324         if (grep.result () != "")
00325           {
00326             cvsversions_top_info = grep.result ();
00327             cvsversions_top_info.replace ("cvsversions_top=", "");
00328           }
00329         else
00330           {
00331             cvsversions_top_info = "";
00332           }
00333 
00334         grep.run (out, "cvsversions=");
00335 
00336         if (grep.result () != "")
00337           {
00338             cvsversions_info = grep.result ();
00339             cvsversions_info.replace ("cvsversions=", "");
00340           }
00341         else
00342           {
00343             cvsversions_info = "";
00344           }
00345 
00346         cmt_string tag_filter = CmtSystem::getenv ("CMTCVSTAGFILTER");
00347 
00348         if (tag_filter != "")
00349           {
00350             cmt_string package;
00351             CmtSystem::basename (module, package);
00352             
00353             cmt_string pattern = "<package>";
00354             
00355             tag_filter.replace_all (pattern, package);
00356             
00357             cmt_regexp exp (tag_filter);
00358             
00359             cmt_string text;
00360             
00361             filter_list (tags_top_info, exp);
00362             filter_list (tags_info, exp);
00363             filter_list (cvsversions_top_info, exp);
00364             filter_list (cvsversions_info, exp);
00365           }
00366 
00367         if (m_cmtcvstest)
00368           {
00369             cout << "## tags_top_info=" << tags_top_info << endl;
00370             cout << "## tags_info=" << tags_info << endl;
00371             cout << "## cvsversions_top_info=" << cvsversions_top_info << endl;
00372             cout << "## cvsversions_info=" << cvsversions_info << endl;
00373           }
00374 
00375         grep.run (out, "branches=");
00376 
00377         if (grep.result () != "")
00378           {
00379             branches_info = grep.result ();
00380             branches_info.replace ("branches=", "");
00381           }
00382         else
00383           {
00384             branches_info = "";
00385           }
00386 
00387         grep.run (out, "subpackages=");
00388 
00389         if (grep.result () != "")
00390           {
00391             subpackages_info = grep.result ();
00392             subpackages_info.replace ("subpackages=", "");
00393           }
00394         else
00395           {
00396             subpackages_info = "";
00397           }
00398 
00399         CmtSystem::cd (home_dir);
00400           //cout << "# (removing tmp_dir= " << tmp_dir << " home=" << home_dir<< ")" << endl;
00401         CmtSystem::remove_directory (tmp_dir);
00402       }
00403 
00404   void show_cvs_infos (const cmt_string& offset,
00405                        const cmt_string& module)
00406   {
00407     cmt_string full_name;
00408 
00409     if (offset != "") 
00410       {
00411         full_name = offset;
00412         full_name += "/";
00413         full_name.replace_all ("//", "/");
00414       }
00415 
00416     full_name += module;
00417 
00418     show_cvs_infos (full_name);
00419   }
00420 
00421     //
00422     // Resolve all possible "aaa/bbb/../ccc/ddd" patterns into "aaa/ccc/ddd"
00423     //
00424   void filter_dir (cmt_string& d)
00425       {
00426         while (true)
00427           {
00428             int pos = d.find ("/../");
00429             if (pos == cmt_string::npos) break;
00430             
00431             int slash = d.find ("/");
00432             if (slash < pos)
00433               {
00434                   //
00435                   // xxxxx/yyy/../zzzz -> xxxxx/zzzz
00436                   // 01234567890123456
00437                   //       1234567
00438                   //  pos   = 9
00439                   //  slash = 5
00440                   //  length = 9+3-5
00441                   //
00442                 d.erase (slash + 1, pos + 3 - slash);
00443               }
00444             else
00445               {
00446                   //
00447                   // yyy/../zzzz -> zzzz
00448                   // 01234567890
00449                   // 1234567
00450                   //  pos   = 3
00451                   //  length = 3+1+3
00452                   //
00453                 d.erase (0, pos + 1 + 3);
00454               }
00455           }
00456       }
00457 
00466   bool match_version_request (const cmt_string& text, 
00467                               const cmt_regexp& version_exp,
00468                               cmt_string& version)
00469       {
00470         CmtSystem::cmt_string_vector vs;
00471       
00472         CmtSystem::split (text, " \t", vs);
00473 
00474         version = "";
00475 
00476         for (int i = 0; i < vs.size (); i++)
00477           {
00478             const cmt_string& vv = vs[i];
00479         
00480             if (version_exp.match (vv))
00481               {
00482                 version = vv;
00483                 return (true);
00484               }
00485           }
00486 
00487         return (false);
00488       }
00489 
00490   bool get_version (const cmt_string& prefix,
00491                     const cmt_string& package,
00492                     const cmt_string& version_request,
00493                     cmt_string& module,
00494                     cmt_string& version,
00495                     bool& at_head)
00496       {
00497         Grep grep;
00498         cmt_string topversions;
00499         cmt_string versions;
00500         cmt_string requested_version = version_request;
00501     
00502         at_head = false;
00503             
00504         module = "";
00505 
00506         if (prefix != "")
00507           {
00508             module = prefix;
00509             module += "/"; // This is for CVS only
00510             module.replace_all ("//", "/");
00511           }
00512 
00513         module += package;
00514 
00529           //cout << " in get version : module=[" << module << "]" << endl;
00530 
00531         show_cvs_infos (module);
00532 
00533         if (error_info != "")
00534           {
00535             versions = "";
00536             cout << "# Package " << package << " not found in ${CVSROOT}" << endl;
00537             return (false);
00538           }
00539 
00540         versions = tags_top_info;
00541 
00542         cmt_string v = version_request;
00543 
00544         if (version_request.find ("*") != cmt_string::npos)
00545           {
00546             v.replace_all ("*", ".*");
00547           }
00548         else
00549           {
00550             v += "$";
00551           }
00552 
00553         if (m_cmtcvstest) cout << "##    (version expression is " << v << ")" << endl;
00554 
00555         cmt_regexp version_exp (v);
00556     
00557         if (!match_version_request (versions, version_exp, version))
00558           {
00559             if (m_cmtcvstest) cout << "##    (no match in " << versions << ")" << endl;
00560 
00561               // We try on non-top versions
00562 
00563             versions = tags_info;
00564 
00565             if (!match_version_request (versions, version_exp, version))
00566               {
00567                 if (m_cmtcvstest) cout << "##    (no match in " << versions << ")" << endl;
00568 
00569                 version = requested_version;
00570                 int pos = 0;
00571                 if ((pos = version.find ("*")) != cmt_string::npos)
00572                   {
00573                       //
00574                       //  There was a wild card but the expression does not match
00575                       // any of the existing tags in CVS.
00576                       //  Things will be retreived from HEAD but we have to build
00577                       // a reasonable version tag from the wild card expression.
00578                       //  If the letter before the * was a digit, then simply remove
00579                       // the * (v5* -> v5) otherwise add a zero (v5r* -> v5r0)
00580                       //
00581                     if (pos > 0)
00582                       {
00583                         char letter = version[pos-1];
00584 
00585                         static const cmt_string digits = "0123456789";
00586 
00587                         if (digits.find (letter) == cmt_string::npos)
00588                           {
00589                               // "v5r*" -> "v5r0"
00590                             version.replace ("*", "0");
00591                           }
00592                         else
00593                           {
00594                               // "v5*" -> "v5"
00595                             version.replace ("*", "");
00596                           }
00597                       }
00598                     else
00599                       {
00600                           // The expression was simply "*" !!!
00601                         version = "v0";
00602                       }
00603                   }
00604                 at_head = true;
00605               }
00606             else
00607               {
00608                 if (m_cmtcvstest) cout << "##    (match in non head " << versions << ")" << endl;
00609 
00610                 at_head = false;
00611               }
00612           }
00613         else
00614           {
00615             if (m_cmtcvstest) cout << "##    (match in head " << versions << ")" << endl;
00616 
00617             at_head = true;
00618           }
00619     
00624         return (true);
00625       }
00626 
00627   cmt_string build_version_directory (const cmt_string& prefix,
00628                                       const cmt_string& package,
00629                                       const cmt_string& version)
00630       {
00631         cmt_string dir = m_home_dir;
00632 
00633         if (m_checkout_dir != "")
00634           {
00635             dir += CmtSystem::file_separator ();
00636             dir += m_checkout_dir;
00637           }
00638 
00639         dir += CmtSystem::file_separator ();
00640         dir += prefix;
00641         dir += CmtSystem::file_separator ();
00642         dir += package;
00643         dir += CmtSystem::file_separator ();
00644         dir += version;
00645 
00646         {
00647           cmt_string fs = CmtSystem::file_separator ();
00648           cmt_string dfs = fs;
00649           dfs += fs;
00650 
00651           dir.replace_all (dfs, fs);
00652         }
00653 
00654         return (dir);
00655       }
00656 
00657   bool really_checkout_package (const cmt_string& prefix,
00658                                 const cmt_string& package,
00659                                 const cmt_string& version,
00660                                 const cmt_string& module,
00661                                 const cmt_string& basedir,
00662                                 bool at_head)
00663       {
00664         cmt_string dir = basedir;
00665         cmt_string out;
00666 
00667         cout << "# ================= working on package " << package 
00668              << " version " << version;
00669 
00670         if (at_head) cout << " (At head) ";
00671 
00672         {
00673           cmt_string full_prefix;
00674 
00675           full_prefix = m_offset;
00676           full_prefix += prefix;
00677 
00678           cmt_string echo_ppath;
00679         
00680           if (full_prefix != "")
00681             {
00682               echo_ppath = " path ";
00683               echo_ppath += prefix;
00684             }
00685 
00686           cout << echo_ppath << endl;
00687         }
00688 
00689         CmtSystem::dirname (dir, dir);
00690 
00691         if (!CmtSystem::mkdir (dir))
00692           {
00693             return (false);
00694           }
00695 
00696         CmtSystem::cd (dir);
00697 
00698         cout << "  # get top files " << endl;
00699             
00700         cmt_string command = "cvs -Q co -P -l ";
00701         if (!at_head)
00702           {
00703             command += "-r ";
00704             command += version;
00705           }
00706         command += " -d ";
00707         command += version;
00708         command += " ";
00709         command += module;
00710                 
00711         if (m_cmtcvstest)
00712           {
00713             cmt_string cvsroot;
00714             
00715             CmtSystem::get_cvsroot (cvsroot);
00716             
00717             cout << "## cvsroot=" << cvsroot << " command[" << command << "]" << endl;
00718           }
00719         
00720         int status = CmtSystem::execute (command, out);
00721         
00722           //cout << "-> status = " << status << " out=[" << out << "]" << endl;
00723         
00724         if (!CmtSystem::cd (version))
00725           {
00726             CmtSystem::mkdir (version);
00727             if (!CmtSystem::cd (version))
00728               {
00729                 cout << "# Error creating the version directory :" << version << endl;
00730                 cout << "#---------------------------------------------------------" << endl;
00731                 return (false);
00732               }
00733           }
00734                 
00735         dir += CmtSystem::file_separator ();
00736         dir += version;
00737         
00738         cmt_string file_name;
00739         cmt_string text;
00740         
00741         cmt_string branches = CmtSystem::getenv ("CMTCVSBRANCHES");
00742         
00743         if (branches == "")
00744           {
00745             branches = branches_info;
00746           }
00747         
00748         CmtSystem::cmt_string_vector branch_vector;
00749         
00750         CmtSystem::split (branches, " \t", branch_vector);
00751         
00752         int i;
00753         
00754         cout << "  # get branches " << branches << endl;
00755         
00756         command = "";
00757         
00758         file_name = "CVS";
00759         file_name += CmtSystem::file_separator ();
00760         file_name += "Entries";
00761         
00762         if (!text.read (file_name))
00763           {
00764               // This happens when there were no top files
00765           }
00766         
00767         for (i = 0; i < branch_vector.size (); i++)
00768           {
00769             cmt_string& branch = branch_vector[i];
00770             
00771               //command += "cvs -Q co -P ";
00772             command += "cvs -Q co ";
00773             
00774 //            if (branch != "cmt")
00775 //              {
00776                 if (!at_head)
00777                   {
00778                     command += "-r ";
00779                     command += version;
00780                   }
00781 //              }
00782             
00783             command += " -d ";
00784             command += branch;
00785             command += " ";
00786             command += module;
00787             command += "/";    // CVS uses the '/' notation on all platforms!!
00788             command += branch;
00789             //command += "\n";
00790             command += CmtSystem::command_separator ();
00791             
00792             text += "D/";
00793             text += branch;
00794             text += "
00795           }
00796         
00797         if (m_cmtcvstest)
00798           {
00799             cmt_string cvsroot;
00800             
00801             CmtSystem::get_cvsroot (cvsroot);
00802             
00803             cout << " cvsroot=" << cvsroot << " command[" << command << "]" << endl;
00804           }
00805         
00806         if (CmtSystem::execute (command, out) == 0)
00807           {
00808             cout << "# Error getting package contents:" << endl;
00809             cout << out << endl;
00810             cout << "#---------------------------------------------------------" << endl;
00811           }
00812         else
00813           {
00814             if (!CmtSystem::test_directory ("CVS"))
00815               {
00821                   //cout << "file_name=" << file_name << endl;
00822                 
00823                 CmtSystem::mkdir ("CVS");
00824                 cmt_string s;
00825                 
00826                   // Let's create first the CVS/Root file.
00827                 
00828                 CmtSystem::get_cvsroot (s);
00829                 s += "\n";
00830                 
00831                 cmt_string f;
00832                 
00833                 f = "CVS";
00834                 f += CmtSystem::file_separator ();
00835                 f += "Root";
00836                 
00837                   //cout << "f=" << f << " s=[" << s << "]" << endl;
00838                 s.write (f);
00839                 
00840                   // Now we create the CVS/Repository file
00841                 
00842                 f = "CVS";
00843                 f += CmtSystem::file_separator ();
00844                 f += "Repository";
00845                 
00846                 CmtSystem::get_cvsroot (s);
00847                 if (s[0] == ':')
00848                   {
00849                     int pos = s.find (1, ":");
00850                     s.erase (0, pos+1);
00851                     pos = s.find (0, ":");
00852                     s.erase (0, pos+1);
00853                   }
00854                 s += "/";
00855                 s += module;
00856                 s += "\n";
00857                 
00858                   //cout << "f=" << f << " s=[" << s << "]" << endl;
00859                 s.write (f);
00860               }
00861             
00862               // Now the CVS/Entries is ready to be created.
00863             text.write (file_name);
00864           }
00865 
00866         return (true);
00867       }
00868 
00869   cmt_string find_matching_version (const cmt_string& expression)
00870       {
00871         cmt_string result;
00872 
00873           //
00874           // Here expression takes the form
00875           //   <some path>/<expression with wild-card>
00876           //
00877 
00878         cmt_string dir;
00879         CmtSystem::dirname (expression, dir);
00880         dir += CmtSystem::file_separator ();
00881 
00882         cmt_string version;
00883         CmtSystem::basename (expression, version);
00884 
00885         if (version.find ("*") == cmt_string::npos)
00886           {
00887               // there is no wildcarding here. A simple test is enough.
00888             if (CmtSystem::test_directory (expression))
00889               {
00890                 if (m_cmtcvstest) cout << "## Found direct match with " << version << endl;
00891                 result = version;
00892               }
00893             else
00894               {
00895                 if (m_cmtcvstest) cout << "## Explicit version " << version 
00896                                        << " has no direct match" << endl;
00897               }
00898           }
00899         else
00900           {
00901             version.replace ("*", ".*");
00902 
00903             cmt_regexp exp (version);
00904 
00905             CmtSystem::cmt_string_vector list;
00906 
00907             if (m_cmtcvstest) cout << "## Trying scan_dir dir=" << dir
00908                                    << " exp=" << version << endl;
00909 
00910             CmtSystem::scan_dir (dir, exp, list);
00911 
00912             if (list.size () > 0)
00913               {
00914                 result = list[0];
00915 
00916                 if (m_cmtcvstest) cout << "## At least one version is matching " << version 
00917                                        << "(" << list.size () << " matches) " << result << endl;
00918 
00919                 CmtSystem::basename (result, result);
00920               }
00921             else
00922               {
00923                 if (m_cmtcvstest) cout << "## There is no version matching " << version << endl;
00924               }
00925           }
00926 
00927         return (result);
00928       }
00929   
00930   void checkout_package (const cmt_string& prefix,
00931                          const cmt_string& package,
00932                          const cmt_string& specified_version)
00933       {
00934         cmt_string version = specified_version;
00935         cmt_string empty;
00936         cmt_string full_prefix;
00937 
00938         full_prefix = m_offset;
00939         full_prefix += prefix;
00940 
00941         cmt_string echo_ppath;
00942         
00943         if (full_prefix != "")
00944           {
00945             echo_ppath = " path ";
00946             echo_ppath += prefix;
00947           }
00948         
00949         if (version == "")
00950           {
00951             cout << "# ================= No version specified for package " << package << endl;
00952             return;
00953           }
00954 
00955           //
00956           //  First make an attempt to locate the specified version of
00957           //  this package "as-it-is" in the work area.
00958           //   Since 'version' may contain wild-card, it's likely that
00959           //  we should not simply use CmtSystem::test_directory but
00960           //  use the wild-card search.
00961           //
00962 
00963         cmt_string dir;
00964         
00965         dir = build_version_directory (prefix, package, version);
00966               
00967         if (m_cmtcvstest) cout << "## (testing dir= " << dir << ")" << endl;
00968 
00969         bool recursive = m_recursive;
00970 
00971           /*
00972         if (m_cmtcvstest)
00973           {
00974             cmt_string v = find_matching_version (dir);
00975 
00976             cout << "---> v=" << v << endl;
00977           }
00978           */
00979 
00980           //if (CmtSystem::test_directory (dir))
00981 
00982         cmt_string effective_version = find_matching_version (dir);
00983 
00984         if (effective_version != "")
00985           {
00986             version = effective_version;
00987 
00988             dir = build_version_directory (prefix, package, version);
00989 
00990             cout << "# ================= Package " << package 
00991                  << " version " << version << echo_ppath 
00992                  << " already installed." << endl;
00993 
00994             recursive = false;
00995           }
00996         else
00997           {
00998             bool at_head = false;
00999             cmt_string module;
01000 
01001               //
01002               // get_version attempts to find the most appropriate version
01003               // tag matching the specification FROM the repository. However,
01004               // we should take into account situations where some versions have
01005               // already been checked out, in which case they might be sufficient
01006               // (or preferred?)
01007               //
01008 
01009             if (version.find ("*") != cmt_string::npos)
01010               {
01011                 cout << "# ================= Package " << package 
01012                      << " version " << version << echo_ppath 
01013                      << " has wild cards and will not be considered." << endl;
01014                 return;
01015               }
01016 
01017             if (!get_version (full_prefix, package, version, 
01018                               module, version, at_head))
01019               {
01020                 return;
01021               }
01022 
01023               //cout << " full_prefix=[" << full_prefix << "] module=[" << module << "]" << endl;
01024 
01025             if (m_cmtcvstest) cout << "## after get_version at_head=" << at_head << " m_head=" << m_head << endl;
01026 
01027             if (m_head)
01028               {
01029                 m_head = false;
01030 
01031                 at_head = true;
01032               }
01033             else
01034               {
01035                 at_head = false;
01036               }
01037 
01038               //
01039               // Make a second try after having selected a version from all the
01040               // available versions compatible with the specified version
01041               //
01042 
01043             dir = build_version_directory (prefix, package, version);
01044 
01045             if (CmtSystem::test_directory (dir))
01046               {
01047                 cout << "# ================= Package " << package 
01048                      << " version " << version << echo_ppath 
01049                      << " already installed." << endl;
01050 
01051                 recursive = false;
01052               }
01053             else
01054               {
01055                   //
01056                   // Now we can say that we have to perform the real checkout.
01057                   // 
01058 
01059                 if (!really_checkout_package (prefix, package, version, module, dir, at_head))
01060                   {
01061                     cout << "# bad return from really_checkout_package" << endl;
01062                     return;
01063                   }
01064               }
01065           }
01066 
01067           //
01068           //  Now reach the newly checked out package.
01069           //
01070 
01071         CmtSystem::cd (dir);
01072 
01073           // Check if it is a true CMT package.
01074 
01075         cmt_string file_name;
01076 
01077         file_name = "cmt";
01078         file_name += CmtSystem::file_separator ();
01079         file_name += "requirements";
01080 
01081         if (CmtSystem::test_file (file_name))
01082           {
01083             dir += CmtSystem::file_separator ();
01084             dir += "cmt";
01085             CmtSystem::cd ("cmt");
01086           }
01087         else
01088           {
01089             file_name = "mgr";
01090             file_name += CmtSystem::file_separator ();
01091             file_name += "requirements";
01092             
01093             if (CmtSystem::test_file (file_name))
01094               {
01095                 dir += CmtSystem::file_separator ();
01096                 dir += "mgr";
01097                 CmtSystem::cd ("mgr");
01098               }
01099             else
01100               {
01101                 cout << "# " << package << " not a CMT package" << endl;
01102                 return;
01103               }
01104           }
01105 
01106           //cout << "#   (recursive is " << recursive << ")" << endl;
01107 
01108         if (recursive)
01109           {
01110             checkout_from_requirements ("requirements");
01111           }
01112       }
01113 
01118   void checkout_from_requirements (const cmt_string& requirements_path)
01119   {
01120     static cmt_regexp expression ("^[ \t]*use[ \t]");
01121 
01122     cmt_string text;
01123 
01124     text.read (requirements_path);
01125 
01126     RecursivePass1 p1;
01127     p1.run (text, expression);
01128 
01129     RecursivePass2 p2 (*this);
01130     p2.run (p1.result ());
01131   }
01132 
01133   void tags (const CmtSystem::cmt_string_vector& arguments)
01134       {
01135         if (arguments.size () < 1)
01136           {
01137             help ();
01138             return;
01139           }
01140         
01141         if (CmtSystem::getenv ("CVSROOT") == "")
01142           {
01143             cout << "# Please set CVSROOT first !" << endl;
01144             return;
01145           }
01146               
01147         if (CmtSystem::getenv ("CMTCVSTEST") != "")
01148           {
01149             m_cmtcvstest = true;
01150           }
01151         else
01152           {
01153             m_cmtcvstest = false;
01154           }
01155 
01156         m_offset = CmtSystem::getenv ("CMTCVSOFFSET");
01157         if (m_offset != "") 
01158           {
01159             m_offset += "/";
01160             m_offset.replace_all ("//", "/");
01161           }
01162 
01163         bool all = false;
01164         
01165         for (int arg = 0; arg < arguments.size (); arg++)
01166           {
01167             const cmt_string& option = arguments[arg];
01168 
01169             if (option == "-all")
01170               {
01171                 all = true;
01172               }
01173             else
01174               {
01175                 show_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), option);
01176 
01177                 if (error_info != "")
01178                   {
01179                     cout << error_info << endl;
01180                   }
01181                 else
01182                   {
01183                     cmt_string tags;
01184 
01185                     if (all)
01186                       {
01187                         tags = cvsversions_top_info;
01188                         tags += " ";
01189                         tags += cvsversions_info;
01190                       }
01191                     else
01192                       {
01193                         tags = tags_top_info;
01194                         tags += " ";
01195                         tags += tags_info;
01196                       }
01197 
01198                     CmtSystem::cmt_string_vector v;
01199 
01200                     CmtSystem::split (tags, " \t", v);
01201                     for (int i = 0; i < v.size (); i++)
01202                       {
01203                         const cmt_string& s = v[i];
01204                         cout << s << endl;
01205                       }
01206                   }
01207               }
01208           }
01209       }
01210 
01211   void branches (const cmt_string& module)
01212       {
01213         cmt_string out;
01214 
01215         show_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), module);
01216 
01217         if (error_info != "")
01218           {
01219             cout << error_info << endl;
01220           }
01221         else
01222           {
01223             cout << branches_info << endl;
01224           }
01225       }
01226 
01227   void subpackages (const cmt_string& module)
01228       {
01229         cmt_string out;
01230 
01231         show_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), module);
01232 
01233         if (error_info != "")
01234           {
01235             cout << error_info << endl;
01236           }
01237         else
01238           {
01239             cout << subpackages_info << endl;
01240           }
01241       }
01242 
01243   void help ()
01244       {
01245         cout << "> cd <some work area>" << endl;
01246         cout << "> cmt checkout [modifier ...] <package>" << endl;
01247         cout << "" << endl;
01248         cout << "   modifier :" << endl;
01249         cout << "   -l        Do not process used packages (default)." << endl;
01250         cout << "   -R        Process used packages recursively." << endl;
01251         cout << "   -r rev    Check out version tag. (is sticky)" << endl;
01252         cout << "   -d dir    Check out into dir instead of module name." << endl;
01253         cout << "   -o offset Offset in the CVS repository" << endl;
01254         cout << "   -requirements <requirements file path>  Check out packages referenced in this requirements file" << endl;
01255           //cout << "   -n        simulation mode on" << endl;
01256           //cout << "   -v        verbose mode on" << endl;
01257         cout << "   --help    print this help" << endl;
01258         cout << "" << endl;
01259       }
01260 
01261   void do_checkout (const cmt_string& module, const cmt_string& version_tag)
01262   {
01263     //CMTPATH=${CMTPATH}:${m_home_dir}; export CMTPATH
01264 
01265     History& h = History::instance ();
01266 
01267     h.clear ();
01268 
01269     if (module == "") return;
01270 
01271     cmt_string prefix;
01272     cmt_string package;
01273     cmt_string version;
01274     
01275     if (version_tag == "")
01276       {
01277         Cut cut (0);
01278         
01279         cmt_string m;
01280         m = m_offset;
01281         m += module;
01282         
01283         show_cvs_infos (m);
01284         
01285         if (error_info != "")
01286           {
01287             cout << error_info << endl;
01288             return;
01289           }
01290 
01291         if (tags_top_info != "") version = tags_top_info;
01292         else version = tags_info;
01293         
01294           //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "version=" << version << endl;
01295 
01296         cut.run (version);
01297         
01298         version = cut.result ();
01299 
01300           //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "version=" << version << endl;
01301       }
01302     else
01303       {
01304         version = version_tag;
01305       }
01306     
01307     CmtSystem::dirname (module, prefix);
01308     CmtSystem::basename (module, package);
01309     
01310     cmt_string top_dir;
01311         
01312     top_dir = m_home_dir;
01313     top_dir += CmtSystem::file_separator ();
01314     top_dir += m_checkout_dir;
01315     top_dir += CmtSystem::file_separator ();
01316     top_dir += prefix;
01317     top_dir += CmtSystem::file_separator ();
01318     top_dir += package;
01319     top_dir += CmtSystem::file_separator ();
01320     top_dir += version;
01321     
01322     checkout_package (prefix, package, version);
01323     
01324     //cout << "after checkout_package pwd=[" << CmtSystem::pwd () << "] top_dir=[" << top_dir << "]" << endl;
01325     
01326     if (!CmtSystem::cd (top_dir)) return;
01327     
01328     cmt_string file_name;
01329     
01330     file_name = "cmt";
01331     file_name += CmtSystem::file_separator ();
01332     file_name += "requirements";
01333     
01334     if (CmtSystem::test_file (file_name))
01335       {
01336         top_dir += CmtSystem::file_separator ();
01337         top_dir += "cmt";
01338         CmtSystem::cd ("cmt");
01339       }
01340     else
01341       {
01342         file_name = "mgr";
01343         file_name += CmtSystem::file_separator ();
01344         file_name += "requirements";
01345         
01346         if (CmtSystem::test_file (file_name))
01347           {
01348             top_dir += CmtSystem::file_separator ();
01349             top_dir += "mgr";
01350             CmtSystem::cd ("mgr");
01351           }
01352         else
01353           {
01354             cout << "# " << package << "not a CMT package" << endl;
01355             return;
01356           }
01357       }
01358     
01359     //cout << "end of checkout pwd=[" << CmtSystem::pwd () << "]" << endl;
01360     
01361     if (m_recursive)
01362       {
01363         CmtSystem::execute ("cmt broadcast cmt config");
01364       }
01365     else
01366       {
01367         CmtSystem::execute ("cmt config");
01368       }
01369   }
01370 
01371   void checkout (const CmtSystem::cmt_string_vector& arguments)
01372       {
01373         if (arguments.size () < 1)
01374           {
01375             help ();
01376             return;
01377           }
01378         
01379         if (CmtSystem::getenv ("CVSROOT") == "")
01380           {
01381             cout << "# Please set CVSROOT first !" << endl;
01382             return;
01383           }
01384               
01385         if (CmtSystem::getenv ("CMTCVSTEST") != "")
01386           {
01387             m_cmtcvstest = true;
01388           }
01389         else
01390           {
01391             m_cmtcvstest = false;
01392           }
01393 
01394         m_home_dir = CmtSystem::pwd ();
01395         m_checkout_dir = "";
01396         m_offset = "";
01397         m_branch_suffix = "";
01398 
01399         cmt_string module;
01400               
01401         m_recursive = false;
01402 
01403         bool need_version_tag = false;
01404         cmt_string version_tag;
01405 
01406         bool need_checkout_dir = false;
01407         bool need_offset = false;
01408         bool need_requirements_file = false;
01409 
01410         bool simulation = false;
01411         bool verbose = false;
01412 
01413         bool need_branch_suffix = false;
01414 
01415         m_head = true;
01416 
01417         m_offset = CmtSystem::getenv ("CMTCVSOFFSET");
01418         if (m_offset != "") 
01419           {
01420             m_offset += "/";
01421             m_offset.replace_all ("//", "/");
01422           }
01423 
01424         for (int arg = 0; arg < arguments.size (); arg++)
01425           {
01426             const cmt_string& option = arguments[arg];
01427 
01428             if (need_version_tag)
01429               {
01430                 need_version_tag = false;
01431 
01432                 if (option == "HEAD")
01433                   {
01434                     m_head = true;
01435                   }
01436                 else
01437                   {
01438                     version_tag = option;
01439                   }
01440               }
01441             else if (need_checkout_dir)
01442               {
01443                 need_checkout_dir = false;
01444                 m_checkout_dir = option;
01445               }
01446             else if (need_offset)
01447               {
01448                 need_offset = false;
01449                 m_offset = option;
01450                 m_offset += '/';
01451                 m_offset.replace_all ("//", "/");
01452               }
01453             else if (need_branch_suffix)
01454               {
01455                 need_branch_suffix = false;
01456                 m_branch_suffix = "-";
01457                 m_branch_suffix += option;
01458               }
01459             else if (need_requirements_file)
01460               {
01461                 need_requirements_file = false;
01462                 m_head = false;
01463                 checkout_from_requirements (option);
01464               }
01465             else
01466               {
01467                 if (option == "-R")
01468                   {
01469                     m_recursive = true;
01470                   }
01471                 else if (option == "-l")
01472                   {
01473                     m_recursive = false;
01474                   }
01475                 else if (option == "-r")
01476                   {
01477                     need_version_tag = true;
01478                     m_head = false;
01479                   }
01480                 else if (option == "-d")
01481                   {
01482                     need_checkout_dir = true;
01483                   }
01484                 else if (option == "-o")
01485                   {
01486                     need_offset = true;
01487                   }
01488                 else if (option == "-n")
01489                   {
01490                     simulation = true;
01491                     verbose = true;
01492                   }
01493                 else if (option == "-v")
01494                   {
01495                     verbose = true;
01496                   }
01497                 else if (option == "-branch")
01498                   {
01499                     need_branch_suffix = true;
01500                   }
01501                 else if (option == "-requirements")
01502                   {
01503                     need_requirements_file = true;
01504                   }
01505                 else if (option == "--help")
01506                   {
01507                     help ();
01508                     return;
01509                   }
01510                 else if (option[0] == '-')
01511                   {
01512                     help ();
01513                     return;
01514                   }
01515                 else
01516                   {
01517                     do_checkout (option, version_tag);
01518                   }
01519               }
01520           }
01521 
01522       }
01523 
01524 private:
01525 
01526   bool m_recursive;
01527   bool m_head;
01528   bool m_cmtcvstest;
01529 
01530   cmt_string m_home_dir;
01531   cmt_string m_checkout_dir;
01532   cmt_string m_offset;
01533   cmt_string m_branch_suffix;
01534 
01535   cmt_string error_info;
01536   cmt_string tags_top_info;
01537   cmt_string tags_info;
01538   cmt_string cvsversions_top_info;
01539   cmt_string cvsversions_info;
01540   cmt_string branches_info;
01541   cmt_string subpackages_info;
01542 };
01543 
01544 //--------------------------------------------------------------------
01545 
01546 void Grep::begin ()
01547 {
01548   m_result = "";
01549 }
01550 
01551 void Grep::filter (const cmt_string& line)
01552 {
01553     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "Grep::filter" << endl;
01554 
01555   if (m_result != "") m_result += " ";
01556   m_result += line;
01557 }
01558 
01559 const cmt_string& Grep::result () const
01560 {
01561   return (m_result);
01562 }
01563 
01564 //--------------------------------------------------------------------
01565 
01566 Cut::Cut (int field)
01567 {
01568   m_field = field;
01569 }
01570 
01571 void Cut::begin ()
01572 {
01573     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "Cut::begin" << endl;
01574   m_result = "";
01575 }
01576 
01577 void Cut::filter (const cmt_string& line)
01578 {
01579     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "Cut::filter" << endl;
01580 
01581   static CmtSystem::cmt_string_vector words;
01582   
01583   CmtSystem::split (line, " \t", words);
01584   
01585   if (words.size () <= m_field) return;
01586   
01587   if (m_result != "") m_result += " ";
01588   m_result += words[m_field];
01589 }
01590 
01591 const cmt_string& Cut::result () const
01592 {
01593   return (m_result);
01594 }
01595 
01596 //--------------------------------------------------------------------
01597 //--------------------------------------------------------------------
01598 
01599 History& History::instance ()
01600 {
01601   static History h;
01602   return (h);
01603 }
01604 
01605 void History::clear ()
01606 {
01607   m_installed = "";
01608 }
01609 
01610 void History::install (const cmt_string& line)
01611 {
01612   m_installed += "|";
01613   m_installed += line;
01614   m_installed += "|";
01615 }
01616 
01617 bool History::is_installed (const cmt_string& line)
01618 {
01619   if (m_installed.find (line) != cmt_string::npos)
01620     {
01621       return (true);
01622     }
01623   
01624   return (false);
01625 }
01626 
01627 History::History ()
01628 {
01629 }
01630 
01631 
01632 //--------------------------------------------------------------------
01633 
01634 void RecursivePass1::begin ()
01635 {
01636   m_first = true;
01637   m_result = "";
01638 }
01639 
01640 void RecursivePass1::filter (const cmt_string& line)
01641 {
01642     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "RecursivePass1::filter" << endl;
01643 
01644   if (line.find ("use CMT") != cmt_string::npos) return;
01645   if (line.find ("use cmt") != cmt_string::npos) return;
01646   
01647   History& h = History::instance ();
01648   
01649   if (h.is_installed (line)) return;
01650   
01651   CmtSystem::cmt_string_vector words;
01652   
01653   CmtSystem::split (line, " \t", words);
01654 
01655   enum
01656   {
01657     need_package,
01658     need_version,
01659     need_path,
01660     no_need
01661   } state = need_package;
01662 
01663   cmt_string package;
01664   cmt_string version;
01665   cmt_string path;
01666 
01667   for (int i = 1; i < words.size (); i++)
01668     {
01669       const cmt_string& s = words[i];
01670 
01671       if (s[0] == '-') continue;
01672 
01673       switch (state)
01674         {
01675           case need_package:
01676             package = s;
01677             state = need_version;
01678             break;
01679           case need_version:
01680             version = s;
01681             state = need_path;
01682             break;
01683           case need_path:
01684             path = s;
01685             state = no_need;
01686             break;
01687         }
01688     }
01689   
01690   if (version.find ("*") != cmt_string::npos)
01691     {
01692         /*
01693       cout << "# ================= Package " << package 
01694            << " version " << version << " " << path 
01695            << " has wild cards and will not be considered." << endl;
01696         */
01697       return;
01698     }
01699 
01705   m_result += line;
01706   m_result += "\n";
01707   
01708   if (m_first)
01709     {
01710       m_first = false;
01711       cout << "  # --> now propagate cmt checkout to :" << endl;
01712     }
01713   
01714   cout << "  #     " << package << " " << version << " " << path << endl;
01715 }
01716 
01717 const cmt_string& RecursivePass1::result () const
01718 {
01719   return (m_result);
01720 }
01721 
01722 //--------------------------------------------------------------------
01723 
01724 RecursivePass2::RecursivePass2 (CvsImplementation& cvs) : m_cvs (cvs)
01725 {
01726 }
01727 
01728 void RecursivePass2::begin ()
01729 {
01730 }
01731 
01732 void RecursivePass2::filter (const cmt_string& line)
01733 {
01734     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "RecursivePass2::filter" << endl;
01735 
01742   History& h = History::instance ();
01743   
01744   if (h.is_installed (line)) return;
01745   
01746   h.install (line);
01747   
01748   CmtSystem::cmt_string_vector words;
01749   
01750   CmtSystem::split (line, " \t", words);
01751 
01752   enum
01753   {
01754     need_package,
01755     need_version,
01756     need_path,
01757     no_need
01758   } state = need_package;
01759 
01760   cmt_string package;
01761   cmt_string version;
01762   cmt_string path;
01763 
01764   for (int i = 1; i < words.size (); i++)
01765     {
01766       const cmt_string& s = words[i];
01767 
01768       if (s[0] == '-') continue;
01769 
01770       switch (state)
01771         {
01772           case need_package:
01773             package = s;
01774             state = need_version;
01775             break;
01776           case need_version:
01777             version = s;
01778             state = need_path;
01779             break;
01780           case need_path:
01781             path = s;
01782             state = no_need;
01783             break;
01784         }
01785     }
01786 
01787   if (version.find ("*") != cmt_string::npos)
01788     {
01789         /*
01790       cout << "# ================= Package " << package 
01791            << " version " << version << " " << path 
01792            << " has wild cards and will not be considered." << endl;
01793         */
01794     }
01795   else
01796     {
01797       m_cvs.checkout_package (path, package, version);
01798     }
01799 }
01800 
01801 //--------------------------------------------------------------------
01802 
01803 void Cvs::tags (const CmtSystem::cmt_string_vector& arguments)
01804 {
01805   CvsImplementation cvs;
01806 
01807   cvs.tags (arguments);
01808 }
01809 
01810 void Cvs::branches (const cmt_string& module)
01811 {
01812   CvsImplementation cvs;
01813 
01814   cvs.branches (module);
01815 }
01816 
01817 void Cvs::subpackages (const cmt_string& module)
01818 {
01819   CvsImplementation cvs;
01820 
01821   cvs.subpackages (module);
01822 }
01823 
01824 void Cvs::checkout (const CmtSystem::cmt_string_vector& arguments)
01825 {
01826   CvsImplementation cvs;
01827 
01828   cvs.checkout (arguments);
01829 }
01830 

Generated at Thu Apr 11 16:49:40 2002 for CMT by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000