[gnome-builder] libide: add ide_project_rename_file_async()
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] libide: add ide_project_rename_file_async()
- Date: Thu, 16 Apr 2015 01:07:48 +0000 (UTC)
commit 18863ccae90bcab050c0d8caf94dc456ea32c931
Author: Christian Hergert <christian hergert me>
Date: Wed Apr 15 18:02:13 2015 -0700
libide: add ide_project_rename_file_async()
This will rename a file within the project tree and attach it to the
new position in the tree.
This process has lead me to believe we probably want to add tree observers
to deal with movements/additions/deletes. It could really simplify
things externally, like the project-tree UI.
libide/ide-project-file.c | 21 ++++---
libide/ide-project-files.c | 3 +-
libide/ide-project.c | 155 ++++++++++++++++++++++++++++++++++++++++++++
libide/ide-project.h | 35 ++++++----
4 files changed, 191 insertions(+), 23 deletions(-)
---
diff --git a/libide/ide-project-file.c b/libide/ide-project-file.c
index af24a43..d4ef827 100644
--- a/libide/ide-project-file.c
+++ b/libide/ide-project-file.c
@@ -71,9 +71,13 @@ ide_project_file_set_path (IdeProjectFile *self,
IdeProjectFilePrivate *priv = ide_project_file_get_instance_private (self);
g_return_if_fail (IDE_IS_PROJECT_FILE (self));
- g_return_if_fail (!priv->path);
- priv->path = g_strdup (path);
+ if (priv->path != path)
+ {
+ g_free (priv->path);
+ priv->path = g_strdup (path);
+ g_object_notify_by_pspec (G_OBJECT (self), gParamSpecs [PROP_PATH]);
+ }
}
const gchar *
@@ -149,7 +153,10 @@ ide_project_file_set_file_info (IdeProjectFile *file,
g_return_if_fail (!file_info || G_IS_FILE_INFO (file_info));
if (g_set_object (&priv->file_info, file_info))
- g_object_notify_by_pspec (G_OBJECT (file), gParamSpecs [PROP_FILE_INFO]);
+ {
+ g_object_notify_by_pspec (G_OBJECT (file), gParamSpecs [PROP_FILE_INFO]);
+ g_object_notify_by_pspec (G_OBJECT (file), gParamSpecs [PROP_NAME]);
+ }
}
static void
@@ -250,9 +257,7 @@ ide_project_file_class_init (IdeProjectFileClass *klass)
_("File Info"),
_("The file information for the project file."),
G_TYPE_FILE_INFO,
- (G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_FILE_INFO,
gParamSpecs [PROP_FILE_INFO]);
@@ -279,9 +284,7 @@ ide_project_file_class_init (IdeProjectFileClass *klass)
_("Path"),
_("The path for the file within the project tree."),
NULL,
- (G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_PATH,
gParamSpecs [PROP_PATH]);
}
diff --git a/libide/ide-project-files.c b/libide/ide-project-files.c
index 9238923..7f9568d 100644
--- a/libide/ide-project-files.c
+++ b/libide/ide-project-files.c
@@ -96,6 +96,7 @@ ide_project_files_find_child (IdeProjectItem *item,
* @file: A #GFile.
*
* Tries to locate an #IdeProjectFile matching the given file.
+ * If @file is the working directory, @self is returned.
*
* Returns: (transfer none) (nullable): An #IdeProjectItem or %NULL.
*/
@@ -120,7 +121,7 @@ ide_project_files_find_file (IdeProjectFiles *self,
workdir = ide_vcs_get_working_directory (vcs);
if (g_file_equal (workdir, file))
- return NULL;
+ return IDE_PROJECT_ITEM (self);
path = g_file_get_relative_path (workdir, file);
if (path == NULL)
diff --git a/libide/ide-project.c b/libide/ide-project.c
index aaae474..97b5079 100644
--- a/libide/ide-project.c
+++ b/libide/ide-project.c
@@ -19,6 +19,7 @@
#include <glib/gi18n.h>
#include "ide-context.h"
+#include "ide-debug.h"
#include "ide-file.h"
#include "ide-project.h"
#include "ide-project-files.h"
@@ -32,6 +33,12 @@ typedef struct
gchar *name;
} IdeProjectPrivate;
+typedef struct
+{
+ GFile *orig_file;
+ GFile *new_file;
+} RenameFile;
+
G_DEFINE_TYPE_WITH_PRIVATE (IdeProject, ide_project, IDE_TYPE_OBJECT)
enum {
@@ -400,3 +407,151 @@ ide_project_init (IdeProject *self)
g_rw_lock_init (&priv->rw_lock);
}
+
+static void
+ide_project_rename_file_worker (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ IdeProject *self = source_object;
+ IdeProjectFiles *files;
+ IdeProjectItem *item;
+ IdeContext *context;
+ IdeVcs *vcs;
+ RenameFile *op = task_data;
+ g_autoptr(GFileInfo) file_info = NULL;
+ g_autofree gchar *path = NULL;
+ GError *error = NULL;
+ GFile *workdir;
+
+ g_assert (IDE_IS_PROJECT (self));
+ g_assert (op != NULL);
+ g_assert (G_IS_FILE (op->orig_file));
+ g_assert (G_IS_FILE (op->new_file));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ ide_project_writer_lock (self);
+
+ files = ide_project_get_files (self);
+ context = ide_object_get_context (IDE_OBJECT (self));
+ vcs = ide_context_get_vcs (context);
+ workdir = ide_vcs_get_working_directory (vcs);
+ path = g_file_get_relative_path (workdir, op->new_file);
+
+#ifndef IDE_DISABLE_TRACE
+ {
+ gchar *old_path = g_file_get_uri (op->orig_file);
+ gchar *new_path = g_file_get_uri (op->new_file);
+ IDE_TRACE_MSG ("Renaming %s to %s", old_path, new_path);
+ g_free (old_path);
+ g_free (new_path);
+ }
+#endif
+
+ if (path == NULL)
+ {
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_FILENAME,
+ _("Destination file must be within the project tree."));
+ goto cleanup;
+ }
+
+ item = ide_project_files_find_file (files, op->orig_file);
+
+ if (item == NULL)
+ {
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_FILENAME,
+ _("Source file must be within the project tree."));
+ goto cleanup;
+ }
+
+ if (!g_file_move (op->orig_file, op->new_file, G_FILE_COPY_NONE, cancellable, NULL, NULL, &error))
+ {
+ g_task_return_error (task, error);
+ goto cleanup;
+ }
+
+ file_info = g_file_query_info (op->new_file,
+ G_FILE_ATTRIBUTE_STANDARD_NAME","
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME","
+ G_FILE_ATTRIBUTE_STANDARD_TYPE,
+ G_FILE_QUERY_INFO_NONE,
+ cancellable,
+ &error);
+
+ if (file_info == NULL)
+ {
+ g_task_return_error (task, error);
+ goto cleanup;
+ }
+
+ g_object_ref (item);
+ ide_project_item_remove (ide_project_item_get_parent (item), item);
+ g_object_set (item,
+ "file", op->new_file,
+ "path", path,
+ "file-info", file_info,
+ NULL);
+ ide_project_files_add_file (files, IDE_PROJECT_FILE (item));
+ g_object_unref (item);
+
+ g_task_return_boolean (task, TRUE);
+
+cleanup:
+ ide_project_writer_unlock (self);
+}
+
+static void
+rename_file_free (gpointer data)
+{
+ RenameFile *op = data;
+
+ if (op != NULL)
+ {
+ g_object_unref (op->new_file);
+ g_object_unref (op->orig_file);
+ g_slice_free (RenameFile, op);
+ }
+}
+
+void
+ide_project_rename_file_async (IdeProject *self,
+ GFile *orig_file,
+ GFile *new_file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+ RenameFile *op;
+
+ g_return_if_fail (IDE_IS_PROJECT (self));
+ g_return_if_fail (G_IS_FILE (orig_file));
+ g_return_if_fail (G_IS_FILE (new_file));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ op = g_slice_new0 (RenameFile);
+ op->orig_file = g_object_ref (orig_file);
+ op->new_file = g_object_ref (new_file);
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_task_data (task, op, rename_file_free);
+ g_task_run_in_thread (task, ide_project_rename_file_worker);
+}
+
+gboolean
+ide_project_rename_file_finish (IdeProject *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ GTask *task = (GTask *)result;
+
+ g_return_val_if_fail (IDE_IS_PROJECT (self), FALSE);
+ g_return_val_if_fail (G_IS_TASK (task), FALSE);
+
+ return g_task_propagate_boolean (task, error);
+}
diff --git a/libide/ide-project.h b/libide/ide-project.h
index 3fef16f..f631478 100644
--- a/libide/ide-project.h
+++ b/libide/ide-project.h
@@ -33,19 +33,28 @@ struct _IdeProjectClass
IdeObjectClass parent;
};
-IdeProjectItem *ide_project_get_root (IdeProject *project);
-const gchar *ide_project_get_name (IdeProject *project);
-IdeFile *ide_project_get_file_for_path (IdeProject *project,
- const gchar *path);
-IdeFile *ide_project_get_project_file (IdeProject *self,
- GFile *gfile);
-void ide_project_reader_lock (IdeProject *project);
-void ide_project_reader_unlock (IdeProject *project);
-void ide_project_writer_lock (IdeProject *project);
-void ide_project_writer_unlock (IdeProject *project);
-void ide_project_add_file (IdeProject *project,
- IdeProjectFile *file);
-IdeProjectFiles *ide_project_get_files (IdeProject *self);
+IdeProjectItem *ide_project_get_root (IdeProject *project);
+const gchar *ide_project_get_name (IdeProject *project);
+IdeFile *ide_project_get_file_for_path (IdeProject *project,
+ const gchar *path);
+IdeFile *ide_project_get_project_file (IdeProject *self,
+ GFile *gfile);
+void ide_project_reader_lock (IdeProject *project);
+void ide_project_reader_unlock (IdeProject *project);
+void ide_project_writer_lock (IdeProject *project);
+void ide_project_writer_unlock (IdeProject *project);
+void ide_project_add_file (IdeProject *project,
+ IdeProjectFile *file);
+IdeProjectFiles *ide_project_get_files (IdeProject *self);
+void ide_project_rename_file_async (IdeProject *self,
+ GFile *orig_file,
+ GFile *new_file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean ide_project_rename_file_finish (IdeProject *project,
+ GAsyncResult *result,
+ GError **error);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]