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