2 * evolution-source-registry-migrate-basedir.c
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) version 3.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with the program; if not, see <http://www.gnu.org/licenses/>
20 #include <glib/gstdio.h>
21 #include <libedataserver/libedataserver.h>
23 /* Forward Declarations */
24 void evolution_source_registry_migrate_basedir (void);
27 migrate_rename (const gchar *old_filename,
28 const gchar *new_filename)
30 gboolean old_filename_is_dir;
31 gboolean old_filename_exists;
32 gboolean new_filename_exists;
33 gboolean success = TRUE;
35 old_filename_is_dir = g_file_test (old_filename, G_FILE_TEST_IS_DIR);
36 old_filename_exists = g_file_test (old_filename, G_FILE_TEST_EXISTS);
37 new_filename_exists = g_file_test (new_filename, G_FILE_TEST_EXISTS);
39 if (!old_filename_exists)
42 g_print (" mv %s %s\n", old_filename, new_filename);
44 /* It's safe to go ahead and move directories because rename()
45 * will fail if the new directory already exists with content.
46 * With regular files we have to be careful not to overwrite
47 * new files with old files. */
48 if (old_filename_is_dir || !new_filename_exists) {
49 if (g_rename (old_filename, new_filename) < 0) {
50 g_printerr (" FAILED: %s\n", g_strerror (errno));
54 g_printerr (" FAILED: Destination file already exists\n");
62 migrate_rmdir (const gchar *dirname)
65 gboolean success = TRUE;
67 if (g_file_test (dirname, G_FILE_TEST_IS_DIR)) {
68 g_print (" rmdir %s\n", dirname);
69 if (g_rmdir (dirname) < 0) {
70 g_printerr (" FAILED: %s", g_strerror (errno));
71 if (errno == ENOTEMPTY) {
72 dir = g_dir_open (dirname, 0, NULL);
73 g_printerr (" (contents follows)");
80 /* List the directory's contents to aid debugging. */
82 const gchar *basename;
84 /* Align the filenames beneath the error message. */
85 while ((basename = g_dir_read_name (dir)) != NULL)
86 g_print (" %s\n", basename);
95 migrate_process_corrections (GHashTable *corrections)
98 gpointer old_filename;
99 gpointer new_filename;
101 g_hash_table_iter_init (&iter, corrections);
103 while (g_hash_table_iter_next (&iter, &old_filename, &new_filename)) {
104 migrate_rename (old_filename, new_filename);
105 g_hash_table_iter_remove (&iter);
110 migrate_move_contents (const gchar *src_directory,
111 const gchar *dst_directory)
114 GHashTable *corrections;
115 const gchar *basename;
117 dir = g_dir_open (src_directory, 0, NULL);
121 /* This is to avoid renaming files while we're iterating over the
122 * directory. POSIX says the outcome of that is unspecified. */
123 corrections = g_hash_table_new_full (
124 g_str_hash, g_str_equal,
125 (GDestroyNotify) g_free,
126 (GDestroyNotify) g_free);
128 g_mkdir_with_parents (dst_directory, 0700);
130 while ((basename = g_dir_read_name (dir)) != NULL) {
134 old_filename = g_build_filename (src_directory, basename, NULL);
135 new_filename = g_build_filename (dst_directory, basename, NULL);
137 g_hash_table_insert (corrections, old_filename, new_filename);
142 migrate_process_corrections (corrections);
143 g_hash_table_destroy (corrections);
145 /* It's tempting to want to remove the source directory here.
146 * Don't. We might be iterating over the source directory's
147 * parent directory, and removing the source directory would
148 * screw up the iteration. */
154 migrate_fix_exchange_bug (const gchar *old_base_dir)
157 GHashTable *corrections;
158 const gchar *basename;
160 gchar *old_cache_dir;
162 /* The exchange backend mistakenly cached calendar attachments in
163 * ~/.evolution/exchange instead of ~/.evolution/cache/calendar.
164 * Fix that before we migrate the cache directory. */
166 exchange_dir = g_build_filename (old_base_dir, "exchange", NULL);
167 old_cache_dir = g_build_filename (old_base_dir, "cache", "calendar", NULL);
169 dir = g_dir_open (exchange_dir, 0, NULL);
173 /* This is to avoid renaming files while we're iterating over the
174 * directory. POSIX says the outcome of that is unspecified. */
175 corrections = g_hash_table_new_full (
176 g_str_hash, g_str_equal,
177 (GDestroyNotify) g_free,
178 (GDestroyNotify) g_free);
180 while ((basename = g_dir_read_name (dir)) != NULL) {
184 if (!g_str_has_prefix (basename, "exchange___"))
187 old_filename = g_build_filename (exchange_dir, basename, NULL);
188 new_filename = g_build_filename (old_cache_dir, basename, NULL);
190 g_hash_table_insert (corrections, old_filename, new_filename);
195 migrate_process_corrections (corrections);
196 g_hash_table_destroy (corrections);
199 g_free (exchange_dir);
200 g_free (old_cache_dir);
204 migrate_fix_memos_cache_bug (const gchar *old_base_dir)
206 gchar *src_directory;
207 gchar *dst_directory;
209 /* Some calendar backends cached memo data under
210 * ~/.evolution/cache/journal instead of ~/.evolution/cache/memos.
211 * Fix that before we migrate the cache directory. */
213 src_directory = g_build_filename (old_base_dir, "cache", "journal", NULL);
214 dst_directory = g_build_filename (old_base_dir, "cache", "memos", NULL);
216 migrate_move_contents (src_directory, dst_directory);
217 migrate_rmdir (src_directory);
219 g_free (src_directory);
220 g_free (dst_directory);
224 migrate_fix_groupwise_bug (const gchar *old_base_dir)
227 GHashTable *corrections;
228 const gchar *basename;
230 gchar *old_cache_dir;
232 /* The groupwise backend mistakenly put its addressbook
233 * cache files in ~/.evolution/addressbook instead of
234 * ~/.evolution/cache/addressbook. Fix that before
235 * we migrate the cache directory. */
237 old_data_dir = g_build_filename (old_base_dir, "addressbook", NULL);
238 old_cache_dir = g_build_filename (old_base_dir, "cache", "addressbook", NULL);
240 dir = g_dir_open (old_data_dir, 0, NULL);
244 /* This is to avoid renaming files while we're iterating over the
245 * directory. POSIX says the outcome of that is unspecified. */
246 corrections = g_hash_table_new_full (
247 g_str_hash, g_str_equal,
248 (GDestroyNotify) g_free,
249 (GDestroyNotify) g_free);
251 while ((basename = g_dir_read_name (dir)) != NULL) {
255 if (!g_str_has_prefix (basename, "groupwise___"))
258 old_filename = g_build_filename (old_data_dir, basename, NULL);
259 new_filename = g_build_filename (old_cache_dir, basename, NULL);
261 g_hash_table_insert (corrections, old_filename, new_filename);
266 migrate_process_corrections (corrections);
267 g_hash_table_destroy (corrections);
270 g_free (old_data_dir);
271 g_free (old_cache_dir);
275 migrate_to_user_cache_dir (const gchar *old_base_dir)
277 const gchar *new_cache_dir;
278 gchar *old_cache_dir;
279 gchar *src_directory;
280 gchar *dst_directory;
282 old_cache_dir = g_build_filename (old_base_dir, "cache", NULL);
283 new_cache_dir = e_get_user_cache_dir ();
285 g_print ("Migrating cached backend data\n");
287 /* We don't want to move the source directory directly because the
288 * destination directory may already exist with content. Instead
289 * we want to merge the content of the source directory into the
290 * destination directory.
292 * For example, given:
294 * $(src_directory)/A and $(dst_directory)/B
297 * we want to end up with:
303 * Any name collisions will be left in the source directory.
306 src_directory = g_build_filename (old_cache_dir, "addressbook", NULL);
307 dst_directory = g_build_filename (new_cache_dir, "addressbook", NULL);
309 migrate_move_contents (src_directory, dst_directory);
310 migrate_rmdir (src_directory);
312 g_free (src_directory);
313 g_free (dst_directory);
315 src_directory = g_build_filename (old_cache_dir, "calendar", NULL);
316 dst_directory = g_build_filename (new_cache_dir, "calendar", NULL);
318 migrate_move_contents (src_directory, dst_directory);
319 migrate_rmdir (src_directory);
321 g_free (src_directory);
322 g_free (dst_directory);
324 src_directory = g_build_filename (old_cache_dir, "memos", NULL);
325 dst_directory = g_build_filename (new_cache_dir, "memos", NULL);
327 migrate_move_contents (src_directory, dst_directory);
328 migrate_rmdir (src_directory);
330 g_free (src_directory);
331 g_free (dst_directory);
333 src_directory = g_build_filename (old_cache_dir, "tasks", NULL);
334 dst_directory = g_build_filename (new_cache_dir, "tasks", NULL);
336 migrate_move_contents (src_directory, dst_directory);
337 migrate_rmdir (src_directory);
339 g_free (src_directory);
340 g_free (dst_directory);
342 /* Try to remove the old cache directory. Good chance this will
343 * fail on the first try, since Evolution puts stuff here too. */
344 migrate_rmdir (old_cache_dir);
346 g_free (old_cache_dir);
350 migrate_to_user_data_dir (const gchar *old_base_dir)
352 const gchar *new_data_dir;
353 gchar *src_directory;
354 gchar *dst_directory;
356 new_data_dir = e_get_user_data_dir ();
358 g_print ("Migrating local backend data\n");
360 /* We don't want to move the source directory directly because the
361 * destination directory may already exist with content. Instead
362 * we want to merge the content of the source directory into the
363 * destination directory.
365 * For example, given:
367 * $(src_directory)/A and $(dst_directory)/B
370 * we want to end up with:
376 * Any name collisions will be left in the source directory.
379 src_directory = g_build_filename (old_base_dir, "addressbook", "local", NULL);
380 dst_directory = g_build_filename (new_data_dir, "addressbook", NULL);
382 migrate_move_contents (src_directory, dst_directory);
383 migrate_rmdir (src_directory);
385 g_free (src_directory);
386 g_free (dst_directory);
388 src_directory = g_build_filename (old_base_dir, "calendar", "local", NULL);
389 dst_directory = g_build_filename (new_data_dir, "calendar", NULL);
391 migrate_move_contents (src_directory, dst_directory);
392 migrate_rmdir (src_directory);
394 g_free (src_directory);
395 g_free (dst_directory);
397 src_directory = g_build_filename (old_base_dir, "memos", "local", NULL);
398 dst_directory = g_build_filename (new_data_dir, "memos", NULL);
400 migrate_move_contents (src_directory, dst_directory);
401 migrate_rmdir (src_directory);
403 g_free (src_directory);
404 g_free (dst_directory);
406 src_directory = g_build_filename (old_base_dir, "tasks", "local", NULL);
407 dst_directory = g_build_filename (new_data_dir, "tasks", NULL);
409 migrate_move_contents (src_directory, dst_directory);
410 migrate_rmdir (src_directory);
412 g_free (src_directory);
413 g_free (dst_directory);
415 /* XXX This is not really the right place to be migrating
416 * exchange data, but since we already cleaned out the
417 * cached attachment files from this directory, may as
418 * well move the user accounts too while we're at it. */
420 src_directory = g_build_filename (old_base_dir, "exchange", NULL);
421 dst_directory = g_build_filename (new_data_dir, "exchange", NULL);
423 migrate_move_contents (src_directory, dst_directory);
424 migrate_rmdir (src_directory);
426 g_free (src_directory);
427 g_free (dst_directory);
431 evolution_source_registry_migrate_basedir (void)
433 const gchar *home_dir;
436 /* XXX This blocks, but it's all just local directory
437 * renames so it should be nearly instantaneous. */
439 home_dir = g_get_home_dir ();
440 old_base_dir = g_build_filename (home_dir, ".evolution", NULL);
442 /* Is there even anything to migrate? */
443 if (!g_file_test (old_base_dir, G_FILE_TEST_IS_DIR))
446 /* Miscellaneous tweaks before we start. */
447 migrate_fix_exchange_bug (old_base_dir);
448 migrate_fix_memos_cache_bug (old_base_dir);
449 migrate_fix_groupwise_bug (old_base_dir);
451 migrate_to_user_cache_dir (old_base_dir);
452 migrate_to_user_data_dir (old_base_dir);
454 /* Try to remove the old base directory. Good chance this will
455 * fail on the first try, since Evolution puts stuff here too. */
456 migrate_rmdir (old_base_dir);
459 g_free (old_base_dir);