source: cmtcvs/HEAD/src/cmtcvs.cxx @ 439

Last change on this file since 439 was 439, checked in by rybkin, 16 years ago

See C.L. 7

File size: 16.7 KB
Line 
1
2#include <cmt_std.h>
3#include <cmt_string.h>
4#include <cmt_system.h>
5
6/*
7#---------------------------------------------------------------------
8#
9# This program should be installed within the loginfo file of CVS
10# using the following line :
11#
12# ...
13#.cmtcvsinfos (${CMTROOT}\cmtcvs\v1\VisualC\cmtcvs.exe %s)
14# ...
15#
16# and is used whenever one tries to import a module named .cmtcvsinfos/<module>
17#
18#---------------------------------------------------------------------
19*/
20
21
22//
23//  This global flag is set when the string "/cmtcvstest/" is found in
24//  the module argument. This can be used to change the default
25//  behaviour of this pluggin.
26//
27//   Eg. It can be used to experiment new features.
28//
29static bool cmtcvstest = false;
30
31//---------------------------------------------------------------------
32static cmt_string get_cvsroot (cmt_string& result)
33{
34    //echo ${CVSROOT} | sed -e 's#^:[^:]*:##'
35  CmtSystem::get_cvsroot (result);
36
37  int pos = result.find (":");
38  if (pos == 0)
39    {
40      pos = result.find (1, ":");
41      result.erase (0, pos+1);
42    }
43
44  return (result);
45}
46
47static void clear_cmtcvsinfos ()
48{
49  cmt_string dir;
50  get_cvsroot (dir);
51  dir += CmtSystem::file_separator ();
52  dir += ".cmtcvsinfos";
53 
54  CmtSystem::cmt_string_vector files;
55  CmtSystem::scan_dir (dir, files);
56 
57  for (int i = 0; i < files.size (); i++)
58    {
59      const cmt_string& f = files[i];
60      CmtSystem::remove_directory (f);
61    }
62}
63
64//---------------------------------------------------------------------
65static bool check_head (const cmt_string& head,
66                        const cmt_string& version)
67{
68  CmtSystem::cmt_string_vector hlist;
69  CmtSystem::cmt_string_vector vlist;
70
71  CmtSystem::split (head, " ", hlist);
72  CmtSystem::split (version, " ", vlist);
73
74  int nh = hlist.size ();
75    //int nv = vlist.size ();
76
77  for (int i = 0; i < nh; ++i)
78    {
79      const cmt_string& h = hlist[i];
80      const cmt_string& v = vlist[i];
81
82      if (h != v) return (false);
83    }
84
85  return (true);
86}
87
88//---------------------------------------------------------------------
89// Question: is v1 newer than v2?
90//
91static bool check_newer (const cmt_string& v1,
92                         const cmt_string& v2)
93{
94  if (v2 == "") return (true);
95  if (v1 == "") return (false);
96
97  CmtSystem::cmt_string_vector list1;
98  CmtSystem::cmt_string_vector list2;
99
100  CmtSystem::split (v1, ".", list1);
101  CmtSystem::split (v2, ".", list2);
102
103  int n1 = list1.size ();
104  int n2 = list2.size ();
105
106  //cerr << "checknewer v1=" << v1 << " v2=" << v2 << " n1=" << n1 << " n2=" << n2 << endl;
107
108  /*
109     v1 = a1.a2.a3.a4
110     v2 = b1.b2.b3
111
112     {i = 0.. min(n1,n2) | if (ai > bi) -> [v1 newer than v2] }  [1.2.5 vs 1.2.4]
113
114     then
115        if (n1 < n2} [v2 newer]     [1.2  vs 1.2.5]
116        if (n1 > n2) [v1 newer]     [1.2.5 vs 1.2]
117     
118  */
119 
120  for (int i = 0; i < n1; ++i)
121    {
122      if (i >= n2)
123        {
124          // cerr << "n1 > n2" << endl;
125          return (false);
126        }
127
128      const cmt_string& s1 = list1[i];
129      const cmt_string& s2 = list2[i];
130
131      int i1;
132      int i2;
133
134      i1 = atoi (s1.c_str ());
135      i2 = atoi (s2.c_str ());
136
137      //cerr << "    i1=" << i1 << " i2=" << i2 << endl;
138
139      if (i1 > i2) return (true); // v1 newer
140      if (i1 < i2) return (false); // v2 newer
141    }
142
143  // n2 > n1
144  // v2 newer
145
146  //cerr << "n2 > n1" << endl;
147
148  return (false);
149}
150
151typedef enum
152  {
153    no_structure,
154    in_project,
155    in_package
156  } StructureType;
157
158//---------------------------------------------------------------------
159static StructureType get_tags (const cmt_string& module,
160                               CmtSystem::cmt_string_vector& toptags,
161                               CmtSystem::cmt_string_vector& tags,
162                               CmtSystem::cmt_string_vector& topcvsversions,
163                               CmtSystem::cmt_string_vector& cvsversions)
164{
165  cmt_string package;
166  cmt_string container;
167
168  CmtSystem::basename (module, package);
169  CmtSystem::dirname (module, container);
170  CmtSystem::dirname (container, container);
171
172    //cout << "package=" << package << endl;
173    //cout << "container=" << container << endl;
174
175    /*
176      #  First figure out which test file will be used to retreive the tags
177      o consider ChangeLog in the top directory first
178      (as it is most likely changed when the module is tagged and, therefore,
179      its revision will allow us to distinguish between the trunk and branches)
180      #   o requirements file is considered first
181      #   o then any other file in the top directory
182      #
183    */
184
185  StructureType result (no_structure);
186
187  cmt_string proj_file;
188
189  get_cvsroot (proj_file);
190  proj_file += CmtSystem::file_separator ();
191  proj_file += module;
192  proj_file += CmtSystem::file_separator ();
193  proj_file += "cmt";
194  proj_file += CmtSystem::file_separator ();
195  proj_file += "project.cmt,v";
196
197  if (CmtSystem::test_file (proj_file))
198    {
199      result = in_project;
200    }
201  else
202    {
203      result = in_package;
204    }
205
206  cmt_string test_file;
207  bool found = false;
208
209  get_cvsroot (test_file);
210  test_file += CmtSystem::file_separator ();
211  test_file += module;
212  test_file += CmtSystem::file_separator ();
213  test_file += "ChangeLog,v";
214
215  found = CmtSystem::test_file (test_file);
216
217  if (!found && result == in_project)
218    {
219      test_file = proj_file;
220      found = true;
221    }
222
223  if (!found)
224    {
225      // not a CMT project
226      // try it as a CMT package with cmt directory
227 
228      result = in_package;
229
230      get_cvsroot (test_file);
231      test_file += CmtSystem::file_separator ();
232      test_file += module;
233      test_file += CmtSystem::file_separator ();
234      test_file += "cmt";
235      test_file += CmtSystem::file_separator ();
236      test_file += "requirements,v";
237   
238      found = CmtSystem::test_file (test_file);
239    }
240
241  if (!found)
242    {
243      // try it as a CMT package with mgr directory
244
245      get_cvsroot (test_file);
246      test_file += CmtSystem::file_separator ();
247      test_file += module;
248      test_file += CmtSystem::file_separator ();
249      test_file += "mgr";
250      test_file += CmtSystem::file_separator ();
251      test_file += "requirements,v";
252       
253      found = CmtSystem::test_file (test_file);
254    }
255
256  if (!found)
257    {
258      // try it as a CMT package with cmt directory but in Attic
259
260      get_cvsroot (test_file);
261      test_file += CmtSystem::file_separator ();
262      test_file += module;
263      test_file += CmtSystem::file_separator ();
264      test_file += "cmt";
265      test_file += CmtSystem::file_separator ();
266      test_file += "Attic";
267      test_file += CmtSystem::file_separator ();
268      test_file += "requirements,v";
269       
270      found = CmtSystem::test_file (test_file);
271    }
272
273  if (!found)
274    {
275      // try it as an old SRT package (should be obsolete)
276
277      get_cvsroot (test_file);
278      test_file += CmtSystem::file_separator ();
279      test_file += module;
280      test_file += CmtSystem::file_separator ();
281      test_file += "PACKAGE,v";
282     
283      found = CmtSystem::test_file (test_file);
284    }
285
286  if (!found)
287    {
288      // Structure not recognized (should we take the first file?)
289      result = no_structure;
290      return (result);
291    }
292
293    /*
294#symbols
295#       v10:1.1.1.1
296#       v2:1.1.1.1
297#       v1r2:1.1.1.1
298#       v1r1:1.1.1.1
299#       v1:1.1.1.1
300#       cmt:1.1.1;
301#locks; strict;
302
303  #
304  # Then extract all tags from the file header
305  #  one line per tag :
306  #
307  #   <tag>:<cvs-version-id>
308  #
309    */
310
311  cmt_string top;
312 
313  cmt_string temp;
314  temp.read (test_file);
315  int pos = temp.find ("symbols");
316  temp.erase (0, pos + 7);
317  pos = temp.find ("locks");
318  temp.erase (pos);
319
320  //cerr << "temp=[" << temp << "]" << endl;
321
322  CmtSystem::cmt_string_vector words;
323  CmtSystem::split (temp, " \t\n", words);
324
325  int i;
326
327  CmtSystem::cmt_string_vector alltags;
328
329  for (i = 0; i < words.size (); i++)
330    {
331      const cmt_string& s = words[i];
332      CmtSystem::cmt_string_vector w;
333      CmtSystem::split (s, ".", w);
334      int n = w.size ();
335
336      //cerr << "level=" << n << endl;
337
338      if ((n == 2) ||
339          (n == 4) ||
340          (n == 6))
341        {
342          cmt_string& t = alltags.add ();
343          t = s;
344        }
345    }
346
347
348    /*#
349      #  Compute the most recent tag (using the cvs version ids)
350      #*/
351
352  for (i = 0; i < alltags.size (); ++i)
353    {
354      const cmt_string& s = alltags[i];
355      cmt_string tag = s;
356      pos = tag.find (":");
357      tag.erase (pos);
358      cmt_string v = s;
359      v.replace (";", "");
360      v.erase (0, pos+1);
361
362      //cerr << "s=" << s << " v=" << v << " top=" << top << endl;
363
364      if (check_newer (v, top))
365        {
366          //cerr << v << " plus recent que " << top << endl;
367          top = v;
368        }
369    }
370
371  // cerr << "topv=" << top << endl;
372
373  bool has_container = false;
374  bool has_package = false;
375 
376  //
377  //  Atlas specific behaviour which consists in detecting tags
378  //  with a pattern <package>-xxx
379  //
380 
381  for (i = 0; i < alltags.size (); ++i)
382    {
383      const cmt_string& s = alltags[i];
384
385      // Get the symbolic tag
386      cmt_string tag = s;
387      pos = tag.find (":");
388      if (pos == cmt_string::npos) continue;
389      tag.erase (pos);
390
391      // Analyze its structure
392      cmt_string name = tag;
393      pos = name.find ("-");
394      if (pos != cmt_string::npos)
395        {
396          name.erase (pos);
397        }
398
399      if (name == container)
400        {
401          has_container = true;
402        }
403      else if (name == package)
404        {
405          has_package = true;
406        }
407    }
408
409  /*#
410    #  Split the tag list into tags that have same cvs-version-id than
411    #  the top tag (tags_tops) and older ones (tags).
412    #*/
413 
414  toptags.clear ();
415  tags.clear ();
416  topcvsversions.clear ();
417  cvsversions.clear ();
418 
419  for (i = 0; i < alltags.size (); ++i)
420    {
421      static const cmt_string digits = "0123456789";
422 
423      const cmt_string& s = alltags[i];
424      cmt_string tag = s;
425      pos = tag.find (":");
426      tag.erase (pos);
427     
428      cmt_string v = s;
429      v.replace (";", "");
430      v.erase (0, pos+1);
431     
432      cmt_string fullv = s;
433      fullv.replace (";", "");
434     
435      cmt_string digit;
436      cmt_string name = tag;
437      pos = name.find ("-");
438      if (pos != cmt_string::npos)
439        {
440          digit = name[pos+1];
441          name.erase (pos);
442        }
443
444      //cout << "tag=" << tag << " name=" << name << " v=" << v << " package=" << package << endl;
445     
446      if (!has_package || ((name == package) && (digits.find (digit) != cmt_string::npos )))
447        {
448          if (v == top)
449            {
450              toptags.push_back (tag);
451              topcvsversions.push_back (fullv);
452            }
453          else
454            {
455              tags.push_back (tag);
456              cvsversions.push_back (fullv);
457            }
458        }
459    }
460
461  return (result);
462}
463
464//---------------------------------------------------------------------
465static cmt_string get_branches (const cmt_string& module)
466{
467  cmt_string result;
468
469  cmt_string dir;
470
471  get_cvsroot (dir);
472  dir += CmtSystem::file_separator ();
473  dir += module;
474
475  CmtSystem::cmt_string_vector files;
476  CmtSystem::scan_dir (dir, files);
477
478  for (int i = 0; i < files.size (); i++)
479    {
480      const cmt_string& branch = files[i];
481
482      if (!CmtSystem::test_directory (branch)) continue;
483
484      cmt_string t;
485
486      CmtSystem::basename (branch, t);
487
488      if (t == "Attic") continue;
489      if (t == "CVSROOT") continue;
490      if (t == "defunct.CVS") continue;
491      if (t == ".cmtcvsinfos") continue;
492      if (t == ".cmtcvsinfostest") continue;
493      if (t == ".cmtcvstest") continue;
494
495      t = branch;
496      t += CmtSystem::file_separator ();
497      t += "cmt";
498      t += CmtSystem::file_separator ();
499      t += "requirements,v";
500      if (CmtSystem::test_file (t)) continue;
501
502      t = branch;
503      t += CmtSystem::file_separator ();
504      t += "mgr";
505      t += CmtSystem::file_separator ();
506      t += "requirements,v";
507         
508      if (CmtSystem::test_file (t)) continue;
509
510      t = branch;
511      t += CmtSystem::file_separator ();
512      t += "cmt";
513      t += CmtSystem::file_separator ();
514      t += "project.cmt,v";
515
516      if (CmtSystem::test_file (t)) continue;
517
518      CmtSystem::basename (branch, t);
519
520      if (result != "") result += " ";
521      result += t;
522    }
523
524  return (result);
525}
526
527//---------------------------------------------------------------------
528static cmt_string get_subpackages (const cmt_string& module)
529{
530  cmt_string result;
531
532  cmt_string dir;
533
534  get_cvsroot (dir);
535  dir += CmtSystem::file_separator ();
536  dir += module;
537
538  CmtSystem::cmt_string_vector files;
539  CmtSystem::scan_dir (dir, files);
540
541  for (int i = 0; i < files.size (); i++)
542    {
543      const cmt_string& subpackage = files[i];
544
545      if (!CmtSystem::test_directory (subpackage)) continue;
546
547      cmt_string t;
548
549      CmtSystem::basename (subpackage, t);
550
551      if (t == "Attic") continue;
552
553      t = subpackage;
554      t += CmtSystem::file_separator ();
555      t += "cmt";
556      t += CmtSystem::file_separator ();
557      t += "requirements,v";
558      if (CmtSystem::test_file (t))
559        {
560          CmtSystem::basename (subpackage, t);
561
562          if (result != "") result += " ";
563          result += t;
564        }
565      else
566        {
567          t = subpackage;
568          t += CmtSystem::file_separator ();
569          t += "mgr";
570          t += CmtSystem::file_separator ();
571          t += "requirements,v";
572         
573          if (CmtSystem::test_file (t))
574            {
575              CmtSystem::basename (subpackage, t);
576
577              if (result != "") result += " ";
578              result += t;
579            }
580        }
581    }
582
583  return (result);
584}
585
586//---------------------------------------------------------------------
587static cmt_string get_subprojects (const cmt_string& module)
588{
589  cmt_string result;
590
591  cmt_string dir;
592
593  get_cvsroot (dir);
594  dir += CmtSystem::file_separator ();
595  dir += module;
596
597  CmtSystem::cmt_string_vector files;
598  CmtSystem::scan_dir (dir, files);
599
600  for (int i = 0; i < files.size (); i++)
601    {
602      const cmt_string& subproject = files[i];
603
604      if (!CmtSystem::test_directory (subproject)) continue;
605
606      cmt_string t;
607
608      CmtSystem::basename (subproject, t);
609
610      if (t == "Attic") continue;
611
612      t = subproject;
613      t += CmtSystem::file_separator ();
614      t += "cmt";
615      t += CmtSystem::file_separator ();
616      t += "project.cmt,v";
617      if (CmtSystem::test_file (t))
618        {
619          CmtSystem::basename (subproject, t);
620
621          if (result != "") result += " ";
622          result += t;
623        }
624    }
625
626  return (result);
627}
628
629#define V(v) #v
630
631//---------------------------------------------------------------------
632int main (int /*argc*/, char* argv[])
633{
634  clear_cmtcvsinfos ();
635
636  cmt_string module = argv[1];
637  int pos = module.find (" ");
638  if (pos != cmt_string::npos) module.erase (pos);
639
640  module.replace (".cmtcvsinfos/", "");
641
642  cout << "#VERSION=[" << VERSION << "]" << endl;
643
644  cmt_string version = VERSION;
645  version += "/";
646
647  pos = module.find (version);
648  if (pos == 0)
649    {
650      const cmt_string null = "";
651      module.replace (version, null);
652    }
653
654  pos = module.find (VERSION);
655  if (pos == 0)
656    {
657      module.replace (VERSION, "");
658    }
659
660  pos = module.find ("cmtcvstest/");
661  if (pos == 0)
662    {
663      module.replace ("cmtcvstest/", "");
664      cmtcvstest = true;
665        //cout << "cmtcvstest=true" << endl;
666    }
667
668  cout << "#module=[" << module << "]" << endl;
669
670  if (module == "")
671    {
672      module = ".";
673    }
674
675  cmt_string tags;
676  cmt_string tags_top;
677  cmt_string cvsversions;
678  cmt_string cvsversions_top;
679
680  cmt_string dir;
681  get_cvsroot (dir);
682  dir += CmtSystem::file_separator ();
683  dir += module;
684
685  cmt_string error;
686  StructureType structure = no_structure;
687
688    //cout << "dir=" << dir << endl;
689
690  if (CmtSystem::test_directory (dir))
691    {
692      CmtSystem::cmt_string_vector toptag_list;
693      CmtSystem::cmt_string_vector tag_list;
694      CmtSystem::cmt_string_vector topcvsversion_list;
695      CmtSystem::cmt_string_vector cvsversion_list;
696
697      structure = get_tags (module, 
698                            toptag_list, 
699                            tag_list, 
700                            topcvsversion_list, 
701                            cvsversion_list);
702
703      int i;
704
705      for (i = 0; i < toptag_list.size (); i++)
706        {
707          const cmt_string& s = toptag_list[i];
708          const cmt_string& v = topcvsversion_list[i];
709          if (tags_top != "") tags_top += " ";
710          tags_top += s;
711          if (cvsversions_top != "") cvsversions_top += " ";
712          cvsversions_top += v;
713        }
714
715      for (i = 0; i < tag_list.size (); i++)
716        {
717          const cmt_string& s = tag_list[i];
718          const cmt_string& v = cvsversion_list[i];
719          if (tags != "") tags += " ";
720          tags += s;
721          if (cvsversions != "") cvsversions += " ";
722          cvsversions += v;
723        }
724    }
725  else
726    {
727      error = "### Module ";
728      error += module;
729      error += " not found.";
730    }
731
732  cmt_string branches;
733  cmt_string subpackages;
734  cmt_string subprojects;
735
736  if (CmtSystem::test_directory (dir))
737    {
738      branches = get_branches (module);
739      subpackages = get_subpackages (module);
740      subprojects = get_subprojects (module);
741    }
742
743  if (error != "")
744    {
745      cout << "error=" << error << endl;
746    }
747
748  cmt_string structures[] = {"none", "project", "package"};
749
750  cout << "structure=" << structures[structure] << endl;
751  cout << "tags_top=" << tags_top << endl;
752  cout << "tags=" << tags << endl;
753  cout << "cvsversions_top=" << cvsversions_top << endl;
754  cout << "cvsversions=" << cvsversions << endl;
755  cout << "branches=" << branches << endl;
756  cout << "subpackages=" << subpackages << endl;
757  cout << "subprojects=" << subprojects << endl;
758
759  exit (1);
760}
Note: See TracBrowser for help on using the repository browser.