00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "pathReplace.h"
00016 #include "config_util.h"
00017 #include "config_pandatoolbase.h"
00018 #include "indent.h"
00019 #include "virtualFileSystem.h"
00020
00021
00022
00023
00024
00025
00026 PathReplace::
00027 PathReplace() {
00028 _path_store = PS_keep;
00029 _copy_files = false;
00030 _noabs = false;
00031 _exists = false;
00032 _error_flag = false;
00033 }
00034
00035
00036
00037
00038
00039
00040 PathReplace::
00041 ~PathReplace() {
00042 }
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 Filename PathReplace::
00054 match_path(const Filename &orig_filename,
00055 const DSearchPath &additional_path) {
00056 Filename match;
00057 bool got_match = false;
00058
00059 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00060
00061 Entries::const_iterator ei;
00062 for (ei = _entries.begin(); ei != _entries.end(); ++ei) {
00063 const Entry &entry = (*ei);
00064 Filename new_filename;
00065 if (entry.try_match(orig_filename, new_filename)) {
00066
00067
00068 got_match = true;
00069 match = new_filename;
00070
00071 if (new_filename.is_fully_qualified()) {
00072
00073
00074 if (vfs->exists(new_filename)) {
00075 return new_filename;
00076 }
00077
00078 } else {
00079
00080
00081 if (vfs->resolve_filename(new_filename, _path) ||
00082 vfs->resolve_filename(new_filename, additional_path) ||
00083 vfs->resolve_filename(new_filename, get_model_path())) {
00084
00085 if (_path_store == PS_keep) {
00086
00087
00088 return match;
00089 } else {
00090
00091 return new_filename;
00092 }
00093 }
00094 }
00095
00096
00097 }
00098 }
00099
00100
00101
00102 if (got_match) {
00103 if (_exists) {
00104 _error_flag = true;
00105 pandatoolbase_cat.error()
00106 << "File does not exist: " << match << "\n";
00107 } else if (pandatoolbase_cat.is_debug()) {
00108 pandatoolbase_cat.debug()
00109 << "File does not exist: " << match << "\n";
00110 }
00111
00112 return match;
00113 }
00114
00115 if (!orig_filename.is_local()) {
00116
00117
00118 if (_noabs) {
00119 _error_flag = true;
00120 pandatoolbase_cat.error()
00121 << "Absolute pathname: " << orig_filename << "\n";
00122 } else if (pandatoolbase_cat.is_debug()) {
00123 pandatoolbase_cat.debug()
00124 << "Absolute pathname: " << orig_filename << "\n";
00125 }
00126 }
00127
00128
00129
00130 if (_path_store != PS_keep) {
00131 Filename new_filename = orig_filename;
00132 if (vfs->resolve_filename(new_filename, _path) ||
00133 vfs->resolve_filename(new_filename, additional_path) ||
00134 vfs->resolve_filename(new_filename, get_model_path())) {
00135
00136 return new_filename;
00137 }
00138 }
00139
00140
00141
00142 if (_exists) {
00143 _error_flag = true;
00144 pandatoolbase_cat.error()
00145 << "File does not exist: " << orig_filename << "\n";
00146 } else if (pandatoolbase_cat.is_debug()) {
00147 pandatoolbase_cat.debug()
00148 << "File does not exist: " << orig_filename << "\n";
00149 }
00150 return orig_filename;
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 Filename PathReplace::
00162 store_path(const Filename &orig_filename) {
00163 if (orig_filename.empty()) {
00164 return orig_filename;
00165 }
00166
00167 if (_path_directory.is_local()) {
00168 _path_directory.make_absolute();
00169 }
00170 Filename filename = orig_filename;
00171
00172 if (_copy_files) {
00173 copy_this_file(filename);
00174 }
00175
00176 switch (_path_store) {
00177 case PS_relative:
00178 filename.make_absolute();
00179 filename.make_relative_to(_path_directory);
00180 break;
00181
00182 case PS_absolute:
00183 filename.make_absolute();
00184 break;
00185
00186 case PS_rel_abs:
00187 filename.make_absolute();
00188 filename.make_relative_to(_path_directory, false);
00189 break;
00190
00191 case PS_strip:
00192 filename = filename.get_basename();
00193 break;
00194
00195 case PS_keep:
00196 break;
00197
00198 case PS_invalid:
00199 break;
00200 }
00201
00202 return filename;
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 void PathReplace::
00215 full_convert_path(const Filename &orig_filename,
00216 const DSearchPath &additional_path,
00217 Filename &resolved_path,
00218 Filename &output_path) {
00219 if (_path_directory.is_local()) {
00220 _path_directory.make_absolute();
00221 }
00222
00223 Filename match;
00224 bool got_match = false;
00225
00226 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00227
00228 Entries::const_iterator ei;
00229 for (ei = _entries.begin(); ei != _entries.end(); ++ei) {
00230 const Entry &entry = (*ei);
00231 Filename new_filename;
00232 if (entry.try_match(orig_filename, new_filename)) {
00233
00234
00235 got_match = true;
00236 match = new_filename;
00237
00238 if (new_filename.is_fully_qualified()) {
00239
00240
00241 if (vfs->exists(new_filename)) {
00242 resolved_path = new_filename;
00243 goto calculate_output_path;
00244 }
00245
00246 } else {
00247
00248
00249 if (vfs->resolve_filename(new_filename, _path) ||
00250 vfs->resolve_filename(new_filename, additional_path) ||
00251 vfs->resolve_filename(new_filename, get_model_path())) {
00252
00253 resolved_path = new_filename;
00254 goto calculate_output_path;
00255 }
00256 }
00257
00258
00259 }
00260 }
00261
00262
00263
00264 if (got_match) {
00265 if (_exists) {
00266 _error_flag = true;
00267 pandatoolbase_cat.error()
00268 << "File does not exist: " << match << "\n";
00269 } else if (pandatoolbase_cat.is_debug()) {
00270 pandatoolbase_cat.debug()
00271 << "File does not exist: " << match << "\n";
00272 }
00273
00274 resolved_path = match;
00275 goto calculate_output_path;
00276 }
00277
00278 if (!orig_filename.is_local()) {
00279
00280
00281 if (_noabs) {
00282 _error_flag = true;
00283 pandatoolbase_cat.error()
00284 << "Absolute pathname: " << orig_filename << "\n";
00285 } else if (pandatoolbase_cat.is_debug()) {
00286 pandatoolbase_cat.debug()
00287 << "Absolute pathname: " << orig_filename << "\n";
00288 }
00289 }
00290
00291
00292
00293 {
00294 Filename new_filename = orig_filename;
00295 if (vfs->resolve_filename(new_filename, _path) ||
00296 vfs->resolve_filename(new_filename, additional_path) ||
00297 vfs->resolve_filename(new_filename, get_model_path())) {
00298
00299 match = orig_filename;
00300 resolved_path = new_filename;
00301 goto calculate_output_path;
00302 }
00303 }
00304
00305
00306
00307 if (_exists) {
00308 _error_flag = true;
00309 pandatoolbase_cat.error()
00310 << "File does not exist: " << orig_filename << "\n";
00311 } else if (pandatoolbase_cat.is_debug()) {
00312 pandatoolbase_cat.debug()
00313 << "File does not exist: " << orig_filename << "\n";
00314 }
00315 match = orig_filename;
00316 resolved_path = orig_filename;
00317
00318
00319
00320
00321 calculate_output_path:
00322
00323 if (_copy_files) {
00324 if (copy_this_file(resolved_path)) {
00325 match = resolved_path;
00326 }
00327 }
00328
00329 switch (_path_store) {
00330 case PS_relative:
00331 if (resolved_path.empty())
00332 output_path = resolved_path;
00333 else {
00334 output_path = resolved_path;
00335 output_path.make_absolute();
00336 output_path.make_relative_to(_path_directory);
00337 }
00338 break;
00339
00340 case PS_absolute:
00341 if (resolved_path.empty())
00342 output_path = resolved_path;
00343 else {
00344 output_path = resolved_path;
00345 output_path.make_absolute();
00346 }
00347 break;
00348
00349 case PS_rel_abs:
00350 if (resolved_path.empty())
00351 output_path = resolved_path;
00352 else {
00353 output_path = resolved_path;
00354 output_path.make_absolute();
00355 output_path.make_relative_to(_path_directory, false);
00356 }
00357 break;
00358
00359 case PS_strip:
00360 output_path = match.get_basename();
00361 break;
00362
00363 case PS_keep:
00364 output_path = match;
00365 break;
00366
00367 case PS_invalid:
00368 output_path = "";
00369 break;
00370 }
00371 }
00372
00373
00374
00375
00376
00377
00378 void PathReplace::
00379 write(ostream &out, int indent_level) const {
00380 Entries::const_iterator ei;
00381 for (ei = _entries.begin(); ei != _entries.end(); ++ei) {
00382 indent(out, indent_level)
00383 << "-pr " << (*ei)._orig_prefix << "="
00384 << (*ei)._replacement_prefix << "\n";
00385 }
00386 int num_directories = _path.get_num_directories();
00387 for (int i = 0; i < num_directories; i++) {
00388 indent(out, indent_level)
00389 << "-pp " << _path.get_directory(i) << "\n";
00390 }
00391 indent(out, indent_level)
00392 << "-ps " << _path_store << "\n";
00393
00394
00395 switch (_path_store) {
00396 case PS_relative:
00397 case PS_rel_abs:
00398 indent(out, indent_level)
00399 << "-pd " << _path_directory << "\n";
00400
00401 default:
00402 break;
00403 }
00404
00405 if (_copy_files) {
00406 indent(out, indent_level)
00407 << "-pc " << _copy_into_directory << "\n";
00408 }
00409
00410 if (_noabs) {
00411 indent(out, indent_level)
00412 << "-noabs\n";
00413 }
00414 }
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 bool PathReplace::
00425 copy_this_file(Filename &filename) {
00426 if (_copy_into_directory.is_local()) {
00427 _copy_into_directory = Filename(_path_directory, _copy_into_directory);
00428 }
00429
00430 Copied::iterator ci = _orig_to_target.find(filename);
00431 if (ci != _orig_to_target.end()) {
00432
00433
00434 if (filename != (*ci).second) {
00435 filename = (*ci).second;
00436 return true;
00437 }
00438 return false;
00439 }
00440
00441 Filename target_filename(_copy_into_directory, filename.get_basename());
00442 ci = _target_to_orig.find(target_filename);
00443 if (ci != _target_to_orig.end()) {
00444 if ((*ci).second != filename) {
00445 _error_flag = true;
00446 pandatoolbase_cat.error()
00447 << "Filename conflict! Both " << (*ci).second << " and "
00448 << filename << " map to " << target_filename << "\n";
00449 }
00450
00451
00452 _orig_to_target[filename] = filename;
00453 return false;
00454 }
00455
00456 _orig_to_target[filename] = target_filename;
00457 _target_to_orig[target_filename] = filename;
00458
00459
00460 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00461 vfs->make_directory_full(_copy_into_directory);
00462 if (!vfs->copy_file(filename, target_filename)) {
00463 _error_flag = true;
00464 pandatoolbase_cat.error()
00465 << "Cannot copy file from " << filename << " to " << target_filename
00466 << "\n";
00467 _orig_to_target[filename] = filename;
00468 return false;
00469 }
00470
00471 filename = target_filename;
00472 return true;
00473 }
00474
00475
00476
00477
00478
00479
00480 PathReplace::Entry::
00481 Entry(const string &orig_prefix, const string &replacement_prefix) :
00482 _orig_prefix(orig_prefix),
00483 _replacement_prefix(replacement_prefix)
00484 {
00485
00486 if (_orig_prefix.length() > 1 &&
00487 _orig_prefix[_orig_prefix.length() - 1] == '/') {
00488 _orig_prefix = _orig_prefix.substr(0, _orig_prefix.length() - 1);
00489 }
00490 if (_replacement_prefix.length() > 1 &&
00491 _replacement_prefix[_replacement_prefix.length() - 1] == '/') {
00492 _replacement_prefix = _replacement_prefix.substr(0, _replacement_prefix.length() - 1);
00493 }
00494
00495 Filename filename(_orig_prefix);
00496 _is_local = filename.is_local();
00497
00498 vector_string components;
00499 filename.extract_components(components);
00500 vector_string::const_iterator ci;
00501 for (ci = components.begin(); ci != components.end(); ++ci) {
00502 _orig_components.push_back(Component(*ci));
00503 }
00504 }
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514 bool PathReplace::Entry::
00515 try_match(const Filename &filename, Filename &new_filename) const {
00516 if (_is_local != filename.is_local()) {
00517 return false;
00518 }
00519 vector_string components;
00520 filename.extract_components(components);
00521 size_t mi = r_try_match(components, 0, 0);
00522 if (mi == 0) {
00523
00524 return false;
00525 }
00526
00527
00528 string result = _replacement_prefix;
00529 while (mi < components.size()) {
00530 if (!result.empty()) {
00531 result += '/';
00532 }
00533 result += components[mi];
00534 ++mi;
00535 }
00536 new_filename = result;
00537 return true;
00538 }
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 size_t PathReplace::Entry::
00553 r_try_match(const vector_string &components, size_t oi, size_t ci) const {
00554 if (oi >= _orig_components.size()) {
00555
00556 return ci;
00557 }
00558 if (ci >= components.size()) {
00559
00560
00561
00562
00563
00564 return 0;
00565 }
00566
00567 const Component &orig_component = _orig_components[oi];
00568 if (orig_component._double_star) {
00569
00570
00571 size_t mi = r_try_match(components, oi, ci + 1);
00572 if (mi != 0) {
00573 return mi;
00574 }
00575
00576
00577 return r_try_match(components, oi + 1, ci);
00578 }
00579
00580
00581
00582 if (orig_component._orig_prefix.matches(components[ci])) {
00583
00584 return r_try_match(components, oi + 1, ci + 1);
00585 }
00586
00587
00588 return 0;
00589 }