Skip to content

Commit

Permalink
projectorganizer: Change the way symlinks are handled
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
techee committed Mar 29, 2015
1 parent 8cffdb4 commit 9de7847
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 75 deletions.
26 changes: 23 additions & 3 deletions projectorganizer/src/prjorg-project.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
{
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
}


Expand Down
16 changes: 8 additions & 8 deletions projectorganizer/src/prjorg-sidebar.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
71 changes: 8 additions & 63 deletions projectorganizer/src/prjorg-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion projectorganizer/src/prjorg-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 9de7847

Please sign in to comment.