[gnome-builder/wip/project-selector: 4/10] autotools: add basic autotools project miner



commit ef110315676e1e037af7ed93896d6c5f21d7e326
Author: Christian Hergert <christian hergert me>
Date:   Sun Mar 29 22:33:42 2015 -0700

    autotools: add basic autotools project miner

 .gitignore                                     |    1 +
 libide/Makefile.am                             |    2 +
 libide/autotools/ide-autotools-project-miner.c |  320 ++++++++++++++++++++++++
 libide/autotools/ide-autotools-project-miner.h |   37 +++
 tools/Makefile.am                              |    5 +
 tools/ide-mine-projects.c                      |   83 ++++++
 6 files changed, 448 insertions(+), 0 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index fdcf05a..bc7a1d6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,6 +31,7 @@ ide-list-devices
 ide-list-diagnostics
 ide-list-file-settings
 ide-list-files
+ide-mine-projects
 ide-search
 intltool-extract.in
 intltool-merge.in
diff --git a/libide/Makefile.am b/libide/Makefile.am
index a239fdb..5129c8e 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -9,6 +9,8 @@ libide_1_0_la_public_sources = \
        libide/autotools/ide-autotools-build-task.h \
        libide/autotools/ide-autotools-builder.c \
        libide/autotools/ide-autotools-builder.h \
+       libide/autotools/ide-autotools-project-miner.c \
+       libide/autotools/ide-autotools-project-miner.h \
        libide/c/ide-c-indenter.c \
        libide/c/ide-c-indenter.h \
        libide/c/ide-c-language.c \
diff --git a/libide/autotools/ide-autotools-project-miner.c b/libide/autotools/ide-autotools-project-miner.c
new file mode 100644
index 0000000..8cfd07b
--- /dev/null
+++ b/libide/autotools/ide-autotools-project-miner.c
@@ -0,0 +1,320 @@
+/* ide-autotools-project-miner.c
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define G_LOG_DOMAIN "ide-autotools-project-miner"
+
+#include <glib/gi18n.h>
+
+#include "ide-autotools-project-miner.h"
+#include "ide-debug.h"
+
+#define MAX_MINE_DEPTH 5
+
+struct _IdeAutotoolsProjectMiner
+{
+  IdeProjectMiner  parent_instance;
+  GFile           *root_directory;
+};
+
+G_DEFINE_TYPE (IdeAutotoolsProjectMiner, ide_autotools_project_miner, IDE_TYPE_PROJECT_MINER)
+
+enum {
+  PROP_0,
+  PROP_ROOT_DIRECTORY,
+  LAST_PROP
+};
+
+static GParamSpec *gParamSpecs [LAST_PROP];
+
+static void
+ide_autotools_project_miner_discovered (IdeAutotoolsProjectMiner *self,
+                                        GFile                    *directory,
+                                        GFileInfo                *file_info)
+{
+  g_autofree gchar *uri = NULL;
+  g_autofree gchar *name = NULL;
+  g_autoptr(GFile) file = NULL;
+  g_autoptr(IdeProjectInfo) project_info = NULL;
+  const gchar *filename;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_AUTOTOOLS_PROJECT_MINER (self));
+  g_assert (G_IS_FILE (directory));
+  g_assert (G_IS_FILE_INFO (file_info));
+
+  uri = g_file_get_uri (directory);
+  g_debug ("Discovered autotools project at %s", uri);
+
+  filename = g_file_info_get_attribute_byte_string (file_info, G_FILE_ATTRIBUTE_STANDARD_NAME);
+  file = g_file_get_child (directory, filename);
+  name = g_file_get_basename (directory);
+
+  project_info = g_object_new (IDE_TYPE_PROJECT_INFO,
+                               "directory", directory,
+                               "file", file,
+                               "name", name,
+                               NULL);
+
+  ide_project_miner_emit_discovered (IDE_PROJECT_MINER (self), project_info);
+
+  IDE_EXIT;
+}
+
+static void
+ide_autotools_project_miner_mine_directory (IdeAutotoolsProjectMiner *self,
+                                            GFile                    *directory,
+                                            guint                     depth,
+                                            GCancellable             *cancellable)
+{
+  g_autoptr(GFileEnumerator) file_enum = NULL;
+  GFileInfo *file_info;
+
+  g_assert (IDE_IS_AUTOTOOLS_PROJECT_MINER (self));
+  g_assert (G_IS_FILE (directory));
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  if (depth == MAX_MINE_DEPTH)
+    return;
+
+#ifndef IDE_DISABLE_TRACE
+  {
+    g_autofree gchar *uri = NULL;
+
+    uri = g_file_get_uri (directory);
+    IDE_TRACE_MSG ("Mining directory %s", uri);
+  }
+#endif
+
+  file_enum = g_file_enumerate_children (directory,
+                                         G_FILE_ATTRIBUTE_STANDARD_NAME","
+                                         G_FILE_ATTRIBUTE_STANDARD_TYPE,
+                                         G_FILE_QUERY_INFO_NONE,
+                                         cancellable,
+                                         NULL);
+
+  if (file_enum == NULL)
+    return;
+
+  while ((file_info = g_file_enumerator_next_file (file_enum, cancellable, NULL)))
+    {
+      const gchar *filename;
+      GFileType file_type;
+      GFile *child;
+
+      file_type = g_file_info_get_attribute_uint32 (file_info, G_FILE_ATTRIBUTE_STANDARD_TYPE);
+      filename = g_file_info_get_attribute_byte_string (file_info, G_FILE_ATTRIBUTE_STANDARD_NAME);
+
+      if (filename && filename [0] == '.')
+        goto cleanup;
+
+      switch (file_type)
+        {
+        case G_FILE_TYPE_DIRECTORY:
+          child = g_file_get_child (directory, filename);
+          ide_autotools_project_miner_mine_directory (self, child, depth + 1, cancellable);
+          g_clear_object (&child);
+          break;
+
+        case G_FILE_TYPE_REGULAR:
+          if ((0 == g_strcmp0 (filename, "configure.ac")) ||
+              (0 == g_strcmp0 (filename, "configure.in")))
+            {
+              ide_autotools_project_miner_discovered (self, directory, file_info);
+              g_clear_object (&file_info);
+              return;
+            }
+          break;
+
+        case G_FILE_TYPE_UNKNOWN:
+        case G_FILE_TYPE_SYMBOLIC_LINK:
+        case G_FILE_TYPE_SPECIAL:
+        case G_FILE_TYPE_SHORTCUT:
+        case G_FILE_TYPE_MOUNTABLE:
+        default:
+          break;
+        }
+
+    cleanup:
+      g_object_unref (file_info);
+    }
+}
+
+static void
+ide_autotools_project_miner_worker (GTask        *task,
+                                    gpointer      source_object,
+                                    gpointer      task_data,
+                                    GCancellable *cancellable)
+{
+  IdeAutotoolsProjectMiner *self = source_object;
+  GFile *directory = task_data;
+
+  IDE_ENTRY;
+
+  g_assert (G_IS_TASK (task));
+  g_assert (IDE_IS_AUTOTOOLS_PROJECT_MINER (self));
+  g_assert (G_IS_FILE (directory));
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  ide_autotools_project_miner_mine_directory (self, directory, 0, cancellable);
+
+  g_task_return_boolean (task, TRUE);
+
+  IDE_EXIT;
+}
+
+static void
+ide_autotools_project_miner_mine_async (IdeProjectMiner     *miner,
+                                        GCancellable        *cancellable,
+                                        GAsyncReadyCallback  callback,
+                                        gpointer             user_data)
+{
+  IdeAutotoolsProjectMiner *self = (IdeAutotoolsProjectMiner *)miner;
+  g_autoptr(GTask) task = NULL;
+  g_autoptr(GFile) directory = NULL;
+
+  g_assert (IDE_IS_AUTOTOOLS_PROJECT_MINER (self));
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = g_task_new (miner, cancellable, callback, user_data);
+
+  directory = g_file_new_for_path (g_get_home_dir ());
+
+  if (self->root_directory)
+    g_task_set_task_data (task, g_object_ref (self->root_directory), g_object_unref);
+  else
+    g_task_set_task_data (task, g_object_ref (directory), g_object_unref);
+
+  g_task_run_in_thread (task, ide_autotools_project_miner_worker);
+}
+
+static gboolean
+ide_autotools_project_miner_mine_finish (IdeProjectMiner  *miner,
+                                         GAsyncResult     *result,
+                                         GError          **error)
+{
+  GTask *task = (GTask *)result;
+
+  g_assert (IDE_IS_AUTOTOOLS_PROJECT_MINER (miner));
+  g_assert (G_IS_TASK (task));
+
+  return g_task_propagate_boolean (task, error);
+}
+
+static void
+ide_autotools_project_miner_finalize (GObject *object)
+{
+  IdeAutotoolsProjectMiner *self = (IdeAutotoolsProjectMiner *)object;
+
+  g_clear_object (&self->root_directory);
+
+  G_OBJECT_CLASS (ide_autotools_project_miner_parent_class)->finalize (object);
+}
+
+static void
+ide_autotools_project_miner_get_property (GObject    *object,
+                                          guint       prop_id,
+                                          GValue     *value,
+                                          GParamSpec *pspec)
+{
+  IdeAutotoolsProjectMiner *self = IDE_AUTOTOOLS_PROJECT_MINER (object);
+
+  switch (prop_id)
+    {
+    case PROP_ROOT_DIRECTORY:
+      g_value_set_object (value, ide_autotools_project_miner_get_root_directory (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_autotools_project_miner_set_property (GObject      *object,
+                                          guint         prop_id,
+                                          const GValue *value,
+                                          GParamSpec   *pspec)
+{
+  IdeAutotoolsProjectMiner *self = IDE_AUTOTOOLS_PROJECT_MINER (object);
+
+  switch (prop_id)
+    {
+    case PROP_ROOT_DIRECTORY:
+      ide_autotools_project_miner_set_root_directory (self, g_value_get_object (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_autotools_project_miner_class_init (IdeAutotoolsProjectMinerClass *klass)
+{
+  IdeProjectMinerClass *miner_class = IDE_PROJECT_MINER_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = ide_autotools_project_miner_finalize;
+  object_class->get_property = ide_autotools_project_miner_get_property;
+  object_class->set_property = ide_autotools_project_miner_set_property;
+
+  miner_class->mine_async = ide_autotools_project_miner_mine_async;
+  miner_class->mine_finish = ide_autotools_project_miner_mine_finish;
+
+  gParamSpecs [PROP_ROOT_DIRECTORY] =
+    g_param_spec_object ("root-directory",
+                         _("Root Directory"),
+                         _("The root directory to scan from."),
+                         G_TYPE_FILE,
+                         (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (object_class, PROP_ROOT_DIRECTORY,
+                                   gParamSpecs [PROP_ROOT_DIRECTORY]);
+}
+
+static void
+ide_autotools_project_miner_init (IdeAutotoolsProjectMiner *self)
+{
+}
+
+/**
+ * ide_autotools_project_miner_get_root_directory:
+ *
+ * Gets the IdeAutotoolsProjectMiner:root-directory property.
+ * Scans will start from this directory.
+ *
+ * Returns: (transfer none) (nullable): A #GFile or %NULL.
+ */
+GFile *
+ide_autotools_project_miner_get_root_directory (IdeAutotoolsProjectMiner *self)
+{
+  g_return_val_if_fail (IDE_IS_AUTOTOOLS_PROJECT_MINER (self), NULL);
+
+  return self->root_directory;
+}
+
+void
+ide_autotools_project_miner_set_root_directory (IdeAutotoolsProjectMiner *self,
+                                                GFile                    *root_directory)
+{
+  g_return_if_fail (IDE_IS_AUTOTOOLS_PROJECT_MINER (self));
+  g_return_if_fail (!root_directory || G_IS_FILE (root_directory));
+
+  if (g_set_object (&self->root_directory, root_directory))
+    g_object_notify_by_pspec (G_OBJECT (self), gParamSpecs [PROP_ROOT_DIRECTORY]);
+}
diff --git a/libide/autotools/ide-autotools-project-miner.h b/libide/autotools/ide-autotools-project-miner.h
new file mode 100644
index 0000000..fc98884
--- /dev/null
+++ b/libide/autotools/ide-autotools-project-miner.h
@@ -0,0 +1,37 @@
+/* ide-autotools-project-miner.h
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef IDE_AUTOTOOLS_PROJECT_MINER_H
+#define IDE_AUTOTOOLS_PROJECT_MINER_H
+
+#include "ide-project-miner.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_AUTOTOOLS_PROJECT_MINER (ide_autotools_project_miner_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeAutotoolsProjectMiner, ide_autotools_project_miner,
+                      IDE, AUTOTOOLS_PROJECT_MINER, IdeProjectMiner)
+
+GFile *ide_autotools_project_miner_get_root_directory (IdeAutotoolsProjectMiner *self);
+void   ide_autotools_project_miner_set_root_directory (IdeAutotoolsProjectMiner *self,
+                                                       GFile                    *root_directory);
+
+G_END_DECLS
+
+#endif /* IDE_AUTOTOOLS_PROJECT_MINER_H */
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 88641bc..e9abfad 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -33,3 +33,8 @@ noinst_PROGRAMS += ide-search
 ide_search_SOURCES = tools/ide-search.c
 ide_search_CFLAGS = $(libide_1_0_la_CFLAGS)
 ide_search_LDADD = libide-1.0.la $(LIBIDE_LIBS)
+
+noinst_PROGRAMS += ide-mine-projects
+ide_mine_projects_SOURCES = tools/ide-mine-projects.c
+ide_mine_projects_CFLAGS = $(libide_1_0_la_CFLAGS)
+ide_mine_projects_LDADD = libide-1.0.la $(LIBIDE_LIBS)
diff --git a/tools/ide-mine-projects.c b/tools/ide-mine-projects.c
new file mode 100644
index 0000000..4e68eab
--- /dev/null
+++ b/tools/ide-mine-projects.c
@@ -0,0 +1,83 @@
+/* ide-mine-projects.c
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n.h>
+#include <ide.h>
+
+#include "ide-project-miner.h"
+#include "autotools/ide-autotools-project-miner.h"
+
+static void
+mine_cb (GObject      *object,
+         GAsyncResult *result,
+         gpointer      user_data)
+{
+  IdeProjectMiner *miner = (IdeProjectMiner *)object;
+  g_autoptr(GError) error = NULL;
+  GMainLoop *main_loop = user_data;
+
+  if (!ide_project_miner_mine_finish (miner, result, &error))
+    g_warning ("%s", error->message);
+
+  g_main_loop_quit (main_loop);
+}
+
+static gboolean
+verbose_cb (void)
+{
+  ide_log_increase_verbosity ();
+  return TRUE;
+}
+
+int
+main (int    argc,
+      gchar *argv[])
+{
+  static const GOptionEntry entries[] = {
+    { "verbose", 'v', G_OPTION_FLAG_NO_ARG|G_OPTION_FLAG_IN_MAIN,
+      G_OPTION_ARG_CALLBACK, verbose_cb },
+    { NULL }
+  };
+  IdeProjectMiner *miner;
+  GOptionContext *context;
+  GMainLoop *main_loop;
+  GError *error = NULL;
+
+  ide_log_init (TRUE, NULL);
+
+  context = g_option_context_new (_("- discover projects"));
+  g_option_context_add_main_entries (context, entries, NULL);
+
+  if (!g_option_context_parse (context, &argc, &argv, &error))
+    {
+      g_printerr ("%s\n", error->message);
+      return EXIT_FAILURE;
+    }
+
+  miner = g_object_new (IDE_TYPE_AUTOTOOLS_PROJECT_MINER,
+                        "root-directory", NULL,
+                        NULL);
+  main_loop = g_main_loop_new (NULL, FALSE);
+  ide_project_miner_mine_async (miner, NULL, mine_cb, main_loop);
+  g_main_loop_run (main_loop);
+  g_main_loop_unref (main_loop);
+
+  ide_log_shutdown ();
+
+  return 0;
+}


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