[geany/geany-plugins] 9de784: projectorganizer: Change the way symlinks are handled

Jiří Techet git-noreply at xxxxx
Sun Mar 29 19:38:39 UTC 2015


Branch:      refs/heads/master
Author:      Jiří Techet <techet at gmail.com>
Committer:   Jiří Techet <techet at gmail.com>
Date:        Sun, 29 Mar 2015 19:38:39 UTC
Commit:      9de7847797069ad10a3c30308e68e6d0a30c95f8
             https://github.com/geany/geany-plugins/commit/9de7847797069ad10a3c30308e68e6d0a30c95f8

Log Message:
-----------
projectorganizer: Change the way symlinks are handled

Previously all file names and directories were resolved to real path using
tm_get_real_path(). This caused some problems because Geany itself
doesn't resolve things like base_path so when something in base_path
is a symlink, geany path differs from path used by ProjectOrganizer.

Additional problem is when symlink points somewhere outside base_path
which causes that there are ".." entries in the project tree.

Don't resolve symlinks and only resolve real path for cases when
file identity has to be checked and also to avoid symlink cycles.
Simplify relative path creation - we don't need the ".." relative paths
any more.


Modified Paths:
--------------
    projectorganizer/src/prjorg-project.c
    projectorganizer/src/prjorg-sidebar.c
    projectorganizer/src/prjorg-utils.c
    projectorganizer/src/prjorg-utils.h

Modified: projectorganizer/src/prjorg-project.c
26 lines changed, 23 insertions(+), 3 deletions(-)
===================================================================
@@ -93,6 +93,19 @@ static GSList *get_file_list(const gchar * path, GSList *patterns, GSList *ignor
 		if (g_file_test(filename, G_FILE_TEST_IS_DIR))
 		{
 			GSList *lst;
+			gchar *parent_realpath, *child_realpath, *relative;
+
+			/* symlink cycle avoidance - test if directory within parent directory */
+			parent_realpath = tm_get_real_path(path);
+			child_realpath = tm_get_real_path(filename);
+			relative = get_relative_path(parent_realpath, child_realpath);
+			g_free(parent_realpath);
+			g_free(child_realpath);
+
+			if (!relative)
+				continue;
+
+			g_free(relative);
 
 			if (patterns_match(ignored_dirs_patterns, name))
 			{
@@ -152,9 +165,8 @@ static gint prjorg_project_rescan_root(PrjOrgRoot *root)
 	
 	foreach_slist(elem, lst)
 	{
-		char *path;
+		char *path = g_strdup(elem->data);
 
-		path = tm_get_real_path(elem->data);
 		if (path)
 		{
 			SETPTR(path, utils_get_utf8_from_locale(path));
@@ -371,7 +383,15 @@ static void close_root(PrjOrgRoot *root, gpointer user_data)
 
 static gint root_comparator(PrjOrgRoot *a, PrjOrgRoot *b)
 {
-	return g_strcmp0(a->base_dir, b->base_dir);
+	gchar *a_realpath, *b_realpath;
+	gint res;
+
+	a_realpath = tm_get_real_path(a->base_dir);
+	b_realpath = tm_get_real_path(b->base_dir);
+	res = g_strcmp0(a_realpath, b_realpath);
+	g_free(a_realpath);
+	g_free(b_realpath);
+	return res;
 }
 
 


Modified: projectorganizer/src/prjorg-sidebar.c
16 lines changed, 8 insertions(+), 8 deletions(-)
===================================================================
@@ -358,7 +358,7 @@ static void find_file_recursive(GtkTreeIter *iter, gboolean case_sensitive, gboo
 			gchar *path;
 
 			path = build_path(iter);
-			name = get_file_relative_path(geany_data->app->project->base_path, path);
+			name = get_relative_path(geany_data->app->project->base_path, path);
 			g_free(path);
 		}
 		else
@@ -372,7 +372,7 @@ static void find_file_recursive(GtkTreeIter *iter, gboolean case_sensitive, gboo
 			gchar *path, *rel_path;
 
 			path = build_path(iter);
-			rel_path = get_file_relative_path(geany_data->app->project->base_path, path);
+			rel_path = get_relative_path(geany_data->app->project->base_path, path);
 			msgwin_msg_add(COLOR_BLACK, -1, NULL, "%s", rel_path ? rel_path : path);
 			g_free(path);
 			g_free(rel_path);
@@ -558,8 +558,8 @@ static gboolean match(TMTag *tag, const gchar *name, gboolean declaration, gbool
 	{
 		gchar *relpath;
 		
-		relpath = get_file_relative_path(path, tag->file->file_name);
-		matches = relpath && !g_str_has_prefix(relpath, "..");
+		relpath = get_relative_path(path, tag->file->file_name);
+		matches = relpath != NULL;
 		g_free(relpath);
 	}
 	
@@ -592,7 +592,7 @@ static void find_tags(const gchar *name, gboolean declaration, gboolean case_sen
 			gchar *scopestr = tag->scope ? g_strconcat(tag->scope, "::", NULL) : g_strdup("");
 			gchar *relpath;
 			
-			relpath = get_file_relative_path(geany_data->app->project->base_path, tag->file->file_name);
+			relpath = get_relative_path(geany_data->app->project->base_path, tag->file->file_name);
 			msgwin_msg_add(COLOR_BLACK, -1, NULL, "%s:%lu:\n\t[%s]\t %s%s%s", relpath,
 				tag->line, tm_tag_type_name(tag), scopestr, tag->name, tag->arglist ? tag->arglist : "");
 			g_free(scopestr);
@@ -1006,7 +1006,7 @@ static void load_project_root(PrjOrgRoot *root, GtkTreeIter *parent, GSList *hea
 	g_hash_table_iter_init(&iter, root->file_table);
 	while (g_hash_table_iter_next(&iter, &key, &value))
 	{
-		gchar *path = get_file_relative_path(root->base_dir, key);
+		gchar *path = get_relative_path(root->base_dir, key);
 		lst = g_slist_prepend(lst, path);
 	}
 	lst = g_slist_sort(lst, (GCompareFunc) strcmp);
@@ -1152,8 +1152,8 @@ static gboolean follow_editor_on_idle(gpointer foo)
 	{
 		PrjOrgRoot *root = elem->data;
 		
-		path = get_file_relative_path(root->base_dir, doc->file_name);
-		if (path != NULL && !g_str_has_prefix(path, ".."))
+		path = get_relative_path(root->base_dir, doc->file_name);
+		if (path)
 			break;
 			
 		g_free(path);


Modified: projectorganizer/src/prjorg-utils.c
71 lines changed, 8 insertions(+), 63 deletions(-)
===================================================================
@@ -26,75 +26,20 @@
 extern GeanyData *geany_data;
 extern GeanyFunctions *geany_functions;
 
-static gchar *relpath(const gchar *origin_dir, const gchar *dest_dir)
-{
-	gchar *origin, *dest;
-	gchar **originv, **destv;
-	gchar *ret = NULL;
-	guint i, j;
-	
-	origin = tm_get_real_path(origin_dir);
-	dest = tm_get_real_path(dest_dir);
-
-	if (EMPTY(origin) || EMPTY(dest) || origin[0] != dest[0])
-	{
-		g_free(origin);
-		g_free(dest);
-		return NULL;
-	}
-
-	originv = g_strsplit_set(g_path_skip_root(origin), "/\\", -1);
-	destv = g_strsplit_set(g_path_skip_root(dest), "/\\", -1);
-
-	for (i = 0; originv[i] != NULL && destv[i] != NULL; i++)
-		if (g_strcmp0(originv[i], destv[i]) != 0)
-			break;
-
-	ret = g_strdup("");
-
-	for (j = i; originv[j] != NULL; j++)
-		SETPTR(ret, g_build_filename(ret, "..", NULL));
 
-	for (j = i; destv[j] != NULL; j++)
-		SETPTR(ret, g_build_filename(ret, destv[j], NULL));
-
-	if (strlen(ret) == 0)
-		SETPTR(ret, g_strdup("."G_DIR_SEPARATOR_S));
-
-	g_free(origin);
-	g_free(dest);
-	g_strfreev(originv);
-	g_strfreev(destv);
-
-	return ret;
-}
-
-
-gchar *get_file_relative_path(const gchar *origin_dir, const gchar *dest_file)
+gchar *get_relative_path(const gchar *parent, const gchar *descendant)
 {
-	gchar *dest_dir, *ret;
+	GFile *gf_parent, *gf_descendant;
+	gchar *ret;
 
-	dest_dir = g_path_get_dirname(dest_file);
-	ret = relpath(origin_dir, dest_dir);
-	if (ret)
-	{
-		gchar *dest_basename;
+	gf_parent = g_file_new_for_path(parent);
+	gf_descendant = g_file_new_for_path(descendant);
 
-		dest_basename = g_path_get_basename(dest_file);
+	ret = g_file_get_relative_path(gf_parent, gf_descendant);
 
-		if (g_strcmp0(ret, "."G_DIR_SEPARATOR_S) != 0)
-		{
-			SETPTR(ret, g_build_filename(ret, dest_basename, NULL));
-		}
-		else
-		{
-			SETPTR(ret, g_strdup(dest_basename));
-		}
-
-		g_free(dest_basename);
-	}
+	g_object_unref(gf_parent);
+	g_object_unref(gf_descendant);
 
-	g_free(dest_dir);
 	return ret;
 }
 


Modified: projectorganizer/src/prjorg-utils.h
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -19,7 +19,7 @@
 #ifndef __PRJORG_UTILS_H__
 #define __PRJORG_UTILS_H__
 
-gchar *get_file_relative_path(const gchar *origin_dir, const gchar *dest_file);
+gchar *get_relative_path(const gchar *parent, const gchar *descendant);
 
 gboolean patterns_match(GSList *patterns, const gchar *str);
 GSList *get_precompiled_patterns(gchar **patterns);



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Plugins-Commits mailing list