source: CMT/v1r19/source/cmt_cvs.cxx @ 1

Last change on this file since 1 was 1, checked in by arnault, 19 years ago

Import all tags

File size: 55.3 KB
Line 
1//-----------------------------------------------------------
2// Copyright Christian Arnault LAL-Orsay CNRS
3// arnault@lal.in2p3.fr
4// See the complete license in cmt_license.txt "http://www.cecill.info".
5//-----------------------------------------------------------
6
7#include <stdlib.h>
8#include <stdio.h>
9
10#include "cmt.h"
11#include "cmt_cvs.h"
12#include "cmt_awk.h"
13
14/**
15
16    Grep : perform a grep like operation onto a cmt_string
17
18    o All lines of the input string are collected when they contain
19      the specified pattern.
20    o The input string and the selector pattern are specified in
21      the constructor:
22
23         Grep (input_string, pattern)
24
25    o All selected lines are accumulated (appended) into the internal
26      variable m_result . 'space' is the separator.
27
28    o The accumulator is retrieved by the result () method.
29
30 */
31class Grep : public Awk
32{
33public:
34
35  void begin ();
36  void filter (const cmt_string& line);
37  const cmt_string& result () const;
38
39private:
40  cmt_string m_result;
41};
42
43/**
44
45     Cut : perform a cut-like operation :
46
47     o collect the <field>'th field of every line into the m_result
48       internal variable
49
50     o the field number is given in the constructor and starts at zero.
51
52     o selected fields are accumulated with a space as separator.
53
54 */
55class Cut : public Awk
56{
57public:
58  Cut (int field);
59  void begin ();
60  void filter (const cmt_string& line);
61  const cmt_string& result () const;
62
63private:
64  cmt_string m_result;
65  int m_field;
66};
67
68/**
69
70      History : maintains the history of checkout packages during a
71                recursive checkout, so as to avoid double checkouts.
72
73 */
74class History
75{
76public:
77  static History& instance ();
78  void clear ();
79  void install (const cmt_string& line);
80  bool is_installed (const cmt_string& line);
81
82private:
83  History ();
84
85  cmt_string m_installed;
86};
87
88/**
89
90     RecursivePass1 : simply validate use statements in a requirements file
91                      and echo those that really need to be handled.
92
93 */
94class RecursivePass1 : public Awk
95{
96public:
97
98  void begin ();
99  void filter (const cmt_string& line);
100  const cmt_string& result () const;
101
102private:
103  cmt_string m_result;
104  bool m_first;
105};
106
107/**
108
109     RecursivePass2 : after filtering the use statements really perform the
110                      checkouts.
111
112 */
113class CvsImplementation;
114class RecursivePass2 : public Awk
115{
116public:
117  RecursivePass2 (CvsImplementation& cvs);
118  void begin ();
119  void filter (const cmt_string& line);
120
121private:
122  CvsImplementation& m_cvs;
123};
124
125/**
126
127   Internal implementation of CVS to CMT operations.
128   The Cvs class only provides abstract interface.
129
130 */
131class CvsImplementation
132{
133public:
134
135  CvsImplementation ()
136  {
137    m_recursive = false;
138    m_head = false;
139    m_cmtcvstest = false;
140    m_verbose = false;
141    m_simulation = false;
142
143    m_home_dir = "";
144    m_checkout_dir = "";
145    m_offset = "";
146    m_branch_suffix = "";
147
148    m_last_module = "";
149    m_last_cvs_infos = "";
150    error_info = "";
151    tags_top_info = "";
152    tags_info = "";
153    cvsversions_top_info = "";
154    cvsversions_info = "";
155    branches_info = "";
156    subpackages_info = "";
157  }
158
159  void filter_list (cmt_string& text, const cmt_regexp& exp)
160      {
161        CmtSystem::cmt_string_vector list;
162
163        CmtSystem::split (text, " ", list);
164
165        int i;
166
167        text = "";
168
169        for (i = 0; i < list.size (); i++)
170          {
171            const cmt_string& s = list[i];
172            if (exp.match (s))
173              {
174                if (i > 0) text += " ";
175                text += s;
176              }
177          }
178      }
179
180    //
181    // This method exploits the hook installed into the loginfo script.
182    // A communication is setup with a dummy CVS module named .cmtcvsinfos/<module>
183    //
184    //  At import time, the contents of the file will be used to parameterize
185    // the script named cmt_buildcvsinfos2.sh (referenced in the loginfo script)
186    //
187    //  This script performs a scan in the CVS repository for currently 4 types of
188    // information :
189    //
190    //   all top symbolic tags installed for the module
191    //   all symbolic tags installed for the module
192    //   all branches available below this module
193    //   all subpackages installed below the module.
194    //
195    //    In principle, only modules corresponding to true CMT packages are considered.
196    //      o tags are obtained from the requirements file
197    //      o branches are sub-directories which are not themselves packages
198    //      o subpackages are sub-directories which are CMT packages
199    //        (a subdirectory is always either a branch or a subpackage)
200    //
201  void show_cvs_infos (const cmt_string& module)
202      {
203        if (module == "")
204          {
205            cout << "#CMT> cmt cvs needs a module name" << endl;
206            return;
207          }
208
209        if (module == m_last_module)
210          {
211            if (m_verbose)
212              {
213                cout << "#CMT> cvs infos for module " << module << " already there" << endl;
214              }
215          }
216        else
217          {
218            m_last_module = module;
219       
220            cmt_string home_dir = CmtSystem::pwd ();
221
222            //
223            // Activities related with .cmtcvsinfos will occur in a temporary directory
224            //
225            cmt_string tmp_dir = CmtSystem::getenv ("TMPDIR");
226            if (tmp_dir == "")
227              {
228                tmp_dir = CmtSystem::file_separator ();
229                tmp_dir += "tmp";
230              }
231           
232            if (!CmtSystem::cd (tmp_dir))
233              {
234                tmp_dir = home_dir;
235              }
236           
237            tmp_dir += CmtSystem::file_separator ();
238            tmp_dir += "cmtcvs";
239            {
240              cmt_string temp = CmtSystem::get_temporary_name ();
241              CmtSystem::basename (temp, temp);
242              tmp_dir += temp;
243            }
244       
245            if (!CmtSystem::test_directory (tmp_dir))
246              {
247                if (!CmtSystem::mkdir (tmp_dir))
248                  {
249                    cout << "#CMT> Cannot create the temporary directory [" 
250                         << tmp_dir << "]" << endl;
251                    return;
252                  }
253              }
254           
255            //trap "rm -rf ${tmp_dir}" 0 1 2 15
256           
257            if (!CmtSystem::cd (tmp_dir))
258              {
259                cout << "#CMT> Cannot move to the temporary directory " << tmp_dir << endl;
260
261                if (m_verbose)
262                  {
263                    cout << "#CMT> now removing tmp_dir " << tmp_dir << " home=" << home_dir << endl;
264                  }
265               
266                CmtSystem::remove_directory (tmp_dir);
267
268                return;
269              }
270           
271            if (m_verbose)
272              {
273                cout << "#CMT> cvs infos are now obtained from the temporary directory " << CmtSystem::pwd () << endl; 
274              }
275           
276            /*
277              #
278              # The script associated to such entries is supposed to :
279              #  1) extract the set of <infos> from the ${module}/cmt/requirements file
280              #  2) build an output of the form :
281              #      <infos>=info1 info2 info3 ...
282              #
283              # Currently this script can be found in
284              #
285              # ${CMTROOT}/cmt/cmt_buildcvsinfos2.sh
286              # %CMTROOT%/cmt/cmt_buildcvsinfos.py
287              #
288            */
289           
290            if (!CmtSystem::test_directory (".cmtcvsinfos"))
291              {
292                CmtSystem::mkdir (".cmtcvsinfos");
293              }
294           
295            CmtSystem::cd (".cmtcvsinfos");
296           
297            cmt_string cvsroot;
298           
299            CmtSystem::get_cvsroot (cvsroot);
300           
301            cmt_string command;
302           
303            command = "cvs";
304            if (cvsroot != "") 
305              {
306                command += " -d ";
307                command += cvsroot;
308              }
309            command += " -Q import -m cmt ";
310            if (m_cmtcvstest)
311              {
312                command += ".cmtcvsinfos/cmtcvstest";
313              }
314            else
315              {
316                command += ".cmtcvsinfos";
317              }
318            command += "/";
319            command += module;
320            command += " CMT v1";
321           
322            if (m_verbose || m_simulation)
323              {
324                cout << "#CMT> Executing [" << command << "]" << endl;
325              }
326
327            m_last_cvs_infos = "";
328            CmtSystem::execute (command, m_last_cvs_infos);
329
330            if (m_verbose)
331              {
332                cout << "#CMT> now removing tmp_dir " << tmp_dir << " home=" << home_dir << endl;
333              }
334           
335            CmtSystem::remove_directory (tmp_dir);
336
337            CmtSystem::cd (home_dir);
338          }
339
340        /**
341           Now retrieve all info fields :
342
343             error=
344             tags_top=
345             tags=
346             branches=
347             subpackages=
348
349         */
350
351        Grep grep;
352
353        grep.run (m_last_cvs_infos, "error=");
354
355        if (grep.result () != "")
356          {
357            error_info = grep.result ();
358            error_info.replace ("error=", "");
359          }
360        else
361          {
362            error_info = "";
363          }
364
365        grep.run (m_last_cvs_infos, "tags_top=");
366
367        if (grep.result () != "")
368          {
369            tags_top_info = grep.result ();
370            tags_top_info.replace ("tags_top=", "");
371          }
372        else
373          {
374            tags_top_info = "";
375          }
376
377        grep.run (m_last_cvs_infos, "tags=");
378
379        if (grep.result () != "")
380          {
381            tags_info = grep.result ();
382            tags_info.replace ("tags=", "");
383          }
384        else
385          {
386            tags_info = "";
387          }
388
389        grep.run (m_last_cvs_infos, "cvsversions_top=");
390
391        if (grep.result () != "")
392          {
393            cvsversions_top_info = grep.result ();
394            cvsversions_top_info.replace ("cvsversions_top=", "");
395          }
396        else
397          {
398            cvsversions_top_info = "";
399          }
400
401        grep.run (m_last_cvs_infos, "cvsversions=");
402
403        if (grep.result () != "")
404          {
405            cvsversions_info = grep.result ();
406            cvsversions_info.replace ("cvsversions=", "");
407          }
408        else
409          {
410            cvsversions_info = "";
411          }
412
413        cmt_string tag_filter = CmtSystem::getenv ("CMTCVSTAGFILTER");
414
415        if (tag_filter != "")
416          {
417            cmt_string package;
418            CmtSystem::basename (module, package);
419           
420            cmt_string pattern = "<package>";
421           
422            tag_filter.replace_all (pattern, package);
423           
424            cmt_regexp exp (tag_filter);
425           
426            cmt_string text;
427           
428            filter_list (tags_top_info, exp);
429            filter_list (tags_info, exp);
430            filter_list (cvsversions_top_info, exp);
431            filter_list (cvsversions_info, exp);
432          }
433
434        if (m_cmtcvstest)
435          {
436            cout << "## tags_top_info=" << tags_top_info << endl;
437            cout << "## tags_info=" << tags_info << endl;
438            cout << "## cvsversions_top_info=" << cvsversions_top_info << endl;
439            cout << "## cvsversions_info=" << cvsversions_info << endl;
440          }
441
442        grep.run (m_last_cvs_infos, "branches=");
443
444        if (grep.result () != "")
445          {
446            branches_info = grep.result ();
447            branches_info.replace ("branches=", "");
448          }
449        else
450          {
451            branches_info = "";
452          }
453
454        grep.run (m_last_cvs_infos, "subpackages=");
455
456        if (grep.result () != "")
457          {
458            subpackages_info = grep.result ();
459            subpackages_info.replace ("subpackages=", "");
460          }
461        else
462          {
463            subpackages_info = "";
464          }
465      }
466
467  void show_cvs_infos (const cmt_string& offset,
468                       const cmt_string& module)
469  {
470    cmt_string full_name;
471
472    if (offset != "") 
473      {
474        full_name = offset;
475        full_name += "/";
476        while (full_name.find ("//") != cmt_string::npos)
477          {
478            full_name.replace_all ("//", "/");
479          }
480      }
481
482    full_name += module;
483
484    show_cvs_infos (full_name);
485  }
486
487    //
488    // Resolve all possible "aaa/bbb/../ccc/ddd" patterns into "aaa/ccc/ddd"
489    //
490  void filter_dir (cmt_string& d)
491      {
492        while (true)
493          {
494            int pos = d.find ("/../");
495            if (pos == cmt_string::npos) break;
496           
497            int slash = d.find ("/");
498            if (slash < pos)
499              {
500                  //
501                  // xxxxx/yyy/../zzzz -> xxxxx/zzzz
502                  // 01234567890123456
503                  //       1234567
504                  //  pos   = 9
505                  //  slash = 5
506                  //  length = 9+3-5
507                  //
508                d.erase (slash + 1, pos + 3 - slash);
509              }
510            else
511              {
512                  //
513                  // yyy/../zzzz -> zzzz
514                  // 01234567890
515                  // 1234567
516                  //  pos   = 3
517                  //  length = 3+1+3
518                  //
519                d.erase (0, pos + 1 + 3);
520              }
521          }
522      }
523
524  /**
525     From a space-separated list of version tags, try to find one tag
526     matching a given regular expression.
527
528       o The first matching tag is returned into 'version'
529       o Success is returned as function value.
530
531   */
532  bool match_version_request (const cmt_string& text, 
533                              const cmt_regexp& version_exp,
534                              cmt_string& version)
535      {
536        CmtSystem::cmt_string_vector vs;
537     
538        CmtSystem::split (text, " \t", vs);
539
540        version = "";
541
542        for (int i = 0; i < vs.size (); i++)
543          {
544            const cmt_string& vv = vs[i];
545       
546            if (version_exp.match (vv))
547              {
548                version = vv;
549                return (true);
550              }
551          }
552
553        return (false);
554      }
555
556  bool get_version (const cmt_string& prefix,
557                    const cmt_string& package,
558                    const cmt_string& version_request,
559                    cmt_string& module,
560                    cmt_string& version,
561                    bool& at_head)
562      {
563        Grep grep;
564        cmt_string topversions;
565        cmt_string versions;
566        cmt_string requested_version = version_request;
567   
568        at_head = false;
569           
570        module = "";
571
572        if (prefix != "")
573          {
574            module = prefix;
575            module += "/"; // This is for CVS only thus we don't use the real separator.
576            while (module.find ("//") != cmt_string::npos)
577              {
578                module.replace_all ("//", "/");
579              }
580          }
581
582        module += package;
583
584          /**
585           *   Try to figure out what is the effective version tag available
586           *   for the requested version expressions (which may contain
587           *   wild card)
588           *
589           *     the requested version may either be in the top tags (ie those
590           *     corresponding to the same most recent CVS version number before
591           *     the HEAD) or not. The returned at_head flag will show this.
592           *
593           *     then the requested package may either be located in the CVS repository
594           *     under the prefix or not, the returned module will contain the effective
595           *     location where the requested version has been found.
596           */
597
598        if (m_verbose)
599          {
600            cout << "#CMT> requesting cvs infos onto module " << module << endl;
601          }
602
603        show_cvs_infos (module);
604
605        if (error_info != "")
606          {
607            versions = "";
608            cout << "#CMT> Package " << package << " not found in ${CVSROOT}" << endl;
609            return (false);
610          }
611
612        versions = tags_top_info;
613
614        cmt_string v = version_request;
615
616        if (version_request.find ("*") != cmt_string::npos)
617          {
618            v.replace_all ("*", ".*");
619          }
620        else
621          {
622            v += "$";
623          }
624
625        if (m_cmtcvstest) cout << "##    (version expression is " << v << ")" << endl;
626
627        cmt_regexp version_exp (v);
628   
629        if (!match_version_request (versions, version_exp, version))
630          {
631            if (m_cmtcvstest) cout << "##    (no match in " << versions << ")" << endl;
632
633              // We try on non-top versions
634
635            versions = tags_info;
636
637            if (!match_version_request (versions, version_exp, version))
638              {
639                if (m_cmtcvstest) cout << "##    (no match in " << versions << ")" << endl;
640
641                version = requested_version;
642                int pos = 0;
643                if ((pos = version.find ("*")) != cmt_string::npos)
644                  {
645                      //
646                      //  There was a wild card but the expression does not match
647                      // any of the existing tags in CVS.
648                      //  Things will be retreived from HEAD but we have to build
649                      // a reasonable version tag from the wild card expression.
650                      //  If the letter before the * was a digit, then simply remove
651                      // the * (v5* -> v5) otherwise add a zero (v5r* -> v5r0)
652                      //
653                    if (pos > 0)
654                      {
655                        char letter = version[pos-1];
656
657                        static const cmt_string digits = "0123456789";
658
659                        if (digits.find (letter) == cmt_string::npos)
660                          {
661                              // "v5r*" -> "v5r0"
662                            version.replace ("*", "0");
663                          }
664                        else
665                          {
666                              // "v5*" -> "v5"
667                            version.replace ("*", "");
668                          }
669                      }
670                    else
671                      {
672                          // The expression was simply "*" !!!
673                        version = "v0";
674                      }
675                  }
676                at_head = true;
677              }
678            else
679              {
680                if (m_cmtcvstest) cout << "##    (match in non head " << versions << ")" << endl;
681
682                at_head = false;
683              }
684          }
685        else
686          {
687            if (m_cmtcvstest) cout << "##    (match in head " << versions << ")" << endl;
688
689            at_head = true;
690          }
691   
692          /**
693           *   Here we have at least one version matching the requested expression.
694           */
695   
696        return (true);
697      }
698
699  cmt_string build_version_directory (const cmt_string& prefix,
700                                      const cmt_string& package,
701                                      const cmt_string& version)
702      {
703        cmt_string dir = m_home_dir;
704
705        if (m_checkout_dir != "")
706          {
707            dir += CmtSystem::file_separator ();
708            dir += m_checkout_dir;
709          }
710
711        dir += CmtSystem::file_separator ();
712        dir += prefix;
713        dir += CmtSystem::file_separator ();
714        dir += package;
715
716        if (Cmt::get_current_structuring_style () == with_version_directory)
717          {
718            dir += CmtSystem::file_separator ();
719            dir += version;
720          }
721
722        CmtSystem::reduce_file_separators (dir);
723
724        return (dir);
725      }
726
727  bool really_checkout_package (const cmt_string& prefix,
728                                const cmt_string& package,
729                                const cmt_string& version,
730                                const cmt_string& module,
731                                const cmt_string& basedir,
732                                bool at_head)
733      {
734        cmt_string dir = basedir;
735        cmt_string out;
736
737        cout << "# ================= working on package " << package
738             << " version " << version;
739
740        if (at_head) cout << " (At head) ";
741
742        {
743          cmt_string full_prefix;
744
745          full_prefix = m_offset;
746          full_prefix += prefix;
747
748          cmt_string echo_ppath;
749       
750          if (prefix != "")
751            {
752              echo_ppath = " path ";
753              echo_ppath += prefix;
754            }
755
756          cout << echo_ppath << endl;
757        }
758
759        CmtSystem::dirname (dir, dir);
760
761        //if (Cmt::get_current_structuring_style () == with_version_directory)
762        {
763          if (m_simulation)
764            {
765              cout << "#CMT> Would mkdir " << dir << endl;
766            }
767          else
768            {
769              if (m_verbose)
770                {
771                  cout << "#CMT> About to mkdir " << dir << endl;
772                }
773             
774              if (!CmtSystem::mkdir (dir))
775                {
776                  cout << "# Error creating the base directory :" << dir << endl;
777                  cout << "#---------------------------------------------------------" << endl;
778                  return (false);
779                }
780             
781              CmtSystem::cd (dir);
782             
783              /*
784              if (m_verbose)
785                {
786                  cout << "#CMT> pwd.1=" << CmtSystem::pwd () << endl;
787                }
788              */
789            }
790        }
791       
792        cout << "  # get top files " << endl;
793           
794        cmt_string command = "cvs -Q co -P -l ";
795        if (!at_head)
796          {
797            command += "-r ";
798            command += version;
799          }
800
801        if (Cmt::get_current_structuring_style () == with_version_directory)
802          {
803            command += " -d ";
804            command += version;
805          }
806        else
807          {
808            command += " -d ";
809            command += package;
810          }
811
812        command += " ";
813        command += module;
814               
815        if (m_cmtcvstest)
816          {
817            cmt_string cvsroot;
818           
819            CmtSystem::get_cvsroot (cvsroot);
820           
821            cout << "## cvsroot=" << cvsroot << " command[" << command << "]" << endl;
822          }
823       
824        int status = 0;
825        int retry = 0;
826
827        for (;;)
828          {
829            if (m_verbose || m_simulation)
830              {
831                cout << "#CMT> Executing [" << command << "]" << endl;
832              }
833
834            if (!m_simulation)
835              {
836                //status = CmtSystem::execute (command, out);
837                status = CmtSystem::execute (command);
838              }
839       
840            if (status != 0)
841              {
842                retry++;
843
844                cout << "# Error getting package CMT contents: status=" << status << endl;
845                cout << "#---------------------------------------------------------" << endl;
846
847                if (retry > 5) exit(0);
848
849              }
850            else
851              {
852                break;
853              }
854          }
855
856
857          {
858            if (Cmt::get_current_structuring_style () == with_version_directory)
859              {
860                if (m_simulation)
861                  {
862                    cout << "#CMT> Would mkdir " << version << endl;
863                  }
864                else
865                  {
866                    if (m_verbose)
867                      {
868                        cout << "#CMT> About to mkdir " << version << endl;
869                      }
870                    if (!CmtSystem::cd (version))
871                      {
872                        CmtSystem::mkdir (version);
873                        if (!CmtSystem::cd (version))
874                          {
875                            cout << "# Error creating the version directory :" << version << endl;
876                            cout << "#---------------------------------------------------------" << endl;
877                            return (false);
878                          }
879                      }
880                   
881                    /*
882                    if (m_verbose)
883                      {
884                        cout << "#CMT> pwd.2=" << CmtSystem::pwd () << endl;
885                      }
886                    */
887                  }
888               
889                dir += CmtSystem::file_separator ();
890                dir += version;
891              }
892            else
893              {
894                if (m_simulation)
895                  {
896                    cout << "#CMT> will mkdir " << package << endl;
897                  }
898                else
899                  {
900                    if (!CmtSystem::cd (package))
901                      {
902                        if (m_verbose)
903                          {
904                            cout << "#CMT> About to mkdir " << package << endl;
905                          }
906                        CmtSystem::mkdir (package);
907                        if (!CmtSystem::cd (package))
908                          {
909                            cout << "# Error creating the package directory :" << package << endl;
910                            cout << "#---------------------------------------------------------" << endl;
911                            return (false);
912                          }
913                      }
914                   
915                    /*
916                    if (m_verbose)
917                      {
918                        cout << "#CMT> pwd.3=" << CmtSystem::pwd () << endl;
919                      }
920                    */
921                  }
922               
923                dir += CmtSystem::file_separator ();
924                dir += package;
925              }
926          }
927               
928        cmt_string entries_file_name;
929        cmt_string text;
930       
931        cmt_string branches = CmtSystem::getenv ("CMTCVSBRANCHES");
932       
933        if (branches == "")
934          {
935            branches = branches_info;
936          }
937       
938        CmtSystem::cmt_string_vector branch_vector;
939       
940        CmtSystem::split (branches, " \t", branch_vector);
941       
942        int i;
943       
944        cout << "  # get branches " << branches << endl;
945       
946        //command = "(";
947        command = "";
948
949        entries_file_name = "CVS";
950        entries_file_name += CmtSystem::file_separator ();
951        entries_file_name += "Entries";
952       
953        if (!text.read (entries_file_name))
954          {
955              // This happens when there were no top files
956          }
957       
958        for (i = 0; i < branch_vector.size (); i++)
959          {
960            cmt_string& branch = branch_vector[i];
961
962            if (i > 0)
963              {
964                command += CmtSystem::command_separator ();
965              }
966           
967              //command += "cvs -Q co -P ";
968            command += "cvs -Q co ";
969           
970//            if (branch != "cmt")
971//              {
972            if (!at_head)
973              {
974                command += "-r ";
975                command += version;
976              }
977//              }
978           
979            command += " -d ";
980            command += branch;
981            command += " ";
982            command += module;
983            command += "/";    // CVS uses the '/' notation on all platforms!!
984            command += branch;
985            //command += "\n";
986           
987            text += "D/";
988            text += branch;
989            text += "////\n";
990          }
991
992        //command += "; echo cmtcvsstatus=$?) 2>&1 ";
993
994        if (m_cmtcvstest)
995          {
996            cmt_string cvsroot;
997           
998            CmtSystem::get_cvsroot (cvsroot);
999           
1000            cout << " cvsroot=" << cvsroot << " command[" << command << "]" << endl;
1001          }
1002       
1003        status = 0;
1004        retry = 0;
1005
1006        for (;;)
1007          {
1008            if (m_verbose || m_simulation)
1009              {
1010                cout << "#CMT> Executing [" << command << "]" << endl;
1011              }
1012
1013            if (!m_simulation)
1014              {
1015                //status = CmtSystem::execute (command, out);
1016                status = CmtSystem::execute (command);
1017              }
1018       
1019            if (status != 0)
1020              {
1021                retry++;
1022
1023                cout << "# Error getting package contents: status=" << status << endl;
1024                cout << "#---------------------------------------------------------" << endl;
1025
1026                if (retry > 5) exit(0);
1027
1028              }
1029            else
1030              {
1031                break;
1032              }
1033          }
1034
1035          {
1036            if (!CmtSystem::test_directory ("CVS"))
1037              {
1038                  /**
1039                   * The CVS repository had not been created (this is generally
1040                   * due to the lack of top files)
1041                   */
1042               
1043                if (m_simulation)
1044                  {
1045                    cout << "#CMT> Would create the CVS directory" << endl;
1046                  }
1047                else
1048                  {
1049                    if (m_verbose)
1050                      {
1051                        cout << "#CMT> About to mkdir " << "CVS" << endl;
1052                      }
1053                    CmtSystem::mkdir ("CVS");
1054                  }
1055
1056                cmt_string s;
1057               
1058                  // Let's create first the CVS/Root file.
1059               
1060                CmtSystem::get_cvsroot (s);
1061                s += "\n";
1062               
1063                cmt_string f;
1064               
1065                f = "CVS";
1066                f += CmtSystem::file_separator ();
1067                f += "Root";
1068               
1069                if (m_simulation)
1070                  {
1071                    cout << "#CMT> Would fill in the CVS/Root file with " << endl;
1072                    cout << s << endl;
1073                  }
1074                else
1075                  {
1076                    if (m_verbose)
1077                      {
1078                        cout << "#CMT> Fill in the CVS/Root file with " << endl;
1079                        cout << s << endl;
1080                      }
1081                    s.write (f);
1082                  }
1083               
1084                  // Now we create the CVS/Repository file
1085               
1086                f = "CVS";
1087                f += CmtSystem::file_separator ();
1088                f += "Repository";
1089               
1090                CmtSystem::get_cvsroot (s);
1091                if (s[0] == ':')
1092                  {
1093                    int pos = s.find (1, ":");
1094                    s.erase (0, pos+1);
1095                    pos = s.find (0, ":");
1096                    s.erase (0, pos+1);
1097                  }
1098                s += "/";
1099                s += module;
1100                s += "\n";
1101               
1102                if (m_simulation)
1103                  {
1104                    cout << "#CMT> Would fill in the CVS/Repository file with " << endl;
1105                    cout << s << endl;
1106                  }
1107                else
1108                  {
1109                    if (m_verbose)
1110                      {
1111                        cout << "#CMT> Fill in the CVS/Repository file with " << endl;
1112                        cout << s << endl;
1113                      }
1114                    s.write (f);
1115                  }
1116              }
1117           
1118            if (m_simulation)
1119              {
1120                cout << "#CMT> Would write the top CVS/Entries file with " << endl;
1121                cout << text << endl;
1122              }
1123            else
1124              {
1125                // Now the CVS/Entries is ready to be created.
1126                if (m_verbose)
1127                  {
1128                    cout << "#CMT> Fill in the top CVS/Entries file with " << endl;
1129                    cout << text << endl;
1130                  }
1131                text.write (entries_file_name);
1132              }
1133          }
1134
1135        return (true);
1136      }
1137
1138  cmt_string find_matching_version (const cmt_string& expression)
1139      {
1140        cmt_string result;
1141
1142          //
1143          // Here expression takes the form
1144          //   <some path>/<expression with wild-card>
1145          //
1146
1147        cmt_string dir;
1148        CmtSystem::dirname (expression, dir);
1149        dir += CmtSystem::file_separator ();
1150
1151        cmt_string version;
1152        CmtSystem::basename (expression, version);
1153
1154        if (version.find ("*") == cmt_string::npos)
1155          {
1156              // there is no wildcarding here. A simple test is enough.
1157            if (CmtSystem::test_directory (expression))
1158              {
1159                if (m_cmtcvstest) cout << "## Found direct match with " << version << endl;
1160                result = version;
1161              }
1162            else
1163              {
1164                if (m_cmtcvstest) cout << "## Explicit version " << version
1165                                       << " has no direct match" << endl;
1166              }
1167          }
1168        else
1169          {
1170            version.replace ("*", ".*");
1171
1172            cmt_regexp exp (version);
1173
1174            CmtSystem::cmt_string_vector list;
1175
1176            if (m_cmtcvstest) cout << "## Trying scan_dir dir=" << dir
1177                                   << " exp=" << version << endl;
1178
1179            CmtSystem::scan_dir (dir, exp, list);
1180
1181            if (list.size () > 0)
1182              {
1183                result = list[0];
1184
1185                if (m_cmtcvstest) cout << "## At least one version is matching " << version
1186                                       << "(" << list.size () << " matches) " << result << endl;
1187
1188                CmtSystem::basename (result, result);
1189              }
1190            else
1191              {
1192                if (m_cmtcvstest) cout << "## There is no version matching " << version << endl;
1193              }
1194          }
1195
1196        return (result);
1197      }
1198 
1199  void checkout_package (const cmt_string& prefix,
1200                         const cmt_string& package,
1201                         const cmt_string& specified_version)
1202      {
1203        if (m_verbose)
1204          {
1205            cout << "#CMT> checkout_package> prefix=" << prefix
1206                 << " package=" << package
1207                 << " specified_version=" << specified_version
1208                 << endl;
1209          }
1210
1211        cmt_string version = specified_version;
1212        cmt_string empty;
1213        cmt_string full_prefix;
1214
1215        full_prefix = m_offset;
1216        full_prefix += prefix;
1217
1218        cmt_string echo_ppath;
1219       
1220        if (prefix != "")
1221          {
1222            echo_ppath = " path ";
1223            echo_ppath += prefix;
1224          }
1225       
1226        if (version == "")
1227          {
1228            cout << "# ================= No version specified for package " << package << endl;
1229            return;
1230          }
1231
1232          //
1233          //  First make an attempt to locate the specified version of
1234          //  this package "as-it-is" in the work area.
1235          //   Since 'version' may contain wild-card, it's likely that
1236          //  we should not simply use CmtSystem::test_directory but
1237          //  use the wild-card search.
1238          //
1239
1240        cmt_string dir;
1241       
1242        dir = build_version_directory (prefix, package, version);
1243             
1244        if (m_cmtcvstest) 
1245          cout << "## (testing dir= " << dir << ")" << endl;
1246
1247        bool recursive = m_recursive;
1248
1249          /*
1250        if (m_cmtcvstest)
1251          {
1252            cmt_string v = find_matching_version (dir);
1253
1254            cout << "---> v=" << v << endl;
1255          }
1256          */
1257
1258        cmt_string effective_version = find_matching_version (dir);
1259
1260        if (effective_version != "")
1261          {
1262            version = effective_version;
1263
1264            dir = build_version_directory (prefix, package, version);
1265
1266            cout << "# ================= Package " << package
1267                 << " version " << version << echo_ppath
1268                 << " already installed in " << dir << endl;
1269
1270            recursive = false;
1271          }
1272        else
1273          {
1274            bool at_head = false;
1275            cmt_string module;
1276
1277              //
1278              // get_version attempts to find the most appropriate version
1279              // tag matching the specification FROM the repository. However,
1280              // we should take into account situations where some versions have
1281              // already been checked out, in which case they might be sufficient
1282              // (or preferred?)
1283              //
1284
1285            if (version.find ("*") != cmt_string::npos)
1286              {
1287                cout << "# ================= Package " << package
1288                     << " version " << version << echo_ppath
1289                     << " has wild cards and will not be considered." << endl;
1290                return;
1291              }
1292
1293            if (!get_version (full_prefix, package, version, 
1294                              module, version, at_head))
1295              {
1296                return;
1297              }
1298
1299              //cout << " full_prefix=[" << full_prefix << "] module=[" << module << "]" << endl;
1300
1301            if (m_cmtcvstest) cout << "## after get_version at_head=" << at_head << " m_head=" << m_head << endl;
1302
1303            if (m_head)
1304              {
1305                m_head = false;
1306
1307                at_head = true;
1308              }
1309            else
1310              {
1311                at_head = false;
1312              }
1313
1314              //
1315              // Make a second try after having selected a version from all the
1316              // available versions compatible with the specified version
1317              //
1318
1319            dir = build_version_directory (prefix, package, version);
1320
1321            if (CmtSystem::test_directory (dir))
1322              {
1323                cout << "# ================= Package " << package
1324                     << " version " << version << echo_ppath
1325                     << " already installed." << endl;
1326
1327                recursive = false;
1328              }
1329            else
1330              {
1331                  //
1332                  // Now we can say that we have to perform the real checkout.
1333                  //
1334
1335                if (!really_checkout_package (prefix, package, version, module, dir, at_head))
1336                  {
1337                    cout << "# bad return from really_checkout_package" << endl;
1338                    return;
1339                  }
1340              }
1341          }
1342
1343          //
1344          //  Now reach the newly checked out package.
1345          //
1346
1347        if (m_simulation)
1348          {
1349            cout << "#CMT> Package directory not really created " << dir << endl;
1350          }
1351        else
1352          {
1353            if (!CmtSystem::cd (dir))
1354              {
1355                cout << "#CMT> Package directory not created " << dir << endl;
1356              }
1357           
1358
1359            /*
1360            if (m_verbose)
1361              {
1362                cout << "#CMT> pwd.4=" << CmtSystem::pwd () << endl;
1363              }
1364            */
1365
1366            // Check if it is a true CMT package.
1367           
1368            cmt_string file_name;
1369           
1370            file_name = "cmt";
1371            file_name += CmtSystem::file_separator ();
1372            file_name += "requirements";
1373           
1374            if (CmtSystem::test_file (file_name))
1375              {
1376                dir += CmtSystem::file_separator ();
1377                dir += "cmt";
1378                CmtSystem::cd ("cmt");
1379               
1380                /*
1381                if (m_verbose)
1382                  {
1383                    cout << "#CMT> pwd.5=" << CmtSystem::pwd () << endl;
1384                  }
1385                */
1386
1387                if (Cmt::get_current_structuring_style () == without_version_directory)
1388                  {
1389                    cmt_string text = version;
1390                    text += "\n";
1391                    text.write ("version.cmt");
1392                  }
1393              }
1394            else
1395              {
1396                file_name = "mgr";
1397                file_name += CmtSystem::file_separator ();
1398                file_name += "requirements";
1399               
1400                if (CmtSystem::test_file (file_name))
1401                  {
1402                    dir += CmtSystem::file_separator ();
1403                    dir += "mgr";
1404                    CmtSystem::cd ("mgr");
1405
1406                    /*
1407                    if (m_verbose)
1408                      {
1409                        cout << "#CMT> pwd.6=" << CmtSystem::pwd () << endl;
1410                      }
1411                    */
1412                  }
1413                else
1414                  {
1415                    cout << "# " << package << " not a CMT package" << endl;
1416                    return;
1417                  }
1418              }
1419
1420            //cout << "#   (recursive is " << recursive << ")" << endl;
1421
1422            if (recursive)
1423              {
1424                checkout_from_requirements ("requirements");
1425              }
1426          }
1427      }
1428
1429  /**
1430   *   We provide a path to a requirements file. From it we read the use
1431   *  statements, and we try to checkout the corresponding packages.
1432   */
1433  void checkout_from_requirements (const cmt_string& requirements_path)
1434  {
1435    static cmt_regexp expression ("^[ \t]*use[ \t]");
1436
1437    cmt_string text;
1438
1439    text.read (requirements_path);
1440
1441    RecursivePass1 p1;
1442    p1.run (text, expression);
1443
1444    RecursivePass2 p2 (*this);
1445    p2.run (p1.result ());
1446  }
1447
1448  void tags (const CmtSystem::cmt_string_vector& arguments)
1449      {
1450        if (arguments.size () < 1)
1451          {
1452            help ();
1453            return;
1454          }
1455       
1456        if (CmtSystem::getenv ("CVSROOT") == "")
1457          {
1458            cout << "# Please set CVSROOT first !" << endl;
1459            return;
1460          }
1461             
1462        if (CmtSystem::getenv ("CMTCVSTEST") != "")
1463          {
1464            m_cmtcvstest = true;
1465          }
1466        else
1467          {
1468            m_cmtcvstest = false;
1469          }
1470
1471        m_offset = CmtSystem::getenv ("CMTCVSOFFSET");
1472        if (m_offset != "") 
1473          {
1474            m_offset += "/";
1475            m_offset.replace_all ("//", "/");
1476          }
1477
1478        bool all = false;
1479       
1480        for (int arg = 0; arg < arguments.size (); arg++)
1481          {
1482            const cmt_string& option = arguments[arg];
1483
1484            if (option == "-all")
1485              {
1486                all = true;
1487              }
1488            else
1489              {
1490                show_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), option);
1491
1492                if (error_info != "")
1493                  {
1494                    cout << error_info << endl;
1495                  }
1496                else
1497                  {
1498                    cmt_string tags;
1499
1500                    if (all)
1501                      {
1502                        tags = cvsversions_top_info;
1503                        tags += " ";
1504                        tags += cvsversions_info;
1505                      }
1506                    else
1507                      {
1508                        tags = tags_top_info;
1509                        tags += " ";
1510                        tags += tags_info;
1511                      }
1512
1513                    CmtSystem::cmt_string_vector v;
1514
1515                    CmtSystem::split (tags, " \t", v);
1516                    for (int i = 0; i < v.size (); i++)
1517                      {
1518                        const cmt_string& s = v[i];
1519                        cout << s << endl;
1520                      }
1521                  }
1522              }
1523          }
1524      }
1525
1526  void branches (const cmt_string& module)
1527      {
1528        cmt_string out;
1529
1530        show_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), module);
1531
1532        if (error_info != "")
1533          {
1534            cout << error_info << endl;
1535          }
1536        else
1537          {
1538            cout << branches_info << endl;
1539          }
1540      }
1541
1542  void subpackages (const cmt_string& module)
1543      {
1544        cmt_string out;
1545
1546        show_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), module);
1547
1548        if (error_info != "")
1549          {
1550            cout << error_info << endl;
1551          }
1552        else
1553          {
1554            cout << subpackages_info << endl;
1555          }
1556      }
1557
1558  void help ()
1559      {
1560        cout << "> cd <some work area>" << endl;
1561        cout << "> cmt checkout [modifier ...] <package>" << endl;
1562        cout << "" << endl;
1563        cout << "   modifier :" << endl;
1564        cout << "   -l        Do not process used packages (default)." << endl;
1565        cout << "   -R        Process used packages recursively." << endl;
1566        cout << "   -r rev    Check out version tag. (is sticky)" << endl;
1567        cout << "   -d dir    Check out into dir instead of module name." << endl;
1568        cout << "   -o offset Offset in the CVS repository" << endl;
1569        cout << "   -requirements <requirements file path>  Check out packages referenced in this requirements file" << endl;
1570        cout << "   -n        simulation mode on" << endl;
1571        cout << "   -v        verbose mode on" << endl;
1572        cout << "   --help    print this help" << endl;
1573        cout << "" << endl;
1574      }
1575
1576  void do_checkout (const cmt_string& module, const cmt_string& version_tag)
1577  {
1578    //CMTPATH=${CMTPATH}:${m_home_dir}; export CMTPATH
1579
1580    History& h = History::instance ();
1581
1582    h.clear ();
1583
1584    if (module == "")
1585      {
1586        if (m_verbose)
1587          {
1588            cout << "#CMT> Missing module name" << endl;
1589          }
1590        return;
1591      }
1592
1593    cmt_string prefix;
1594    cmt_string package;
1595    cmt_string version;
1596   
1597    if (version_tag == "")
1598      {
1599        Cut cut (0);
1600       
1601        cmt_string m;
1602        m = m_offset;
1603        m += module;
1604       
1605        show_cvs_infos (m);
1606       
1607        if (error_info != "")
1608          {
1609            cout << error_info << endl;
1610            return;
1611          }
1612
1613        if (tags_top_info != "") version = tags_top_info;
1614        else version = tags_info;
1615       
1616          //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "version=" << version << endl;
1617
1618        cut.run (version);
1619       
1620        version = cut.result ();
1621
1622          //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "version=" << version << endl;
1623      }
1624    else
1625      {
1626        version = version_tag;
1627      }
1628   
1629    CmtSystem::dirname (module, prefix);
1630    CmtSystem::basename (module, package);
1631   
1632    cmt_string top_dir;
1633       
1634    top_dir = m_home_dir;
1635    top_dir += CmtSystem::file_separator ();
1636    top_dir += m_checkout_dir;
1637    top_dir += CmtSystem::file_separator ();
1638    top_dir += prefix;
1639    top_dir += CmtSystem::file_separator ();
1640    top_dir += package;
1641    top_dir += CmtSystem::file_separator ();
1642    top_dir += version;
1643
1644    CmtSystem::reduce_file_separators (top_dir);
1645
1646    if (m_verbose)
1647      {
1648        cout << "#CMT> about to checkout package " << package << " version " << version << " into " << top_dir << endl;
1649      }
1650   
1651    checkout_package (prefix, package, version);
1652
1653    /*
1654    if (m_verbose)
1655      {
1656        cout << "#CMT> after checkout_package pwd.7=" << CmtSystem::pwd () << " top_dir=" << top_dir << endl;
1657      }
1658    */
1659
1660    if (m_simulation) return;
1661
1662    if (!CmtSystem::cd (top_dir)) return;
1663
1664    /*
1665    if (m_verbose)
1666      {
1667        cout << "#CMT> pwd.8=" << CmtSystem::pwd () << endl;
1668      }
1669    */
1670   
1671    cmt_string file_name;
1672   
1673    file_name = "cmt";
1674    file_name += CmtSystem::file_separator ();
1675    file_name += "requirements";
1676   
1677    if (CmtSystem::test_file (file_name))
1678      {
1679        top_dir += CmtSystem::file_separator ();
1680        top_dir += "cmt";
1681        CmtSystem::cd ("cmt");
1682
1683        /*
1684        if (m_verbose)
1685          {
1686            cout << "#CMT> pwd.9=" << CmtSystem::pwd () << endl;
1687          }
1688        */
1689      }
1690    else
1691      {
1692        file_name = "mgr";
1693        file_name += CmtSystem::file_separator ();
1694        file_name += "requirements";
1695       
1696        if (CmtSystem::test_file (file_name))
1697          {
1698            top_dir += CmtSystem::file_separator ();
1699            top_dir += "mgr";
1700            CmtSystem::cd ("mgr");
1701
1702            /*
1703            if (m_verbose)
1704              {
1705                cout << "#CMT> pwd.10=" << CmtSystem::pwd () << endl;
1706              }
1707            */
1708          }
1709        else
1710          {
1711            cout << "# " << package << " was not properly checked out and is missing its cmt/requirements file" << endl;
1712            return;
1713          }
1714      }
1715   
1716    if (m_verbose)
1717      {
1718        cout << "#CMT> package " << package << " has been checked out" << endl;
1719      }
1720
1721    if (m_recursive)
1722      {
1723        if (m_verbose || m_simulation)
1724          {
1725            cout << "#CMT> Executing [" << "cmt -quiet broadcast cmt -quiet config" << "]" << endl;
1726          }
1727       
1728        if (!m_simulation)
1729          {
1730            CmtSystem::execute ("cmt -quiet broadcast cmt -quiet config");
1731          }
1732      }
1733    else
1734      {
1735        if (m_verbose || m_simulation)
1736          {
1737            cout << "#CMT> Executing [" << "cmt -quiet config" << "]" << endl;
1738          }
1739       
1740        if (!m_simulation)
1741          {
1742            CmtSystem::execute ("cmt -quiet config");
1743          }
1744      }
1745  }
1746
1747  void checkout (const CmtSystem::cmt_string_vector& arguments)
1748      {
1749        if (arguments.size () < 1)
1750          {
1751            help ();
1752            return;
1753          }
1754       
1755        if (CmtSystem::getenv ("CVSROOT") == "")
1756          {
1757            cout << "# Please set CVSROOT first !" << endl;
1758            return;
1759          }
1760             
1761        if (CmtSystem::getenv ("CMTCVSTEST") != "")
1762          {
1763            m_cmtcvstest = true;
1764          }
1765        else
1766          {
1767            m_cmtcvstest = false;
1768          }
1769
1770        m_home_dir = CmtSystem::pwd ();
1771        m_checkout_dir = "";
1772        m_offset = "";
1773        m_branch_suffix = "";
1774
1775        cmt_string module;
1776             
1777        m_recursive = false;
1778
1779        bool need_version_tag = false;
1780        cmt_string version_tag;
1781
1782        bool need_checkout_dir = false;
1783        bool need_offset = false;
1784        bool need_requirements_file = false;
1785
1786        m_simulation = false;
1787        //m_verbose = true;
1788        m_verbose = false;
1789
1790        bool need_branch_suffix = false;
1791
1792        m_head = true;
1793
1794        m_offset = CmtSystem::getenv ("CMTCVSOFFSET");
1795        if (m_offset != "") 
1796          {
1797            m_offset += "/";
1798            m_offset.replace_all ("//", "/");
1799          }
1800
1801        for (int arg = 0; arg < arguments.size (); arg++)
1802          {
1803            const cmt_string& option = arguments[arg];
1804
1805            if (need_version_tag)
1806              {
1807                need_version_tag = false;
1808
1809                if (option == "HEAD")
1810                  {
1811                    m_head = true;
1812                  }
1813                else
1814                  {
1815                    version_tag = option;
1816                  }
1817              }
1818            else if (need_checkout_dir)
1819              {
1820                need_checkout_dir = false;
1821                m_checkout_dir = option;
1822              }
1823            else if (need_offset)
1824              {
1825                need_offset = false;
1826                m_offset = option;
1827                m_offset += '/';
1828                m_offset.replace_all ("//", "/");
1829              }
1830            else if (need_branch_suffix)
1831              {
1832                need_branch_suffix = false;
1833                m_branch_suffix = "-";
1834                m_branch_suffix += option;
1835              }
1836            else if (need_requirements_file)
1837              {
1838                need_requirements_file = false;
1839                m_head = false;
1840                checkout_from_requirements (option);
1841              }
1842            else
1843              {
1844                if (option == "-R")
1845                  {
1846                    m_recursive = true;
1847                  }
1848                else if (option == "-l")
1849                  {
1850                    m_recursive = false;
1851                  }
1852                else if (option == "-r")
1853                  {
1854                    need_version_tag = true;
1855                    m_head = false;
1856                  }
1857                else if (option == "-d")
1858                  {
1859                    need_checkout_dir = true;
1860                  }
1861                else if (option == "-o")
1862                  {
1863                    need_offset = true;
1864                  }
1865                else if (option == "-n")
1866                  {
1867                    m_simulation = true;
1868                  }
1869                else if (option == "-v")
1870                  {
1871                    m_verbose = true;
1872                  }
1873                else if (option == "-branch")
1874                  {
1875                    need_branch_suffix = true;
1876                  }
1877                else if (option == "-requirements")
1878                  {
1879                    need_requirements_file = true;
1880                  }
1881                else if (option == "--help")
1882                  {
1883                    help ();
1884                    return;
1885                  }
1886                else if (option[0] == '-')
1887                  {
1888                    help ();
1889                    return;
1890                  }
1891                else
1892                  {
1893                    do_checkout (option, version_tag);
1894                  }
1895              }
1896          }
1897
1898      }
1899
1900private:
1901
1902  bool m_recursive;
1903  bool m_head;
1904  bool m_cmtcvstest;
1905  bool m_verbose;
1906  bool m_simulation;
1907
1908  cmt_string m_home_dir;
1909  cmt_string m_checkout_dir;
1910  cmt_string m_offset;
1911  cmt_string m_branch_suffix;
1912
1913  cmt_string m_last_module;
1914  cmt_string m_last_cvs_infos;
1915  cmt_string error_info;
1916  cmt_string tags_top_info;
1917  cmt_string tags_info;
1918  cmt_string cvsversions_top_info;
1919  cmt_string cvsversions_info;
1920  cmt_string branches_info;
1921  cmt_string subpackages_info;
1922};
1923
1924//--------------------------------------------------------------------
1925
1926void Grep::begin ()
1927{
1928  m_result = "";
1929}
1930
1931void Grep::filter (const cmt_string& line)
1932{
1933    //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "Grep::filter" << endl;
1934
1935  if (m_result != "") m_result += " ";
1936  m_result += line;
1937}
1938
1939const cmt_string& Grep::result () const
1940{
1941  return (m_result);
1942}
1943
1944//--------------------------------------------------------------------
1945
1946Cut::Cut (int field)
1947{
1948  m_field = field;
1949}
1950
1951void Cut::begin ()
1952{
1953    //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "Cut::begin" << endl;
1954  m_result = "";
1955}
1956
1957void Cut::filter (const cmt_string& line)
1958{
1959    //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "Cut::filter" << endl;
1960
1961  static CmtSystem::cmt_string_vector words;
1962 
1963  CmtSystem::split (line, " \t", words);
1964 
1965  if (words.size () <= m_field) return;
1966 
1967  if (m_result != "") m_result += " ";
1968  m_result += words[m_field];
1969}
1970
1971const cmt_string& Cut::result () const
1972{
1973  return (m_result);
1974}
1975
1976//--------------------------------------------------------------------
1977//--------------------------------------------------------------------
1978
1979History& History::instance ()
1980{
1981  static History h;
1982  return (h);
1983}
1984
1985void History::clear ()
1986{
1987  m_installed = "";
1988}
1989
1990void History::install (const cmt_string& line)
1991{
1992  m_installed += "|";
1993  m_installed += line;
1994  m_installed += "|";
1995}
1996
1997bool History::is_installed (const cmt_string& line)
1998{
1999  if (m_installed.find (line) != cmt_string::npos)
2000    {
2001      return (true);
2002    }
2003 
2004  return (false);
2005}
2006
2007History::History ()
2008{
2009}
2010
2011
2012//--------------------------------------------------------------------
2013
2014void RecursivePass1::begin ()
2015{
2016  m_first = true;
2017  m_result = "";
2018}
2019
2020void RecursivePass1::filter (const cmt_string& line)
2021{
2022    //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "RecursivePass1::filter> "
2023    //                                          << "line=[" << line << "]" << endl;
2024
2025  if (line.find ("use CMT") != cmt_string::npos) return;
2026  if (line.find ("use cmt") != cmt_string::npos) return;
2027 
2028  History& h = History::instance ();
2029 
2030  if (h.is_installed (line)) return;
2031 
2032  CmtSystem::cmt_string_vector words;
2033 
2034  CmtSystem::split (line, " \t", words);
2035
2036  enum
2037  {
2038    need_package,
2039    need_version,
2040    need_path,
2041    no_need
2042  } state = need_package;
2043
2044  cmt_string package;
2045  cmt_string version;
2046  cmt_string path;
2047
2048  for (int i = 1; i < words.size (); i++)
2049    {
2050      const cmt_string& s = words[i];
2051
2052      if (s[0] == '-') continue;
2053
2054      switch (state)
2055        {
2056          case need_package:
2057            package = s;
2058            state = need_version;
2059            break;
2060          case need_version:
2061            version = s;
2062            state = need_path;
2063            break;
2064          case need_path:
2065            path = s;
2066            state = no_need;
2067            break;
2068        }
2069    }
2070 
2071  if (version.find ("*") != cmt_string::npos)
2072    {
2073        /*
2074      cout << "# ================= Package " << package
2075           << " version " << version << " " << path
2076           << " has wild cards and will not be considered." << endl;
2077        */
2078      return;
2079    }
2080
2081  /**
2082   *  At the first pass, we simply accumulate the not-yet handled
2083   *  use statements.
2084   */
2085 
2086  m_result += line;
2087  m_result += "\n";
2088 
2089  if (m_first)
2090    {
2091      m_first = false;
2092      cout << "  # --> now propagate cmt checkout to :" << endl;
2093    }
2094 
2095  cout << "  #     " << package << " " << version << " " << path << endl;
2096}
2097
2098const cmt_string& RecursivePass1::result () const
2099{
2100  return (m_result);
2101}
2102
2103//--------------------------------------------------------------------
2104
2105RecursivePass2::RecursivePass2 (CvsImplementation& cvs) : m_cvs (cvs)
2106{
2107}
2108
2109void RecursivePass2::begin ()
2110{
2111}
2112
2113void RecursivePass2::filter (const cmt_string& line)
2114{
2115    //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "RecursivePass2::filter> "
2116    //                                          << "line=[" << line << "]" << endl;
2117
2118  /**
2119   *   At the second pass, the lines are really handled. Thus
2120   *   the lines are stored into m_installed so as to avoid
2121   *   later on re-installation.
2122   */
2123 
2124  History& h = History::instance ();
2125 
2126  if (h.is_installed (line)) return;
2127 
2128  h.install (line);
2129 
2130  CmtSystem::cmt_string_vector words;
2131 
2132  CmtSystem::split (line, " \t", words);
2133
2134  enum
2135  {
2136    need_package,
2137    need_version,
2138    need_path,
2139    no_need
2140  } state = need_package;
2141
2142  cmt_string package;
2143  cmt_string version;
2144  cmt_string path;
2145
2146  for (int i = 1; i < words.size (); i++)
2147    {
2148      const cmt_string& s = words[i];
2149
2150      if (s[0] == '-') continue;
2151
2152      switch (state)
2153        {
2154          case need_package:
2155            package = s;
2156            state = need_version;
2157            break;
2158          case need_version:
2159            version = s;
2160            state = need_path;
2161            break;
2162          case need_path:
2163            path = s;
2164            state = no_need;
2165            break;
2166        }
2167    }
2168
2169  if (version.find ("*") != cmt_string::npos)
2170    {
2171        /*
2172      cout << "# ================= Package " << package
2173           << " version " << version << " " << path
2174           << " has wild cards and will not be considered." << endl;
2175        */
2176    }
2177  else
2178    {
2179      m_cvs.checkout_package (path, package, version);
2180    }
2181}
2182
2183//--------------------------------------------------------------------
2184
2185void Cvs::tags (const CmtSystem::cmt_string_vector& arguments)
2186{
2187  CvsImplementation cvs;
2188
2189  cvs.tags (arguments);
2190}
2191
2192void Cvs::branches (const cmt_string& module)
2193{
2194  CvsImplementation cvs;
2195
2196  cvs.branches (module);
2197}
2198
2199void Cvs::subpackages (const cmt_string& module)
2200{
2201  CvsImplementation cvs;
2202
2203  cvs.subpackages (module);
2204}
2205
2206void Cvs::checkout (const CmtSystem::cmt_string_vector& arguments)
2207{
2208  CvsImplementation cvs;
2209
2210  cvs.checkout (arguments);
2211}
2212
Note: See TracBrowser for help on using the repository browser.