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

Last change on this file since 409 was 409, checked in by arnault, 17 years ago

First installation in SVN

Fix a bug in check_newer
CL 5

File size: 16.1 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 requirements file is considered first
178      #   o then any other file in the top directory
179      #
180    */
181
182  StructureType result = in_project;
183
184  cmt_string test_file;
185
186  bool found = false;
187
188  get_cvsroot (test_file);
189
190  test_file += CmtSystem::file_separator ();
191  test_file += module;
192  test_file += CmtSystem::file_separator ();
193  test_file += "cmt";
194  test_file += CmtSystem::file_separator ();
195  test_file += "project.cmt,v";
196
197  found = CmtSystem::test_file (test_file);
198
199  if (!found)
200    {
201      // not a CMT project
202      // try it as a CMT package with cmt directory
203 
204      result = in_package;
205
206      get_cvsroot (test_file);
207      test_file += CmtSystem::file_separator ();
208      test_file += module;
209      test_file += CmtSystem::file_separator ();
210      test_file += "cmt";
211      test_file += CmtSystem::file_separator ();
212      test_file += "requirements,v";
213   
214      found = CmtSystem::test_file (test_file);
215    }
216
217  if (!found)
218    {
219      // try it as a CMT package with mgr directory
220
221      get_cvsroot (test_file);
222      test_file += CmtSystem::file_separator ();
223      test_file += module;
224      test_file += CmtSystem::file_separator ();
225      test_file += "mgr";
226      test_file += CmtSystem::file_separator ();
227      test_file += "requirements,v";
228       
229      found = CmtSystem::test_file (test_file);
230    }
231
232  if (!found)
233    {
234      // try it as a CMT package with cmt directory but in Attic
235
236      get_cvsroot (test_file);
237      test_file += CmtSystem::file_separator ();
238      test_file += module;
239      test_file += CmtSystem::file_separator ();
240      test_file += "cmt";
241      test_file += CmtSystem::file_separator ();
242      test_file += "Attic";
243      test_file += CmtSystem::file_separator ();
244      test_file += "requirements,v";
245       
246      found = CmtSystem::test_file (test_file);
247    }
248
249  if (!found)
250    {
251      // try it as an old SRT package (should be obsolete)
252
253      get_cvsroot (test_file);
254      test_file += CmtSystem::file_separator ();
255      test_file += module;
256      test_file += CmtSystem::file_separator ();
257      test_file += "PACKAGE,v";
258     
259      found = CmtSystem::test_file (test_file);
260    }
261
262  if (!found)
263    {
264      // Structure not recognized (should we take the first file?)
265      result = no_structure;
266      return (result);
267    }
268
269    /*
270#symbols
271#       v10:1.1.1.1
272#       v2:1.1.1.1
273#       v1r2:1.1.1.1
274#       v1r1:1.1.1.1
275#       v1:1.1.1.1
276#       cmt:1.1.1;
277#locks; strict;
278
279  #
280  # Then extract all tags from the file header
281  #  one line per tag :
282  #
283  #   <tag>:<cvs-version-id>
284  #
285    */
286
287  cmt_string top;
288 
289  cmt_string temp;
290  temp.read (test_file);
291  int pos = temp.find ("symbols");
292  temp.erase (0, pos + 7);
293  pos = temp.find ("locks");
294  temp.erase (pos);
295
296  //cerr << "temp=[" << temp << "]" << endl;
297
298  CmtSystem::cmt_string_vector words;
299  CmtSystem::split (temp, " \t\n", words);
300
301  int i;
302
303  CmtSystem::cmt_string_vector alltags;
304
305  for (i = 0; i < words.size (); i++)
306    {
307      const cmt_string& s = words[i];
308      CmtSystem::cmt_string_vector w;
309      CmtSystem::split (s, ".", w);
310      int n = w.size ();
311
312      //cerr << "level=" << n << endl;
313
314      if ((n == 2) ||
315          (n == 4) ||
316          (n == 6))
317        {
318          cmt_string& t = alltags.add ();
319          t = s;
320        }
321    }
322
323
324    /*#
325      #  Compute the most recent tag (using the cvs version ids)
326      #*/
327
328  for (i = 0; i < alltags.size (); ++i)
329    {
330      const cmt_string& s = alltags[i];
331      cmt_string tag = s;
332      pos = tag.find (":");
333      tag.erase (pos);
334      cmt_string v = s;
335      v.replace (";", "");
336      v.erase (0, pos+1);
337
338      //cerr << "s=" << s << " v=" << v << " top=" << top << endl;
339
340      if (check_newer (v, top))
341        {
342          //cerr << v << " plus recent que " << top << endl;
343          top = v;
344        }
345    }
346
347  // cerr << "topv=" << top << endl;
348
349  bool has_container = false;
350  bool has_package = false;
351 
352  //
353  //  Atlas specific behaviour which consists in detecting tags
354  //  with a pattern <package>-xxx
355  //
356 
357  for (i = 0; i < alltags.size (); ++i)
358    {
359      const cmt_string& s = alltags[i];
360
361      // Get the symbolic tag
362      cmt_string tag = s;
363      pos = tag.find (":");
364      if (pos == cmt_string::npos) continue;
365      tag.erase (pos);
366
367      // Analyze its structure
368      cmt_string name = tag;
369      pos = name.find ("-");
370      if (pos != cmt_string::npos)
371        {
372          name.erase (pos);
373        }
374
375      if (name == container)
376        {
377          has_container = true;
378        }
379      else if (name == package)
380        {
381          has_package = true;
382        }
383    }
384
385  /*#
386    #  Split the tag list into tags that have same cvs-version-id than
387    #  the top tag (tags_tops) and older ones (tags).
388    #*/
389 
390  toptags.clear ();
391  tags.clear ();
392  topcvsversions.clear ();
393  cvsversions.clear ();
394 
395  for (i = 0; i < alltags.size (); ++i)
396    {
397      static const cmt_string digits = "0123456789";
398 
399      const cmt_string& s = alltags[i];
400      cmt_string tag = s;
401      pos = tag.find (":");
402      tag.erase (pos);
403     
404      cmt_string v = s;
405      v.replace (";", "");
406      v.erase (0, pos+1);
407     
408      cmt_string fullv = s;
409      fullv.replace (";", "");
410     
411      cmt_string digit;
412      cmt_string name = tag;
413      pos = name.find ("-");
414      if (pos != cmt_string::npos)
415        {
416          digit = name[pos+1];
417          name.erase (pos);
418        }
419
420      //cout << "tag=" << tag << " name=" << name << " v=" << v << " package=" << package << endl;
421     
422      if (!has_package || ((name == package) && (digits.find (digit) != cmt_string::npos )))
423        {
424          if (v == top)
425            {
426              toptags.push_back (tag);
427              topcvsversions.push_back (fullv);
428            }
429          else
430            {
431              tags.push_back (tag);
432              cvsversions.push_back (fullv);
433            }
434        }
435    }
436
437  return (result);
438}
439
440//---------------------------------------------------------------------
441static cmt_string get_branches (const cmt_string& module)
442{
443  cmt_string result;
444
445  cmt_string dir;
446
447  get_cvsroot (dir);
448  dir += CmtSystem::file_separator ();
449  dir += module;
450
451  CmtSystem::cmt_string_vector files;
452  CmtSystem::scan_dir (dir, files);
453
454  for (int i = 0; i < files.size (); i++)
455    {
456      const cmt_string& branch = files[i];
457
458      if (!CmtSystem::test_directory (branch)) continue;
459
460      cmt_string t;
461
462      CmtSystem::basename (branch, t);
463
464      if (t == "Attic") continue;
465      if (t == "CVSROOT") continue;
466      if (t == "defunct.CVS") continue;
467      if (t == ".cmtcvsinfos") continue;
468      if (t == ".cmtcvsinfostest") continue;
469      if (t == ".cmtcvstest") continue;
470
471      t = branch;
472      t += CmtSystem::file_separator ();
473      t += "cmt";
474      t += CmtSystem::file_separator ();
475      t += "requirements,v";
476      if (CmtSystem::test_file (t)) continue;
477
478      t = branch;
479      t += CmtSystem::file_separator ();
480      t += "mgr";
481      t += CmtSystem::file_separator ();
482      t += "requirements,v";
483         
484      if (CmtSystem::test_file (t)) continue;
485
486      t = branch;
487      t += CmtSystem::file_separator ();
488      t += "cmt";
489      t += CmtSystem::file_separator ();
490      t += "project.cmt,v";
491
492      if (CmtSystem::test_file (t)) continue;
493
494      CmtSystem::basename (branch, t);
495
496      if (result != "") result += " ";
497      result += t;
498    }
499
500  return (result);
501}
502
503//---------------------------------------------------------------------
504static cmt_string get_subpackages (const cmt_string& module)
505{
506  cmt_string result;
507
508  cmt_string dir;
509
510  get_cvsroot (dir);
511  dir += CmtSystem::file_separator ();
512  dir += module;
513
514  CmtSystem::cmt_string_vector files;
515  CmtSystem::scan_dir (dir, files);
516
517  for (int i = 0; i < files.size (); i++)
518    {
519      const cmt_string& subpackage = files[i];
520
521      if (!CmtSystem::test_directory (subpackage)) continue;
522
523      cmt_string t;
524
525      CmtSystem::basename (subpackage, t);
526
527      if (t == "Attic") continue;
528
529      t = subpackage;
530      t += CmtSystem::file_separator ();
531      t += "cmt";
532      t += CmtSystem::file_separator ();
533      t += "requirements,v";
534      if (CmtSystem::test_file (t))
535        {
536          CmtSystem::basename (subpackage, t);
537
538          if (result != "") result += " ";
539          result += t;
540        }
541      else
542        {
543          t = subpackage;
544          t += CmtSystem::file_separator ();
545          t += "mgr";
546          t += CmtSystem::file_separator ();
547          t += "requirements,v";
548         
549          if (CmtSystem::test_file (t))
550            {
551              CmtSystem::basename (subpackage, t);
552
553              if (result != "") result += " ";
554              result += t;
555            }
556        }
557    }
558
559  return (result);
560}
561
562//---------------------------------------------------------------------
563static cmt_string get_subprojects (const cmt_string& module)
564{
565  cmt_string result;
566
567  cmt_string dir;
568
569  get_cvsroot (dir);
570  dir += CmtSystem::file_separator ();
571  dir += module;
572
573  CmtSystem::cmt_string_vector files;
574  CmtSystem::scan_dir (dir, files);
575
576  for (int i = 0; i < files.size (); i++)
577    {
578      const cmt_string& subproject = files[i];
579
580      if (!CmtSystem::test_directory (subproject)) continue;
581
582      cmt_string t;
583
584      CmtSystem::basename (subproject, t);
585
586      if (t == "Attic") continue;
587
588      t = subproject;
589      t += CmtSystem::file_separator ();
590      t += "cmt";
591      t += CmtSystem::file_separator ();
592      t += "project.cmt,v";
593      if (CmtSystem::test_file (t))
594        {
595          CmtSystem::basename (subproject, t);
596
597          if (result != "") result += " ";
598          result += t;
599        }
600    }
601
602  return (result);
603}
604
605#define V(v) #v
606
607//---------------------------------------------------------------------
608int main (int /*argc*/, char* argv[])
609{
610  clear_cmtcvsinfos ();
611
612  cmt_string module = argv[1];
613  int pos = module.find (" ");
614  if (pos != cmt_string::npos) module.erase (pos);
615
616  module.replace (".cmtcvsinfos/", "");
617
618  cout << "#VERSION=[" << VERSION << "]" << endl;
619
620  cmt_string version = VERSION;
621  version += "/";
622
623  pos = module.find (version);
624  if (pos == 0)
625    {
626      const cmt_string null = "";
627      module.replace (version, null);
628    }
629
630  pos = module.find (VERSION);
631  if (pos == 0)
632    {
633      module.replace (VERSION, "");
634    }
635
636  pos = module.find ("cmtcvstest/");
637  if (pos == 0)
638    {
639      module.replace ("cmtcvstest/", "");
640      cmtcvstest = true;
641        //cout << "cmtcvstest=true" << endl;
642    }
643
644  cout << "#module=[" << module << "]" << endl;
645
646  if (module == "")
647    {
648      module = ".";
649    }
650
651  cmt_string tags;
652  cmt_string tags_top;
653  cmt_string cvsversions;
654  cmt_string cvsversions_top;
655
656  cmt_string dir;
657  get_cvsroot (dir);
658  dir += CmtSystem::file_separator ();
659  dir += module;
660
661  cmt_string error;
662  StructureType structure = no_structure;
663
664    //cout << "dir=" << dir << endl;
665
666  if (CmtSystem::test_directory (dir))
667    {
668      CmtSystem::cmt_string_vector toptag_list;
669      CmtSystem::cmt_string_vector tag_list;
670      CmtSystem::cmt_string_vector topcvsversion_list;
671      CmtSystem::cmt_string_vector cvsversion_list;
672
673      structure = get_tags (module, 
674                            toptag_list, 
675                            tag_list, 
676                            topcvsversion_list, 
677                            cvsversion_list);
678
679      int i;
680
681      for (i = 0; i < toptag_list.size (); i++)
682        {
683          const cmt_string& s = toptag_list[i];
684          const cmt_string& v = topcvsversion_list[i];
685          if (tags_top != "") tags_top += " ";
686          tags_top += s;
687          if (cvsversions_top != "") cvsversions_top += " ";
688          cvsversions_top += v;
689        }
690
691      for (i = 0; i < tag_list.size (); i++)
692        {
693          const cmt_string& s = tag_list[i];
694          const cmt_string& v = cvsversion_list[i];
695          if (tags != "") tags += " ";
696          tags += s;
697          if (cvsversions != "") cvsversions += " ";
698          cvsversions += v;
699        }
700    }
701  else
702    {
703      error = "### Module ";
704      error += module;
705      error += " not found.";
706    }
707
708  cmt_string branches;
709  cmt_string subpackages;
710  cmt_string subprojects;
711
712  if (CmtSystem::test_directory (dir))
713    {
714      branches = get_branches (module);
715      subpackages = get_subpackages (module);
716      subprojects = get_subprojects (module);
717    }
718
719  if (error != "")
720    {
721      cout << "error=" << error << endl;
722    }
723
724  cmt_string structures[] = {"none", "project", "package"};
725
726  cout << "structure=" << structures[structure] << endl;
727  cout << "tags_top=" << tags_top << endl;
728  cout << "tags=" << tags << endl;
729  cout << "cvsversions_top=" << cvsversions_top << endl;
730  cout << "cvsversions=" << cvsversions << endl;
731  cout << "branches=" << branches << endl;
732  cout << "subpackages=" << subpackages << endl;
733  cout << "subprojects=" << subprojects << endl;
734
735  exit (1);
736}
Note: See TracBrowser for help on using the repository browser.