#include #include #include /* #--------------------------------------------------------------------- # # This program should be installed within the loginfo file of CVS # using the following line : # # ... #.cmtcvsinfos (${CMTROOT}\cmtcvs\v1\VisualC\cmtcvs.exe %s) # ... # # and is used whenever one tries to import a module named .cmtcvsinfos/ # #--------------------------------------------------------------------- */ // // This global flag is set when the string "/cmtcvstest/" is found in // the module argument. This can be used to change the default // behaviour of this pluggin. // // Eg. It can be used to experiment new features. // static bool cmtcvstest = false; //--------------------------------------------------------------------- static cmt_string get_cvsroot (cmt_string& result) { //echo ${CVSROOT} | sed -e 's#^:[^:]*:##' CmtSystem::get_cvsroot (result); int pos = result.find (":"); if (pos == 0) { pos = result.find (1, ":"); result.erase (0, pos+1); } return (result); } static void clear_cmtcvsinfos () { cmt_string dir; get_cvsroot (dir); dir += CmtSystem::file_separator (); dir += ".cmtcvsinfos"; CmtSystem::cmt_string_vector files; CmtSystem::scan_dir (dir, files); for (int i = 0; i < files.size (); i++) { const cmt_string& f = files[i]; CmtSystem::remove_directory (f); } } //--------------------------------------------------------------------- static bool check_head (const cmt_string& head, const cmt_string& version) { CmtSystem::cmt_string_vector hlist; CmtSystem::cmt_string_vector vlist; CmtSystem::split (head, " ", hlist); CmtSystem::split (version, " ", vlist); int nh = hlist.size (); //int nv = vlist.size (); for (int i = 0; i < nh; ++i) { const cmt_string& h = hlist[i]; const cmt_string& v = vlist[i]; if (h != v) return (false); } return (true); } //--------------------------------------------------------------------- // Question: is v1 newer than v2? // static bool check_newer (const cmt_string& v1, const cmt_string& v2) { if (v2 == "") return (true); if (v1 == "") return (false); CmtSystem::cmt_string_vector list1; CmtSystem::cmt_string_vector list2; CmtSystem::split (v1, ".", list1); CmtSystem::split (v2, ".", list2); int n1 = list1.size (); int n2 = list2.size (); //cerr << "checknewer v1=" << v1 << " v2=" << v2 << " n1=" << n1 << " n2=" << n2 << endl; /* v1 = a1.a2.a3.a4 v2 = b1.b2.b3 {i = 0.. min(n1,n2) | if (ai > bi) -> [v1 newer than v2] } [1.2.5 vs 1.2.4] then if (n1 < n2} [v2 newer] [1.2 vs 1.2.5] if (n1 > n2) [v1 newer] [1.2.5 vs 1.2] */ for (int i = 0; i < n1; ++i) { if (i >= n2) { // cerr << "n1 > n2" << endl; return (false); } const cmt_string& s1 = list1[i]; const cmt_string& s2 = list2[i]; int i1; int i2; i1 = atoi (s1.c_str ()); i2 = atoi (s2.c_str ()); //cerr << " i1=" << i1 << " i2=" << i2 << endl; if (i1 > i2) return (true); // v1 newer if (i1 < i2) return (false); // v2 newer } // n2 > n1 // v2 newer //cerr << "n2 > n1" << endl; return (false); } typedef enum { no_structure, in_project, in_package } StructureType; //--------------------------------------------------------------------- static StructureType get_tags (const cmt_string& module, CmtSystem::cmt_string_vector& toptags, CmtSystem::cmt_string_vector& tags, CmtSystem::cmt_string_vector& topcvsversions, CmtSystem::cmt_string_vector& cvsversions) { cmt_string package; cmt_string container; CmtSystem::basename (module, package); CmtSystem::dirname (module, container); CmtSystem::dirname (container, container); //cout << "package=" << package << endl; //cout << "container=" << container << endl; /* # First figure out which test file will be used to retreive the tags o consider ChangeLog in the top directory first (as it is most likely changed when the module is tagged and, therefore, its revision will allow us to distinguish between the trunk and branches) # o requirements file is considered first # o then any other file in the top directory # */ StructureType result (no_structure); cmt_string proj_file; get_cvsroot (proj_file); proj_file += CmtSystem::file_separator (); proj_file += module; proj_file += CmtSystem::file_separator (); proj_file += "cmt"; proj_file += CmtSystem::file_separator (); proj_file += "project.cmt,v"; if (CmtSystem::test_file (proj_file)) { result = in_project; } else { result = in_package; } cmt_string test_file; bool found = false; get_cvsroot (test_file); test_file += CmtSystem::file_separator (); test_file += module; test_file += CmtSystem::file_separator (); test_file += "ChangeLog,v"; found = CmtSystem::test_file (test_file); if (!found && result == in_project) { test_file = proj_file; found = true; } if (!found) { // not a CMT project // try it as a CMT package with cmt directory result = in_package; get_cvsroot (test_file); test_file += CmtSystem::file_separator (); test_file += module; test_file += CmtSystem::file_separator (); test_file += "cmt"; test_file += CmtSystem::file_separator (); test_file += "requirements,v"; found = CmtSystem::test_file (test_file); } if (!found) { // try it as a CMT package with mgr directory get_cvsroot (test_file); test_file += CmtSystem::file_separator (); test_file += module; test_file += CmtSystem::file_separator (); test_file += "mgr"; test_file += CmtSystem::file_separator (); test_file += "requirements,v"; found = CmtSystem::test_file (test_file); } if (!found) { // try it as a CMT package with cmt directory but in Attic get_cvsroot (test_file); test_file += CmtSystem::file_separator (); test_file += module; test_file += CmtSystem::file_separator (); test_file += "cmt"; test_file += CmtSystem::file_separator (); test_file += "Attic"; test_file += CmtSystem::file_separator (); test_file += "requirements,v"; found = CmtSystem::test_file (test_file); } if (!found) { // try it as an old SRT package (should be obsolete) get_cvsroot (test_file); test_file += CmtSystem::file_separator (); test_file += module; test_file += CmtSystem::file_separator (); test_file += "PACKAGE,v"; found = CmtSystem::test_file (test_file); } if (!found) { // Structure not recognized (should we take the first file?) result = no_structure; return (result); } /* #symbols # v10:1.1.1.1 # v2:1.1.1.1 # v1r2:1.1.1.1 # v1r1:1.1.1.1 # v1:1.1.1.1 # cmt:1.1.1; #locks; strict; # # Then extract all tags from the file header # one line per tag : # # : # */ cmt_string top; cmt_string temp; temp.read (test_file); int pos = temp.find ("symbols"); temp.erase (0, pos + 7); pos = temp.find ("locks"); temp.erase (pos); //cerr << "temp=[" << temp << "]" << endl; CmtSystem::cmt_string_vector words; CmtSystem::split (temp, " \t\n", words); int i; CmtSystem::cmt_string_vector alltags; for (i = 0; i < words.size (); i++) { const cmt_string& s = words[i]; CmtSystem::cmt_string_vector w; CmtSystem::split (s, ".", w); int n = w.size (); //cerr << "level=" << n << endl; if ((n == 2) || (n == 4) || (n == 6)) { cmt_string& t = alltags.add (); t = s; } } /*# # Compute the most recent tag (using the cvs version ids) #*/ for (i = 0; i < alltags.size (); ++i) { const cmt_string& s = alltags[i]; cmt_string tag = s; pos = tag.find (":"); tag.erase (pos); cmt_string v = s; v.replace (";", ""); v.erase (0, pos+1); //cerr << "s=" << s << " v=" << v << " top=" << top << endl; if (check_newer (v, top)) { //cerr << v << " plus recent que " << top << endl; top = v; } } // cerr << "topv=" << top << endl; bool has_container = false; bool has_package = false; // // Atlas specific behaviour which consists in detecting tags // with a pattern -xxx // for (i = 0; i < alltags.size (); ++i) { const cmt_string& s = alltags[i]; // Get the symbolic tag cmt_string tag = s; pos = tag.find (":"); if (pos == cmt_string::npos) continue; tag.erase (pos); // Analyze its structure cmt_string name = tag; pos = name.find ("-"); if (pos != cmt_string::npos) { name.erase (pos); } if (name == container) { has_container = true; } else if (name == package) { has_package = true; } } /*# # Split the tag list into tags that have same cvs-version-id than # the top tag (tags_tops) and older ones (tags). #*/ toptags.clear (); tags.clear (); topcvsversions.clear (); cvsversions.clear (); for (i = 0; i < alltags.size (); ++i) { static const cmt_string digits = "0123456789"; const cmt_string& s = alltags[i]; cmt_string tag = s; pos = tag.find (":"); tag.erase (pos); cmt_string v = s; v.replace (";", ""); v.erase (0, pos+1); cmt_string fullv = s; fullv.replace (";", ""); cmt_string digit; cmt_string name = tag; pos = name.find ("-"); if (pos != cmt_string::npos) { digit = name[pos+1]; name.erase (pos); } //cout << "tag=" << tag << " name=" << name << " v=" << v << " package=" << package << endl; if (!has_package || ((name == package) && (digits.find (digit) != cmt_string::npos ))) { if (v == top) { toptags.push_back (tag); topcvsversions.push_back (fullv); } else { tags.push_back (tag); cvsversions.push_back (fullv); } } } return (result); } //--------------------------------------------------------------------- static cmt_string get_branches (const cmt_string& module) { cmt_string result; cmt_string dir; get_cvsroot (dir); dir += CmtSystem::file_separator (); dir += module; CmtSystem::cmt_string_vector files; CmtSystem::scan_dir (dir, files); for (int i = 0; i < files.size (); i++) { const cmt_string& branch = files[i]; if (!CmtSystem::test_directory (branch)) continue; cmt_string t; CmtSystem::basename (branch, t); if (t == "Attic") continue; if (t == "CVSROOT") continue; if (t == "defunct.CVS") continue; if (t == ".cmtcvsinfos") continue; if (t == ".cmtcvsinfostest") continue; if (t == ".cmtcvstest") continue; t = branch; t += CmtSystem::file_separator (); t += "cmt"; t += CmtSystem::file_separator (); t += "requirements,v"; if (CmtSystem::test_file (t)) continue; t = branch; t += CmtSystem::file_separator (); t += "mgr"; t += CmtSystem::file_separator (); t += "requirements,v"; if (CmtSystem::test_file (t)) continue; t = branch; t += CmtSystem::file_separator (); t += "cmt"; t += CmtSystem::file_separator (); t += "project.cmt,v"; if (CmtSystem::test_file (t)) continue; CmtSystem::basename (branch, t); if (result != "") result += " "; result += t; } return (result); } //--------------------------------------------------------------------- static cmt_string get_subpackages (const cmt_string& module) { cmt_string result; cmt_string dir; get_cvsroot (dir); dir += CmtSystem::file_separator (); dir += module; CmtSystem::cmt_string_vector files; CmtSystem::scan_dir (dir, files); for (int i = 0; i < files.size (); i++) { const cmt_string& subpackage = files[i]; if (!CmtSystem::test_directory (subpackage)) continue; cmt_string t; CmtSystem::basename (subpackage, t); if (t == "Attic") continue; t = subpackage; t += CmtSystem::file_separator (); t += "cmt"; t += CmtSystem::file_separator (); t += "requirements,v"; if (CmtSystem::test_file (t)) { CmtSystem::basename (subpackage, t); if (result != "") result += " "; result += t; } else { t = subpackage; t += CmtSystem::file_separator (); t += "mgr"; t += CmtSystem::file_separator (); t += "requirements,v"; if (CmtSystem::test_file (t)) { CmtSystem::basename (subpackage, t); if (result != "") result += " "; result += t; } } } return (result); } //--------------------------------------------------------------------- static cmt_string get_subprojects (const cmt_string& module) { cmt_string result; cmt_string dir; get_cvsroot (dir); dir += CmtSystem::file_separator (); dir += module; CmtSystem::cmt_string_vector files; CmtSystem::scan_dir (dir, files); for (int i = 0; i < files.size (); i++) { const cmt_string& subproject = files[i]; if (!CmtSystem::test_directory (subproject)) continue; cmt_string t; CmtSystem::basename (subproject, t); if (t == "Attic") continue; t = subproject; t += CmtSystem::file_separator (); t += "cmt"; t += CmtSystem::file_separator (); t += "project.cmt,v"; if (CmtSystem::test_file (t)) { CmtSystem::basename (subproject, t); if (result != "") result += " "; result += t; } } return (result); } #define V(v) #v //--------------------------------------------------------------------- int main (int /*argc*/, char* argv[]) { clear_cmtcvsinfos (); cmt_string module = argv[1]; int pos = module.find (" "); if (pos != cmt_string::npos) module.erase (pos); module.replace (".cmtcvsinfos/", ""); cout << "#VERSION=[" << VERSION << "]" << endl; cmt_string version = VERSION; version += "/"; pos = module.find (version); if (pos == 0) { const cmt_string null = ""; module.replace (version, null); } pos = module.find (VERSION); if (pos == 0) { module.replace (VERSION, ""); } pos = module.find ("cmtcvstest/"); if (pos == 0) { module.replace ("cmtcvstest/", ""); cmtcvstest = true; //cout << "cmtcvstest=true" << endl; } cout << "#module=[" << module << "]" << endl; if (module == "") { module = "."; } cmt_string tags; cmt_string tags_top; cmt_string cvsversions; cmt_string cvsversions_top; cmt_string dir; get_cvsroot (dir); dir += CmtSystem::file_separator (); dir += module; cmt_string error; StructureType structure = no_structure; //cout << "dir=" << dir << endl; if (CmtSystem::test_directory (dir)) { CmtSystem::cmt_string_vector toptag_list; CmtSystem::cmt_string_vector tag_list; CmtSystem::cmt_string_vector topcvsversion_list; CmtSystem::cmt_string_vector cvsversion_list; structure = get_tags (module, toptag_list, tag_list, topcvsversion_list, cvsversion_list); int i; for (i = 0; i < toptag_list.size (); i++) { const cmt_string& s = toptag_list[i]; const cmt_string& v = topcvsversion_list[i]; if (tags_top != "") tags_top += " "; tags_top += s; if (cvsversions_top != "") cvsversions_top += " "; cvsversions_top += v; } for (i = 0; i < tag_list.size (); i++) { const cmt_string& s = tag_list[i]; const cmt_string& v = cvsversion_list[i]; if (tags != "") tags += " "; tags += s; if (cvsversions != "") cvsversions += " "; cvsversions += v; } } else { error = "### Module "; error += module; error += " not found."; } cmt_string branches; cmt_string subpackages; cmt_string subprojects; if (CmtSystem::test_directory (dir)) { branches = get_branches (module); subpackages = get_subpackages (module); subprojects = get_subprojects (module); } if (error != "") { cout << "error=" << error << endl; } cmt_string structures[] = {"none", "project", "package"}; cout << "structure=" << structures[structure] << endl; cout << "tags_top=" << tags_top << endl; cout << "tags=" << tags << endl; cout << "cvsversions_top=" << cvsversions_top << endl; cout << "cvsversions=" << cvsversions << endl; cout << "branches=" << branches << endl; cout << "subpackages=" << subpackages << endl; cout << "subprojects=" << subprojects << endl; exit (1); }