Changeset 36


Ignore:
Timestamp:
Apr 13, 2005, 11:41:50 AM (19 years ago)
Author:
arnault
Message:

Fix bug in project hierarchy. See CL 265

Location:
CMT/HEAD
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • CMT/HEAD/ChangeLog

    r33 r36  
     12005-04-12  Christian Arnault  <arnault@lal.in2p3.fr> 265
     2
     3        * source/cmt_project.cxx (create_project): Restructure the
     4        algorithm for detection of roject structuring cases. Construct a
     5        finite list of cases.
     6        (has_parent): Implement recursive query function
     7        (has_child): Implement recursive query function
     8        (add_parent, add_child): Use the recursive detection to avoid cycles.
     9
     10        * source/cmt_project.h (class Project): Add has_parent and
     11        has_child functions to protect against recursive cycles
     12
    1132005-04-02  Christian Arnault  <arnault@lal.in2p3.fr> 264
    214
  • CMT/HEAD/source/cmt_project.cxx

    r24 r36  
    9595}
    9696
    97 static bool get_release_from_path (const cmt_string& path, const cmt_string& name, cmt_string& release)
     97static bool get_release_from_path (const CmtSystem::cmt_string_vector& items,
     98                                   const cmt_string& path,
     99                                   const cmt_string& name,
     100                                   cmt_string& real_name,
     101                                   cmt_string& release)
    98102{
    99103  bool result = false;
    100104
    101105  release = "";
     106  real_name = "";
    102107
    103108  cmt_string p = path;
    104109
     110  if ((items.size () == 0) && (name == ""))
     111    {
     112      // There is no CMTPROJECTPATH and no expected project name.
     113      // We have no way to find a project structure
     114      // So we only expect a 2-level structure.
     115
     116      CmtSystem::basename (p, release);
     117      CmtSystem::dirname (p, p);
     118      CmtSystem::basename (p, real_name);
     119     
     120      return (false);
     121    }
     122
    105123  for (;;)
    106124    {
     125      if (p == "")
     126        {
     127          // Protection: we found no matching project name
     128          // and path was outside any CMTPROJECTPATH
     129
     130          p = path;
     131
     132          CmtSystem::basename (p, release);
     133          CmtSystem::dirname (p, p);
     134          CmtSystem::basename (p, real_name);
     135
     136          return (false);
     137        }
     138
    107139      cmt_string n;
    108140
     
    112144      if (n == name)
    113145        {
     146          real_name = name;
    114147          result = true;
    115148          break;
     149        }
     150
     151      CmtSystem::basename (p, real_name);
     152
     153      for (int i = 0; i < items.size (); i++)
     154        {
     155          const cmt_string& item = items[i];
     156          if (p == item)
     157            {
     158              // We have reached an item of CMTPROJECTPATH, no need to continue
     159              return (false);
     160            }
    116161        }
    117162
     
    153198  bool specify_name = (specified_name != "");
    154199
    155   //cerr << "Creating project " << path << " with parent " << ((parent==0)? "0" : parent->get_name ()) << endl;
     200  if (Cmt::get_debug ())
     201    {
     202      cout << "Creating project " << path << " with parent " << ((parent==0)? "0" : parent->get_name ()) << endl;
     203      Project::show_all ();
     204    }
     205
     206  cmt_string sep;
     207  sep = CmtSystem::path_separator ();
     208
     209  cmt_string cmtprojectpath = CmtSystem::getenv ("CMTPROJECTPATH");
     210  CmtSystem::cmt_string_vector items;
     211  CmtSystem::split (cmtprojectpath, sep, items);
    156212
    157213  static Project::ProjectVector& Projects = Project::projects ();
     
    166222        {
    167223          cmt_string r;
    168 
    169           get_release_from_path (compressed_path, p.get_name (), r);
     224          cmt_string n;
     225
     226          get_release_from_path (items, compressed_path, p.get_name (), n, r);
    170227
    171228          if (r != p.get_release ())
    172229            {
    173               cerr << "#CMT> Project " << p.get_name () << " requested with conflicting releases " << p.get_release () << " and " << r << endl;
     230              cerr << "#CMT> Project " << p.get_name ()
     231                   << " requested with conflicting releases " << p.get_release () << " and " << r << endl;
    174232              CmtError::set (CmtError::project_release_conflict, p.get_name ());
    175233            }
     
    199257
    200258  cmt_string name = specified_name;
     259  cmt_string project_name;
    201260  cmt_string release;
    202261
     
    213272       or does not specify the project name
    214273   */
     274  bool has_project_file = false;
     275
    215276  if (CmtSystem::cd ("cmt") && CmtSystem::test_file (Project::get_project_file_name ()))
    216277    {
     278      has_project_file = true;
    217279      text.read (Project::get_project_file_name ());
    218280
     
    221283      reader.run (text);
    222284
    223       name = reader.get_project_name ();
    224       if (name == "")
    225         {
    226           if (!specify_name)
    227             {
    228               // The project is neither specified from the caller nor from the project file
    229               // Send a warning?
    230               // How can we guess it?
    231               // For the moment, assume /name/release/ structure where release is one level only
     285      project_name = reader.get_project_name ();
     286    }
     287
     288  enum
     289    {
     290      without_project_file   = 0x01,
     291      with_project_file      = 0x02,
     292      without_project_name   = 0x04,
     293      with_project_name      = 0x08,
     294      without_specified_name = 0x10,
     295      with_specified_name    = 0x20,
     296      names_mismatch         = 0x40,
     297      names_match            = 0x80
     298    };
     299
     300  int status = ((has_project_file) ? with_project_file : without_project_file) |
     301    ((has_project_file && (project_name != "")) ? with_project_name : without_project_name) |
     302    ((specify_name) ? with_specified_name : without_specified_name) |
     303    ((specify_name && has_project_file && (project_name == specified_name)) ? names_match : names_mismatch);
     304
     305  if (source == "default path")
     306    {
     307      name = "CMT";
     308    }
     309  else
     310    {
     311      cmt_string n;
     312         
     313      switch (status)
     314        {
     315        case with_project_file | without_project_name | without_specified_name | names_mismatch:
     316
     317          // The project is neither specified from the caller nor from the project file
     318
     319          /*
     320            if (!Cmt::get_quiet ())
     321            {
     322            cerr << "#CMT> Warning: project name unspecified in project file." << endl;
     323            }
     324          */
     325     
     326          get_release_from_path (items, compressed_path, "", name, release);
     327
     328          break;
     329         
     330        case with_project_file | without_project_name | with_specified_name | names_mismatch:
     331         
     332          // The name is only specified from the caller
     333          // find this specified name in the path
     334         
     335          if (get_release_from_path (items, compressed_path, specified_name, name, release))
     336            {
     337              // The specified name has been found from the path.
     338              // We believe in the release spec.
     339            }
     340          else
     341            {
     342              // The specified name is not in the path.
     343             
     344              if (!Cmt::get_quiet ())
     345                {
     346                  cerr << "#CMT> Warning: specified project name "
     347                       << specified_name
     348                       << " from the caller does not match path." << endl;
     349                }
     350            }
     351         
     352          break;
     353         
     354        case with_project_file | with_project_name | with_specified_name | names_match:
     355         
     356          // We have a double specification: from the caller and from the project file.
     357          // And both specifications are consistent. 
     358         
     359          if (get_release_from_path (items, compressed_path, specified_name, name, release))
     360            {
     361              // The specified name has been found from the path.
     362              // We believe in the release spec.
     363            }
     364          else
     365            {
     366              // The specified name is not in the path.
     367             
     368              if (!Cmt::get_quiet ())
     369                {
     370                  cerr << "#CMT> Warning: specified project name "
     371                       << specified_name
     372                       << " from project file and from caller does not match path." << endl;
     373                }
     374            }
     375         
     376          break;
     377         
     378        case with_project_file | with_project_name | with_specified_name | names_mismatch:
     379         
     380          // We have a double specification: from the caller and from the project file.
     381          // Specifications are inconsistent!!
     382         
     383          if (!Cmt::get_quiet ())
     384            {
     385              cerr << "#CMT> Warning: specified project name "
     386                   << specified_name
     387                   << " inconsistent with name "
     388                   << project_name
     389                   << " from project file." << endl;
     390            }
     391         
     392          if (get_release_from_path (items, compressed_path, specified_name, n, release))
     393            {
     394              // name from caller wins.
     395            }
     396          else if (get_release_from_path (items, compressed_path, project_name, name, release))
     397            {
     398              // name from project file wins.
     399            }
     400          else
     401            {
     402              // The specified name is not in the path.
     403             
     404              if (!Cmt::get_quiet ())
     405                {
     406                  cerr << "#CMT> Warning: none of specified project names "
     407                       << specified_name
     408                       << " from graph and "
     409                       << project_name
     410                       << " from project file match path." << endl;
     411                }
     412            }
     413         
     414          break;
     415         
     416        case with_project_file | with_project_name | without_specified_name | names_mismatch:
     417         
     418          // Project name is specified in the project file but not from the caller.
     419         
     420          if (get_release_from_path (items, compressed_path, project_name, name, release))
     421            {
     422              // The specified name has been found from the path.
     423              // We believe in the release spec.
     424             
     425            }
     426          else
     427            {
     428              // The specified name is not in the path.
    232429
    233430              /*
    234431              if (!Cmt::get_quiet ())
    235432                {
    236                   cerr << "#CMT> Warning: project name unspecified in project file." << endl;
     433                  cerr << "#CMT> Warning: specified project name "
     434                       << project_name
     435                       << " from project file does not match path." << endl;
    237436                }
    238437              */
    239 
    240               CmtSystem::basename (compressed_path, release);
    241               CmtSystem::dirname (compressed_path, name);
    242               CmtSystem::basename (name, name);
     438            }
     439         
     440          break;
     441         
     442        case without_project_file | without_project_name | without_specified_name | names_mismatch:
     443         
     444          // The project is not specified from the caller and there is no project file
     445          // This corresponds to the backward compatibility
     446          // For the moment, assume /name/release/ structure where release is one level only
     447         
     448          /*
     449            if (!Cmt::get_quiet ())
     450            {
     451            cerr << "#CMT> Warning: project name is not specified "
     452            << " (no project file)." << endl;
     453            }
     454          */
     455         
     456          CmtSystem::basename (compressed_path, release);
     457          CmtSystem::dirname (compressed_path, name);
     458          CmtSystem::basename (name, name);
     459         
     460          break;
     461         
     462        case without_project_file | without_project_name | with_specified_name | names_mismatch:
     463         
     464          // The name is only specified from the caller
     465          // find this specified name in the path
     466         
     467          if (get_release_from_path (items, compressed_path, specified_name, name, release))
     468            {
     469              // The specified name has been found from the path.
     470              // We believe in the release spec.
    243471            }
    244472          else
    245473            {
    246               // The name is specified from the caller
    247               // find this specified name in the path
    248 
    249               cmt_string r;
    250 
    251               if (get_release_from_path (compressed_path, specified_name, r))
    252                 {
    253                   // The specified name has been found from the path.
    254                   // We believe in the release spec.
    255 
    256                   name = specified_name;
    257                   release = r;
    258                 }
    259               else
    260                 {
    261                   // The specified name is not in the path.
    262 
    263 
    264                   if (!Cmt::get_quiet ())
    265                     {
    266                       cerr << "#CMT> Warning: specified project name "
    267                            << specified_name
    268                            << " from project file does not match path." << endl;
    269                     }
    270 
    271                   CmtSystem::basename (compressed_path, release);
    272                   CmtSystem::dirname (compressed_path, name);
    273                   CmtSystem::basename (name, name);
    274                 }
    275             }
    276         }
    277       else
    278         {
    279           if (specify_name)
    280             {
    281               // We have a double specification: from the caller and from the project file.
    282               // check the consistency
    283 
    284               if (name == specified_name)
    285                 {
    286                   // Both specifications are consistent. 
    287                   cmt_string r;
    288 
    289                   if (get_release_from_path (compressed_path, specified_name, r))
    290                     {
    291                       // The specified name has been found from the path.
    292                       // We believe in the release spec.
    293 
    294                       name = specified_name;
    295                       release = r;
    296                     }
    297                   else
    298                     {
    299                       // The specified name is not in the path.
    300 
    301                       if (!Cmt::get_quiet ())
    302                         {
    303                           cerr << "#CMT> Warning: specified project name "
    304                                << specified_name
    305                                << " from project file does not match path." << endl;
    306                         }
    307 
    308                       CmtSystem::basename (compressed_path, release);
    309                       CmtSystem::dirname (compressed_path, name);
    310                       CmtSystem::basename (name, name);
    311                     }
    312                 }
    313               else
    314                 {
    315                   // Specifications from the caller and from the project files are inconsistent!!
    316 
    317                   if (!Cmt::get_quiet ())
    318                     {
    319                       cerr << "#CMT> Warning: specified project name "
    320                            << specified_name
    321                            << " inconsistent with name "
    322                            << name
    323                            << " from project file." << endl;
    324                     }
    325 
    326                   cmt_string r;
    327 
    328                   if (get_release_from_path (compressed_path, specified_name, r))
    329                     {
    330                       // name from caller wins.
    331                     }
    332                   else if (get_release_from_path (compressed_path, specified_name, r))
    333                     {
    334                       // name from project file wins.
    335                     }
    336                   else
    337                     {
    338                       // The specified name is not in the path.
    339 
    340                       if (!Cmt::get_quiet ())
    341                         {
    342                           cerr << "#CMT> Warning: none of specified project names "
    343                                << name
    344                                << " from graph and "
    345                                << specified_name
    346                                << " from project file match path." << endl;
    347                         }
    348 
    349                       CmtSystem::basename (compressed_path, release);
    350                       CmtSystem::dirname (compressed_path, name);
    351                       CmtSystem::basename (name, name);
    352                     }
    353                 }
    354             }
    355         }
    356     }
    357   else
    358     {
    359       // There is no project file in this path.
    360 
    361       if (source == "default path")
    362         {
    363           name = "CMT";
    364         }
    365       else
    366         {
    367           if (!specify_name)
    368             {
    369               // The project is not specified from the caller and there is no project file
    370               // Send a warning?
    371               // How can we guess it?
    372               // For the moment, assume /name/release/ structure where release is one level only
    373 
    374               /*
     474              // The specified name is not in the path.
     475             
    375476              if (!Cmt::get_quiet ())
    376477                {
    377                   cerr << "#CMT> Warning: project name is not specified "
    378                        << " (no project file)." << endl;
     478                  cerr << "#CMT> Warning: specified project name "
     479                       << specified_name
     480                       << " from project graph does not match path." << endl;
    379481                }
    380               */
    381 
    382               CmtSystem::basename (compressed_path, release);
    383               CmtSystem::dirname (compressed_path, name);
    384               CmtSystem::basename (name, name);
    385             }
    386           else
    387             {
    388               // The name is specified from the caller
    389               // find this specified name in the path
    390 
    391               cmt_string r;
    392 
    393               if (get_release_from_path (compressed_path, specified_name, r))
    394                 {
    395                   // The specified name has been found from the path.
    396                   // We believe in the release spec.
    397 
    398                   release = r;
    399                 }
    400               else
    401                 {
    402                   // The specified name is not in the path.
    403 
    404                   if (!Cmt::get_quiet ())
    405                     {
    406                       cerr << "#CMT> Warning: specified project name "
    407                            << specified_name
    408                            << " from project graph does not match path." << endl;
    409                     }
    410 
    411                   CmtSystem::basename (compressed_path, release);
    412                   CmtSystem::dirname (compressed_path, name);
    413                   CmtSystem::basename (name, name);
    414                 }
    415             }
     482            }
     483         
     484          break;
    416485        }
    417486    }
    418487
    419488  project = Project::add (name, release);
    420 
     489     
    421490  if (parent != 0)
    422491    {
     
    11221191
    11231192//----------------------------------------------------------
     1193bool Project::has_parent (Project* p) const
     1194{
     1195  if (p == 0) return (false);
     1196  if (p == this) return (false);
     1197
     1198  const cmt_string& name = p->get_name ();
     1199
     1200  int i;
     1201
     1202  for (i = 0; i < m_parents.size (); i++)
     1203    {
     1204      const Project* parent = m_parents[i];
     1205      if (parent == 0) continue;
     1206
     1207      if (parent->get_name () == name)
     1208        {
     1209          // registered as a parent
     1210          return (true);
     1211        }
     1212
     1213      if (parent->has_parent (p))
     1214        {
     1215          // recurse
     1216          return (true);
     1217        }
     1218    }
     1219
     1220  return (false);
     1221}
     1222
     1223//----------------------------------------------------------
     1224bool Project::has_child (Project* p) const
     1225{
     1226  if (p == 0) return (false);
     1227  if (p == this) return (false);
     1228
     1229  const cmt_string& name = p->get_name ();
     1230
     1231  int i;
     1232
     1233  for (i = 0; i < m_children.size (); i++)
     1234    {
     1235      const Project* child = m_children[i];
     1236      if (child == 0) continue;
     1237
     1238      if (child->get_name () == name)
     1239        {
     1240          // registered as a child
     1241          return (true);
     1242        }
     1243
     1244      if (child->has_child (p))
     1245        {
     1246          // recurse
     1247          return (true);
     1248        }
     1249    }
     1250
     1251  return (false);
     1252}
     1253
     1254//----------------------------------------------------------
    11241255void Project::add_parent (Project* p)
    11251256{
     
    11291260  //cerr << "Adding parent " << p->get_name () << " to " << m_name << endl;
    11301261
    1131   int i;
    1132 
    1133   for (i = 0; i < m_children.size (); i++)
    1134     {
    1135       Project* child = m_children[i];
    1136       if (child == 0) continue;
    1137 
    1138       if (child->get_name () == p->get_name ())
    1139         {
    1140           // Already registered as a child (no cycle permitted!!)
    1141           return;
    1142         }
    1143     }
    1144 
    1145   for (i = 0; i < m_parents.size (); i++)
    1146     {
    1147       Project* parent = m_parents[i];
    1148       if (parent == 0) continue;
    1149 
    1150       if (parent->get_name () == p->get_name ())
    1151         {
    1152           // Already registered as a parent
    1153           return;
    1154         }
    1155     }
     1262  if (has_child (p)) return;
     1263  if (has_parent (p)) return;
    11561264
    11571265  m_parents.push_back (p);
     
    11641272  if (p == this) return;
    11651273
    1166   int i;
    1167 
    1168   for (i = 0; i < m_parents.size (); i++)
    1169     {
    1170       Project* parent = m_parents[i];
    1171       if (parent == 0) continue;
    1172 
    1173       if (parent->get_name () == p->get_name ())
    1174         {
    1175           // Already registered as a parent (no cycle permitted!!)
    1176           return;
    1177         }
    1178     }
    1179 
    1180   for (i = 0; i < m_children.size (); i++)
    1181     {
    1182       Project* child = m_children[i];
    1183       if (child == 0) continue;
    1184 
    1185       if (child->get_name () == p->get_name ())
    1186         {
    1187           // Already registered as a child
    1188           return;
    1189         }
    1190     }
     1274  if (has_child (p)) return;
     1275  if (has_parent (p)) return;
    11911276
    11921277  m_children.push_back (p);
     
    13241409  int i;
    13251410
    1326   /*
    13271411  for (i = 0; i < m_parents.size (); i++)
    13281412    {
     
    13381422      cout << " C=" << p->get_name ();
    13391423    }
    1340   */
    13411424
    13421425  cout << endl;
  • CMT/HEAD/source/cmt_project.h

    r22 r36  
    145145  void clear ();
    146146  void configure ();
     147  bool has_parent (Project* p) const;
     148  bool has_child (Project* p) const;
    147149  void add_parent (Project* p);
    148150  void add_child (Project* p);
Note: See TracChangeset for help on using the changeset viewer.