Browse Source

ENH: Re-implemented CollapseFullPath to not need to change directories. Operation is now fully string based.

Brad King 20 years ago
parent
commit
4ba14d1278
1 changed files with 64 additions and 42 deletions
  1. 64 42
      Source/kwsys/SystemTools.cxx

+ 64 - 42
Source/kwsys/SystemTools.cxx

@@ -2085,60 +2085,82 @@ void SystemTools::CheckTranslationPath(kwsys_stl::string & path)
   path.erase(path.end()-1, path.end());
 }
 
-kwsys_stl::string SystemTools::CollapseFullPath(const char* in_relative,
-                                                const char* in_base)
+void
+SystemToolsAppendComponents(
+  kwsys_stl::vector<kwsys_stl::string>& out_components,
+  kwsys_stl::vector<kwsys_stl::string>::const_iterator first,
+  kwsys_stl::vector<kwsys_stl::string>::const_iterator last)
 {
-  kwsys_stl::string orig;
-  
-  // Change to base of relative path.
-  if(in_base)
+  for(kwsys_stl::vector<kwsys_stl::string>::const_iterator i = first;
+      i != last; ++i)
     {
-    // Save original working directory.
-    orig = SystemTools::GetCurrentWorkingDirectory();
-    Chdir(in_base);
+    if(*i == "..")
+      {
+      if(out_components.begin() != out_components.end())
+        {
+        out_components.erase(out_components.end()-1, out_components.end());
+        }
+      }
+    else if(*i != "." && *i != "")
+      {
+      out_components.push_back(*i);
+      }
     }
-  
-  kwsys_stl::string dir, file;
-  SystemTools::SplitProgramPath(in_relative, dir, file, false);
-  if(dir.size() == 0 && 
-      in_relative && strlen(in_relative) > 0 &&
-      in_relative[0] == '/')
-     {
-     dir = "/";
-     }
+}
 
-  // Resolve relative path.
-  kwsys_stl::string newDir;
-  if(!(dir == ""))
-    {
-    Realpath(dir.c_str(), newDir);    
-    }
-  else
-    {
-    newDir = SystemTools::GetCurrentWorkingDirectory();
-    }
+kwsys_stl::string SystemTools::CollapseFullPath(const char* in_path,
+                                                const char* in_base)
+{
+  // Collect the output path components.
+  kwsys_stl::vector<kwsys_stl::string> out_components;
 
-  if(in_base)
-    {
-    // Restore original working directory.
-    Chdir(orig.c_str());
-    }
-  
-  // Construct and return the full path.
-  kwsys_stl::string newPath = newDir;
-  if(!(file == ""))
+  // Split the input path components.
+  kwsys_stl::vector<kwsys_stl::string> path_components;
+  SystemTools::SplitPath(in_path, path_components);
+
+  // If the input path is relative, start with a base path.
+  if(path_components[0].length() == 0)
     {
-    if(!(newDir.size() == 1 && newDir[0] ==  '/'))
+    kwsys_stl::vector<kwsys_stl::string> base_components;
+    if(in_base)
+      {
+      // Use the given base path.
+      SystemTools::SplitPath(in_base, base_components);
+      }
+    else
       {
-      newPath += "/";
+      // Use the current working directory as a base path.
+      char buf[2048];
+      if(const char* cwd = Getcwd(buf, 2048))
+        {
+        SystemTools::SplitPath(cwd, base_components);
+        }
+      else
+        {
+        // ??
+        }
       }
-    newPath += file;
+
+    // Append base path components to the output path.
+    out_components.push_back(base_components[0]);
+    SystemToolsAppendComponents(out_components,
+                                base_components.begin()+1,
+                                base_components.end());
     }
 
-  // Now we need to update the translation table with this potentially new path
-  SystemTools::AddTranslationPath(newPath.c_str(), in_relative);
+  // Append input path components to the output path.
+  SystemToolsAppendComponents(out_components,
+                              path_components.begin(),
+                              path_components.end());
+
+  // Transform the path back to a string.
+  kwsys_stl::string newPath = SystemTools::JoinPath(out_components);
+
+  // Update the translation table with this potentially new path.
+  SystemTools::AddTranslationPath(newPath.c_str(), in_path);
   SystemTools::CheckTranslationPath(newPath);
 
+  // Return the reconstructed path.
   return newPath;
 }