deploy: Split the file rewriting and prefix checkout out from the exporting

We need this so that we can export an app multiple times, if you're e.g.
switching between deployed versions.
tingping/wmclass
Alexander Larsson 2015-03-09 17:13:04 +01:00
parent 957bf050bd
commit c90f9473e1
1 changed files with 137 additions and 51 deletions

View File

@ -593,22 +593,16 @@ export_desktop_file (const char *app,
}
static gboolean
export_dir (const char *app,
const char *branch,
const char *arch,
int source_parent_fd,
const char *source_name,
const char *source_symlink_prefix,
const char *source_relpath,
int destination_parent_fd,
const char *destination_name,
GCancellable *cancellable,
GError **error)
rewrite_export_dir (const char *app,
const char *branch,
const char *arch,
int source_parent_fd,
const char *source_name,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
int res;
gs_dirfd_iterator_cleanup GSDirFdIterator source_iter;
gs_fd_close int destination_dfd = -1;
gs_unref_hashtable GHashTable *visited_children = NULL;
struct dirent *dent;
@ -617,23 +611,6 @@ export_dir (const char *app,
visited_children = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
do
res = mkdirat (destination_parent_fd, destination_name, 0777);
while (G_UNLIKELY (res == -1 && errno == EINTR));
if (res == -1)
{
if (errno != EEXIST)
{
gs_set_error_from_errno (error, errno);
goto out;
}
}
if (!gs_file_open_dir_fd_at (destination_parent_fd, destination_name,
&destination_dfd,
cancellable, error))
goto out;
while (TRUE)
{
struct stat stbuf;
@ -664,12 +641,9 @@ export_dir (const char *app,
if (S_ISDIR (stbuf.st_mode))
{
gs_free gchar *child_symlink_prefix = g_build_filename ("..", source_symlink_prefix, dent->d_name, NULL);
gs_free gchar *child_relpath = g_strconcat (source_relpath, dent->d_name, "/", NULL);
if (!export_dir (app, branch, arch,
source_iter.fd, dent->d_name, child_symlink_prefix, child_relpath, destination_dfd, dent->d_name,
cancellable, error))
if (!rewrite_export_dir (app, branch, arch,
source_iter.fd, dent->d_name,
cancellable, error))
goto out;
}
else if (S_ISREG (stbuf.st_mode))
@ -678,8 +652,12 @@ export_dir (const char *app,
if (!xdg_app_has_name_prefix (dent->d_name, app))
{
g_warning ("Non-prefixed filename %s in app %s, ignoring.\n", dent->d_name, app);
continue;
g_warning ("Non-prefixed filename %s in app %s, removing.\n", dent->d_name, app);
if (unlinkat (source_iter.fd, dent->d_name, 0) != 0 && errno != ENOENT)
{
gs_set_error_from_errno (error, errno);
goto out;
}
}
if (g_str_has_suffix (dent->d_name, ".desktop") || g_str_has_suffix (dent->d_name, ".service"))
@ -697,6 +675,117 @@ export_dir (const char *app,
goto out;
}
}
}
else
{
g_warning ("Not exporting file %s of unsupported type\n", dent->d_name);
if (unlinkat (source_iter.fd, dent->d_name, 0) != 0 && errno != ENOENT)
{
gs_set_error_from_errno (error, errno);
goto out;
}
}
}
ret = TRUE;
out:
return ret;
}
gboolean
xdg_app_rewrite_export_dir (const char *app,
const char *branch,
const char *arch,
GFile *source,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
/* The fds are closed by this call */
if (!rewrite_export_dir (app, branch, arch,
AT_FDCWD, gs_file_get_path_cached (source),
cancellable, error))
goto out;
ret = TRUE;
out:
return ret;
}
static gboolean
export_dir (int source_parent_fd,
const char *source_name,
const char *source_symlink_prefix,
const char *source_relpath,
int destination_parent_fd,
const char *destination_name,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
int res;
gs_dirfd_iterator_cleanup GSDirFdIterator source_iter;
gs_fd_close int destination_dfd = -1;
struct dirent *dent;
if (!gs_dirfd_iterator_init_at (source_parent_fd, source_name, FALSE, &source_iter, error))
goto out;
do
res = mkdirat (destination_parent_fd, destination_name, 0777);
while (G_UNLIKELY (res == -1 && errno == EINTR));
if (res == -1)
{
if (errno != EEXIST)
{
gs_set_error_from_errno (error, errno);
goto out;
}
}
if (!gs_file_open_dir_fd_at (destination_parent_fd, destination_name,
&destination_dfd,
cancellable, error))
goto out;
while (TRUE)
{
struct stat stbuf;
if (!gs_dirfd_iterator_next_dent (&source_iter, &dent, cancellable, error))
goto out;
if (dent == NULL)
break;
if (fstatat (source_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW) == -1)
{
int errsv = errno;
if (errsv == ENOENT)
continue;
else
{
gs_set_error_from_errno (error, errsv);
goto out;
}
}
if (S_ISDIR (stbuf.st_mode))
{
gs_free gchar *child_symlink_prefix = g_build_filename ("..", source_symlink_prefix, dent->d_name, NULL);
gs_free gchar *child_relpath = g_strconcat (source_relpath, dent->d_name, "/", NULL);
if (!export_dir (source_iter.fd, dent->d_name, child_symlink_prefix, child_relpath, destination_dfd, dent->d_name,
cancellable, error))
goto out;
}
else if (S_ISREG (stbuf.st_mode))
{
gs_free gchar *target = NULL;
target = g_build_filename (source_symlink_prefix, dent->d_name, NULL);
@ -712,10 +801,6 @@ export_dir (const char *app,
goto out;
}
}
else
{
g_warning ("Not exporting file %s of unsupported type\n", source_relpath);
}
}
ret = TRUE;
@ -725,10 +810,7 @@ export_dir (const char *app,
}
gboolean
xdg_app_export_dir (const char *app,
const char *branch,
const char *arch,
GFile *source,
xdg_app_export_dir (GFile *source,
GFile *destination,
const char *symlink_prefix,
GCancellable *cancellable,
@ -740,8 +822,7 @@ xdg_app_export_dir (const char *app,
goto out;
/* The fds are closed by this call */
if (!export_dir (app, branch, arch,
AT_FDCWD, gs_file_get_path_cached (source), symlink_prefix, "",
if (!export_dir (AT_FDCWD, gs_file_get_path_cached (source), symlink_prefix, "",
AT_FDCWD, gs_file_get_path_cached (destination),
cancellable, error))
goto out;
@ -906,12 +987,17 @@ xdg_app_dir_deploy (XdgAppDir *self,
gs_free char *symlink_prefix = NULL;
gs_strfreev char **ref_parts = NULL;
ref_parts = g_strsplit (ref, "/", -1);
if (!xdg_app_rewrite_export_dir (ref_parts[1], ref_parts[3], ref_parts[2], export,
cancellable,
error))
goto out;
relative_path = g_file_get_relative_path (self->basedir, export);
symlink_prefix = g_build_filename ("..", relative_path, NULL);
ref_parts = g_strsplit (ref, "/", -1);
if (!xdg_app_export_dir (ref_parts[1], ref_parts[3], ref_parts[2], export, exports,
if (!xdg_app_export_dir (export, exports,
symlink_prefix,
cancellable,
error))