~codygarver/+junk/gnome-builder

« back to all changes in this revision

Viewing changes to libide/ide-project-files.c

  • Committer: Cody Garver
  • Date: 2015-11-21 00:50:38 UTC
  • Revision ID: cody@elementary.io-20151121005038-8wygis63zt0ljqlz
Import https://github.com/chergert/gnome-builder 06e3158922a02a27f4abca250d70aa7b2970e06a

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ide-project-files.c
 
2
 *
 
3
 * Copyright (C) 2015 Christian Hergert <christian@hergert.me>
 
4
 *
 
5
 * This program is free software: you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation, either version 3 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
 */
 
18
 
 
19
#include "ide-context.h"
 
20
#include "ide-project-file.h"
 
21
#include "ide-project-files.h"
 
22
#include "ide-vcs.h"
 
23
 
 
24
typedef struct
 
25
{
 
26
  GHashTable *files_by_path;
 
27
} IdeProjectFilesPrivate;
 
28
 
 
29
G_DEFINE_TYPE_WITH_PRIVATE (IdeProjectFiles, ide_project_files,
 
30
                            IDE_TYPE_PROJECT_ITEM)
 
31
 
 
32
static void
 
33
ide_project_files_dispose (GObject *object)
 
34
{
 
35
  IdeProjectFiles *self = (IdeProjectFiles *)object;
 
36
  IdeProjectFilesPrivate *priv = ide_project_files_get_instance_private (self);
 
37
 
 
38
  g_clear_pointer (&priv->files_by_path, g_hash_table_unref);
 
39
 
 
40
  G_OBJECT_CLASS (ide_project_files_parent_class)->dispose (object);
 
41
}
 
42
 
 
43
static void
 
44
ide_project_files_class_init (IdeProjectFilesClass *klass)
 
45
{
 
46
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
47
 
 
48
  object_class->dispose = ide_project_files_dispose;
 
49
}
 
50
 
 
51
static void
 
52
ide_project_files_init (IdeProjectFiles *self)
 
53
{
 
54
  IdeProjectFilesPrivate *priv = ide_project_files_get_instance_private (self);
 
55
 
 
56
  priv->files_by_path = g_hash_table_new_full (g_str_hash, g_str_equal,
 
57
                                               g_free, g_object_unref);
 
58
}
 
59
 
 
60
static IdeProjectItem *
 
61
ide_project_files_find_child (IdeProjectItem *item,
 
62
                              const gchar    *child)
 
63
{
 
64
  GSequence *children;
 
65
  GSequenceIter *iter;
 
66
 
 
67
  g_assert (IDE_IS_PROJECT_ITEM (item));
 
68
  g_assert (child);
 
69
 
 
70
  children = ide_project_item_get_children (item);
 
71
  if (!children)
 
72
    return NULL;
 
73
 
 
74
  for (iter = g_sequence_get_begin_iter (children);
 
75
       !g_sequence_iter_is_end (iter);
 
76
       iter = g_sequence_iter_next (iter))
 
77
    {
 
78
      IdeProjectItem *current_item = g_sequence_get (iter);
 
79
 
 
80
      if (IDE_IS_PROJECT_FILE (current_item))
 
81
        {
 
82
          IdeProjectFile *file;
 
83
          const gchar *name;
 
84
 
 
85
          file = IDE_PROJECT_FILE (current_item);
 
86
          name = ide_project_file_get_name (file);
 
87
 
 
88
          if (g_strcmp0 (name, child) == 0)
 
89
            return current_item;
 
90
        }
 
91
    }
 
92
 
 
93
  return NULL;
 
94
}
 
95
 
 
96
/**
 
97
 * ide_project_files_find_file:
 
98
 * @self: (in): A #IdeProjectFiles.
 
99
 * @file: A #GFile.
 
100
 *
 
101
 * Tries to locate an #IdeProjectFile matching the given file.
 
102
 * If @file is the working directory, @self is returned.
 
103
 *
 
104
 * Returns: (transfer none) (nullable): An #IdeProjectItem or %NULL.
 
105
 */
 
106
IdeProjectItem *
 
107
ide_project_files_find_file (IdeProjectFiles *self,
 
108
                             GFile           *file)
 
109
{
 
110
  IdeProjectItem *item;
 
111
  IdeContext *context;
 
112
  IdeVcs *vcs;
 
113
  GFile *workdir;
 
114
  gchar **parts;
 
115
  gchar *path;
 
116
  gsize i;
 
117
 
 
118
  g_return_val_if_fail (IDE_IS_PROJECT_FILES (self), NULL);
 
119
  g_return_val_if_fail (G_IS_FILE (file), NULL);
 
120
 
 
121
  item = IDE_PROJECT_ITEM (self);
 
122
  context = ide_object_get_context (IDE_OBJECT (self));
 
123
  vcs = ide_context_get_vcs (context);
 
124
  workdir = ide_vcs_get_working_directory (vcs);
 
125
 
 
126
  if (g_file_equal (workdir, file))
 
127
    return IDE_PROJECT_ITEM (self);
 
128
 
 
129
  path = g_file_get_relative_path (workdir, file);
 
130
  if (path == NULL)
 
131
    return NULL;
 
132
 
 
133
  parts = g_strsplit (path, G_DIR_SEPARATOR_S, 0);
 
134
 
 
135
  for (i = 0; parts [i]; i++)
 
136
    {
 
137
      if (!(item = ide_project_files_find_child (item, parts [i])))
 
138
        break;
 
139
    }
 
140
 
 
141
  g_strfreev (parts);
 
142
  g_free (path);
 
143
 
 
144
  return item;
 
145
}
 
146
 
 
147
/**
 
148
 * ide_project_files_get_file_for_path:
 
149
 *
 
150
 * Retrieves an #IdeFile for the path. If no such path exists within the
 
151
 * project, %NULL is returned.
 
152
 *
 
153
 * Returns: (transfer full) (nullable): An #IdeFile or %NULL.
 
154
 */
 
155
IdeFile *
 
156
ide_project_files_get_file_for_path (IdeProjectFiles *self,
 
157
                                     const gchar     *path)
 
158
{
 
159
  IdeProjectFilesPrivate *priv = ide_project_files_get_instance_private (self);
 
160
  IdeProjectItem *item = (IdeProjectItem *)self;
 
161
  IdeFile *file = NULL;
 
162
  gchar **parts;
 
163
  gsize i;
 
164
 
 
165
  g_return_val_if_fail (IDE_IS_PROJECT_FILES (self), NULL);
 
166
 
 
167
  if ((file = g_hash_table_lookup (priv->files_by_path, path)))
 
168
    return g_object_ref (file);
 
169
 
 
170
  parts = g_strsplit (path, G_DIR_SEPARATOR_S, 0);
 
171
 
 
172
  for (i = 0; item && parts [i]; i++)
 
173
    item = ide_project_files_find_child (item, parts [i]);
 
174
 
 
175
  if (item)
 
176
    {
 
177
      IdeContext *context;
 
178
      const gchar *file_path;
 
179
      GFile *gfile;
 
180
 
 
181
      context = ide_object_get_context (IDE_OBJECT (self));
 
182
      gfile = ide_project_file_get_file (IDE_PROJECT_FILE (item));
 
183
      file_path = ide_project_file_get_path (IDE_PROJECT_FILE (item));
 
184
      file = g_object_new (IDE_TYPE_FILE,
 
185
                           "context", context,
 
186
                           "file", gfile,
 
187
                           "path", file_path,
 
188
                           NULL);
 
189
      if (file)
 
190
        g_hash_table_insert (priv->files_by_path, g_strdup (file_path), g_object_ref (file));
 
191
    }
 
192
 
 
193
  return file;
 
194
}
 
195
 
 
196
void
 
197
ide_project_files_add_file (IdeProjectFiles *self,
 
198
                            IdeProjectFile  *file)
 
199
{
 
200
  IdeProjectItem *item = (IdeProjectItem *)self;
 
201
  g_autoptr(GFile) parent = NULL;
 
202
  g_autofree gchar *path = NULL;
 
203
  IdeContext *context;
 
204
  IdeVcs *vcs;
 
205
  GFile *workdir;
 
206
  GFile *gfile;
 
207
  gchar **parts;
 
208
  gsize i;
 
209
 
 
210
  g_return_if_fail (IDE_IS_PROJECT_FILES (self));
 
211
  g_return_if_fail (IDE_IS_PROJECT_FILE (file));
 
212
 
 
213
  context = ide_object_get_context (IDE_OBJECT (self));
 
214
  vcs = ide_context_get_vcs (context);
 
215
  workdir = ide_vcs_get_working_directory (vcs);
 
216
 
 
217
  gfile = ide_project_file_get_file (file);
 
218
  parent = g_file_get_parent (gfile);
 
219
  path = g_file_get_relative_path (workdir, parent);
 
220
 
 
221
  if (path == NULL)
 
222
  {
 
223
    ide_project_item_append (IDE_PROJECT_ITEM (self), IDE_PROJECT_ITEM (file));
 
224
    return;
 
225
  }
 
226
 
 
227
  parts = g_strsplit (path, G_DIR_SEPARATOR_S, 0);
 
228
 
 
229
  for (i = 0; parts [i]; i++)
 
230
    {
 
231
      IdeProjectItem *found;
 
232
 
 
233
      found = ide_project_files_find_child (item, parts [i]);
 
234
 
 
235
      if (found == NULL)
 
236
        {
 
237
          g_autoptr(GFileInfo) file_info = NULL;
 
238
          g_autofree gchar *child_path = NULL;
 
239
          IdeProjectItem *child;
 
240
          const gchar *item_path;
 
241
          g_autoptr(GFile) item_file = NULL;
 
242
 
 
243
          file_info = g_file_info_new ();
 
244
          g_file_info_set_file_type (file_info, G_FILE_TYPE_DIRECTORY);
 
245
          g_file_info_set_display_name (file_info, parts [i]);
 
246
          g_file_info_set_name (file_info, parts [i]);
 
247
 
 
248
          item_path = ide_project_file_get_path (IDE_PROJECT_FILE (item));
 
249
          child_path = g_strjoin (G_DIR_SEPARATOR_S, item_path, parts [i], NULL);
 
250
          item_file = g_file_get_child (workdir, child_path);
 
251
 
 
252
          child = g_object_new (IDE_TYPE_PROJECT_FILE,
 
253
                                "context", context,
 
254
                                "parent", item,
 
255
                                "path", path,
 
256
                                "file", item_file,
 
257
                                "file-info", file_info,
 
258
                                NULL);
 
259
          ide_project_item_append (item, child);
 
260
 
 
261
          item = child;
 
262
        }
 
263
      else
 
264
        {
 
265
          item = found;
 
266
        }
 
267
    }
 
268
 
 
269
  ide_project_item_append (item, IDE_PROJECT_ITEM (file));
 
270
 
 
271
  g_strfreev (parts);
 
272
 
 
273
}