[Vala] [PATCH] Make SourceFile.get_relative_filename relative to current directory.



Change SourceFile.get_relative_filename () to return path relative to current
working directory rather than basedir and make it work even when the file is
not under current directory.

This allows filenames in error messages to be resolved by generic build log
handlers like vim quickfix mode and similar tools in other editors and IDEs.

The only other use of the modified function is writing comments to the
generated files. Neither old nor new behaviour seems to be more useful there.

Fixes bug 591683.

Signed-off-by: Jan Hudec <bulb ucw cz>
---

I've looked where the Vala.SourceFile.get_relative_filename function is used
and it seems to only be used for:
 - error messages, where this change is desirable and
 - comments in the generated output, where it should not matter.

The change is important when doing off-tree buids and trying to look at the
error messages with IDE or editor. Make (or waf in my case) reprts current
directory it uses for executing the commands (the Entering directory
message), which the error message parser uses as base for resolving filenames
in error messages printed by the compier.

However, valac only prints the base name without directory if the file was
not in subdirectory of the current directory. This change makes it report the
filename relative to current directory in all cases.

 vala/valasourcefile.vala |   39 ++++++++++++++++++++++++++++++++++++++-
 1 files changed, 38 insertions(+), 1 deletions(-)

diff --git a/vala/valasourcefile.vala b/vala/valasourcefile.vala
index 0ec4429..24bd74c 100644
--- a/vala/valasourcefile.vala
+++ b/vala/valasourcefile.vala
@@ -191,8 +191,45 @@ public class Vala.SourceFile {
                return Path.get_basename (filename.substring (0, dot));
        }
 
+       private static string cwd = null;
+
+       private static weak string get_cwd () {
+               if (cwd == null) {
+                       cwd = Environment.get_current_dir () + Path.DIR_SEPARATOR_S;
+               }
+               return cwd;
+       }
+
+       /**
+        * Returns the filename relative to current working directory.
+        *
+        * @return filename relative to current dir.
+        */
        public string get_relative_filename () {
-               return get_subdir () + Path.get_basename (filename);
+               weak string dir = get_cwd ();
+               weak string name = filename;
+               // find common prefix
+               while (dir[0] != 0 && name[0] != 0 && dir[0] == name[0]) {
+                       dir = dir.offset (1);
+                       name = name.offset (1);
+               }
+               if (dir[0] == 0) {
+                       return name;
+               }
+               // find last directory separator in the prefix
+               dir = cwd.rchr (cwd.pointer_to_offset (dir), '/');
+               if (dir != null && cwd.pointer_to_offset (dir) > 0) { // more than leading / in common
+                       // find respective suffix of filename (without /)
+                       name = filename.offset (cwd.pointer_to_offset (dir) + 1);
+                       var result = new StringBuilder ();
+                       while ((dir = dir.offset (1).chr (-1, '/')) != null) {
+                               result.append ("../");
+                       }
+                       result.append (name);
+                       return result.str;
+               }
+               // nothing in common
+               return filename;
        }
 
        /**
-- 
1.6.3.3



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]