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