// // aegis - project change supervisor // Copyright (C) 2004-2008 Peter Miller // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see // . // #include #include // for assert #include #include #include #include #include void change_file_resolve_names(change::pointer cp, user_ty::pointer up, string_list_ty &names) { trace(("change_file_resolve_names(cp = %08lX, up = %08lX)\n{\n", (long)cp, (long)up.get())); // // Get the change's search path. We will be looking along this to // see if we can resolve each file's relative name. // string_list_ty search_path; change_search_path_get(cp, &search_path, 1); // // Did the user specify the --base-relative option? // bool based = ( search_path.nstrings >= 1 && ( up->relative_filename_preference ( uconf_relative_filename_preference_current ) == uconf_relative_filename_preference_base ) ); // // Now we are finally in a position to figure out the directory to // use to turn relative file names into absolute file names. // string_ty *base = search_path.string[0]; if (!based) { os_become_orig(); base = os_curdir(); os_become_undo(); } // // Work over each of the file names in the given list of names. // for (size_t j = 0; j < names.nstrings; ++j) { // // Make the file name absolute, if it isn't already. // string_ty *filename = names.string[j]; string_ty *s2 = 0; if (filename->str_text[0] == '/') s2 = str_copy(filename); else s2 = os_path_join(base, filename); assert(s2); // // Resolve the absolute file name to get rid of symlinks and "." // or ".." components that would otherwise confuse the process. // up->become_begin(); string_ty *s1 = os_pathname(s2, 1); up->become_end(); str_free(s2); s2 = 0; // // Hunt down the search path to see of the file is below any of // the directories in the search path. It is an error if the // file is not in one of them. // for (size_t k = 0; k < search_path.nstrings; ++k) { s2 = os_below_dir(search_path.string[k], s1); if (s2) break; } str_free(s1); if (!s2) { sub_context_ty sc(__FILE__, __LINE__); sc.var_set_string("File_Name", filename); change_fatal(cp, &sc, i18n("$filename unrelated")); } // // Replace the filename in the list with the resolved path, // relative to the base of the dev dir (or baseline). // str_free(names.string[j]); names.string[j] = s2; } trace(("}\n")); } string_ty * change_file_resolve_name(change::pointer cp, user_ty::pointer up, string_ty *filename) { // // The single file is handled as a special case of one file, rather // than the other way around, for efficiency. Some commands have // thousands of file names to process. // string_list_ty name_list; name_list.push_back(filename); change_file_resolve_names(cp, up, name_list); return str_copy(name_list.string[0]); }