Files
flatpak/lib/flatpak-remote.c
Matthias Clasen e1207256d0 lib: Fix saving of remote titles
We were using the key 'title' in some places, but 'xa.title'
elsewhere. Make it 'xa.title' everywhere. This bug was found
by the new unit tests.
2016-08-01 23:05:38 -04:00

604 lines
16 KiB
C

/*
* Copyright © 2015 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Alexander Larsson <alexl@redhat.com>
*/
#include "config.h"
#include "flatpak-utils.h"
#include "flatpak-remote-private.h"
#include "flatpak-remote-ref-private.h"
#include "flatpak-enum-types.h"
#include <string.h>
/**
* SECTION:flatpak-remote
* @Short_description: Remote repository
* @Title: FlatpakRemote
*
* A #FlatpakRemote object provides information about a remote
* repository (or short: remote) that has been configured.
*
* At its most basic level, a remote has a name and the URL for
* the repository. In addition, they provide some additional
* information that can be useful when presenting repositories
* in a UI, such as a title, a priority or a "don't enumerate"
* flags.
*
* To obtain FlatpakRemote objects for the configured remotes
* on a system, use flatpak_installation_list_remotes() or
* flatpak_installation_get_remote_by_name().
*/
typedef struct _FlatpakRemotePrivate FlatpakRemotePrivate;
struct _FlatpakRemotePrivate
{
char *name;
FlatpakDir *dir;
char *local_url;
char *local_title;
gboolean local_gpg_verify;
gboolean local_noenumerate;
gboolean local_disabled;
int local_prio;
guint local_url_set : 1;
guint local_title_set : 1;
guint local_gpg_verify_set : 1;
guint local_noenumerate_set : 1;
guint local_disabled_set : 1;
guint local_prio_set : 1;
GBytes *local_gpg_key;
};
G_DEFINE_TYPE_WITH_PRIVATE (FlatpakRemote, flatpak_remote, G_TYPE_OBJECT)
enum {
PROP_0,
PROP_NAME,
};
static void
flatpak_remote_finalize (GObject *object)
{
FlatpakRemote *self = FLATPAK_REMOTE (object);
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
g_free (priv->name);
if (priv->dir)
g_object_unref (priv->dir);
if (priv->local_gpg_key)
g_bytes_unref (priv->local_gpg_key);
g_free (priv->local_url);
g_free (priv->local_title);
G_OBJECT_CLASS (flatpak_remote_parent_class)->finalize (object);
}
static void
flatpak_remote_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
FlatpakRemote *self = FLATPAK_REMOTE (object);
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
switch (prop_id)
{
case PROP_NAME:
g_clear_pointer (&priv->name, g_free);
priv->name = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
flatpak_remote_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
FlatpakRemote *self = FLATPAK_REMOTE (object);
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
switch (prop_id)
{
case PROP_NAME:
g_value_set_string (value, priv->name);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
flatpak_remote_class_init (FlatpakRemoteClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->get_property = flatpak_remote_get_property;
object_class->set_property = flatpak_remote_set_property;
object_class->finalize = flatpak_remote_finalize;
g_object_class_install_property (object_class,
PROP_NAME,
g_param_spec_string ("name",
"Name",
"The name of the remote",
NULL,
G_PARAM_READWRITE));
}
static void
flatpak_remote_init (FlatpakRemote *self)
{
}
/**
* flatpak_remote_get_name:
* @self: a #FlatpakRemote
*
* Returns the name of the remote repository.
*
* Returns: (transfer none): the name
*/
const char *
flatpak_remote_get_name (FlatpakRemote *self)
{
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
return priv->name;
}
/**
* flatpak_remote_get_appstream_dir:
* @self: a #FlatpakRemote
* @arch: (nullable): which architecture to fetch (default: current architecture)
*
* Returns the directory where this remote will store locally cached
* appstream information for the specified @arch.
*
* Returns: (transfer full): a #GFile
**/
GFile *
flatpak_remote_get_appstream_dir (FlatpakRemote *self,
const char *arch)
{
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
g_autofree char *subdir = NULL;
if (priv->dir == NULL)
return NULL;
if (arch == NULL)
arch = flatpak_get_arch ();
subdir = g_strdup_printf ("appstream/%s/%s/active", priv->name, arch);
return g_file_resolve_relative_path (flatpak_dir_get_path (priv->dir),
subdir);
}
/**
* flatpak_remote_get_appstream_timestamp:
* @self: a #FlatpakRemote
* @arch: (nullable): which architecture to fetch (default: current architecture)
*
* Returns the timestamp file that will be updated whenever the appstream information
* has been updated (or tried to update) for the specified @arch.
*
* Returns: (transfer full): a #GFile
**/
GFile *
flatpak_remote_get_appstream_timestamp (FlatpakRemote *self,
const char *arch)
{
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
g_autofree char *subdir = NULL;
if (priv->dir == NULL)
return NULL;
if (arch == NULL)
arch = flatpak_get_arch ();
subdir = g_strdup_printf ("appstream/%s/%s/.timestamp", priv->name, arch);
return g_file_resolve_relative_path (flatpak_dir_get_path (priv->dir),
subdir);
}
/**
* flatpak_remote_get_url:
* @self: a #FlatpakRemote
*
* Returns the repository URL of this remote.
*
* Returns: (transfer full): the URL
*/
char *
flatpak_remote_get_url (FlatpakRemote *self)
{
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
char *url;
if (priv->local_url_set)
return g_strdup (priv->local_url);
if (priv->dir)
{
OstreeRepo *repo = flatpak_dir_get_repo (priv->dir);
if (ostree_repo_remote_get_url (repo, priv->name, &url, NULL))
return url;
}
return NULL;
}
/**
* flatpak_remote_set_url:
* @self: a #FlatpakRemote
* @url: The new url
*
* Sets the repository URL of this remote.
*
* Note: This is a local modification of this object, you must commit changes
* using flatpak_installation_modify_remote() for the changes to take
* effect.
*/
void
flatpak_remote_set_url (FlatpakRemote *self,
const char *url)
{
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
g_free (priv->local_url);
priv->local_url = g_strdup (url);
priv->local_url_set = TRUE;
}
/**
* flatpak_remote_get_title:
* @self: a #FlatpakRemote
*
* Returns the title of the remote.
*
* Returns: (transfer full): the title
*/
char *
flatpak_remote_get_title (FlatpakRemote *self)
{
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
if (priv->local_title_set)
return g_strdup (priv->local_title);
if (priv->dir)
return flatpak_dir_get_remote_title (priv->dir, priv->name);
return NULL;
}
/**
* flatpak_remote_set_title:
* @self: a #FlatpakRemote
* @title: The new title
*
* Sets the repository title of this remote.
*
* Note: This is a local modification of this object, you must commit changes
* using flatpak_installation_modify_remote() for the changes to take
* effect.
*/
void
flatpak_remote_set_title (FlatpakRemote *self,
const char *title)
{
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
g_free (priv->local_title);
priv->local_title = g_strdup (title);
priv->local_title_set = TRUE;
}
/**
* flatpak_remote_get_noenumerate:
* @self: a #FlatpakRemote
*
* Returns whether this remote should be used to list applications.
*
* Returns: whether the remote is marked as "don't enumerate"
*/
gboolean
flatpak_remote_get_noenumerate (FlatpakRemote *self)
{
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
if (priv->local_noenumerate_set)
return priv->local_noenumerate;
if (priv->dir)
return flatpak_dir_get_remote_noenumerate (priv->dir, priv->name);
return FALSE;
}
/**
* flatpak_remote_set_noenumerate:
* @self: a #FlatpakRemote
* @noenumerate: a bool
*
* Sets the noenumeration config of this remote. See flatpak_remote_get_noenumerate().
*
* Note: This is a local modification of this object, you must commit changes
* using flatpak_installation_modify_remote() for the changes to take
* effect.
*/
void
flatpak_remote_set_noenumerate (FlatpakRemote *self,
gboolean noenumerate)
{
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
priv->local_noenumerate = noenumerate;
priv->local_noenumerate_set = TRUE;
}
/**
* flatpak_remote_get_disabled:
* @self: a #FlatpakRemote
*
* Returns whether this remote is disabled.
*
* Returns: whether the remote is marked as "don't enumerate"
*/
gboolean
flatpak_remote_get_disabled (FlatpakRemote *self)
{
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
if (priv->local_disabled_set)
return priv->local_disabled;
if (priv->dir)
return flatpak_dir_get_remote_disabled (priv->dir, priv->name);
return FALSE;
}
/**
* flatpak_remote_set_disabled:
* @self: a #FlatpakRemote
* @disabled: a bool
*
* Sets the disabled config of this remote. See flatpak_remote_get_disable().
*
* Note: This is a local modification of this object, you must commit changes
* using flatpak_installation_modify_remote() for the changes to take
* effect.
*/
void
flatpak_remote_set_disabled (FlatpakRemote *self,
gboolean disabled)
{
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
priv->local_disabled = disabled;
priv->local_disabled_set = TRUE;
}
/**
* flatpak_remote_get_prio:
* @self: a #FlatpakRemote
*
* Returns the priority for the remote.
*
* Returns: the priority
*/
int
flatpak_remote_get_prio (FlatpakRemote *self)
{
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
if (priv->local_prio_set)
return priv->local_prio;
if (priv->dir)
return flatpak_dir_get_remote_prio (priv->dir, priv->name);
return 1;
}
/**
* flatpak_remote_set_prio:
* @self: a #FlatpakRemote
* @prio: a bool
*
* Sets the prio config of this remote. See flatpak_remote_get_prio().
*
* Note: This is a local modification of this object, you must commit changes
* using flatpak_installation_modify_remote() for the changes to take
* effect.
*/
void
flatpak_remote_set_prio (FlatpakRemote *self,
int prio)
{
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
priv->local_prio = prio;
priv->local_prio_set = TRUE;
}
/**
* flatpak_remote_get_gpg_verify:
* @self: a #FlatpakRemote
*
* Returns whether GPG verification is enabled for the remote.
*
* Returns: whether GPG verification is enabled
*/
gboolean
flatpak_remote_get_gpg_verify (FlatpakRemote *self)
{
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
gboolean res;
if (priv->local_gpg_verify_set)
return priv->local_gpg_verify;
if (priv->dir)
{
OstreeRepo *repo = flatpak_dir_get_repo (priv->dir);
if (ostree_repo_remote_get_gpg_verify (repo, priv->name, &res, NULL))
return res;
}
return FALSE;
}
/**
* flatpak_remote_set_gpg_verify:
* @self: a #FlatpakRemote
* @gpg_verify: a bool
*
* Sets the gpg_verify config of this remote. See flatpak_remote_get_gpg_verify().
*
* Note: This is a local modification of this object, you must commit changes
* using flatpak_installation_modify_remote() for the changes to take
* effect.
*/
void
flatpak_remote_set_gpg_verify (FlatpakRemote *self,
gboolean gpg_verify)
{
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
priv->local_gpg_verify = gpg_verify;
priv->local_gpg_verify_set = TRUE;
}
/**
* flatpak_remote_set_gpg_key:
* @self: a #FlatpakRemote
* @gpg_key: a #GBytes with gpg binary key data
*
* Sets the trusted gpg key for this remote.
*
* Note: This is a local modification of this object, you must commit changes
* using flatpak_installation_modify_remote() for the changes to take
* effect.
*/
void
flatpak_remote_set_gpg_key (FlatpakRemote *self,
GBytes *gpg_key)
{
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
if (priv->local_gpg_key != NULL)
g_bytes_unref (priv->local_gpg_key);
priv->local_gpg_key = g_bytes_ref (gpg_key);
}
FlatpakRemote *
flatpak_remote_new_with_dir (const char *name,
FlatpakDir *dir)
{
FlatpakRemotePrivate *priv;
FlatpakRemote *self = g_object_new (FLATPAK_TYPE_REMOTE,
"name", name,
NULL);
priv = flatpak_remote_get_instance_private (self);
if (dir)
priv->dir = g_object_ref (dir);
return self;
}
/**
* flatpak_remote_new:
* @name: a name
*
* Returns a new remote object which can be used to configure a new remote.
*
* Note: This is a local configuration object, you must commit changes
* using flatpak_installation_modify_remote() for the changes to take
* effect.
*
* Returns: (transfer full): a new #FlatpakRemote
**/
FlatpakRemote *
flatpak_remote_new (const char *name)
{
return flatpak_remote_new_with_dir (name, NULL);
}
gboolean
flatpak_remote_commit (FlatpakRemote *self,
FlatpakDir *dir,
GCancellable *cancellable,
GError **error)
{
FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (self);
g_autofree char *url = NULL;
g_autoptr(GKeyFile) config = NULL;
g_autofree char *group = g_strdup_printf ("remote \"%s\"", priv->name);
url = flatpak_remote_get_url (self);
if (url == NULL || *url == 0)
return flatpak_fail (error, "No url specified");
config = ostree_repo_copy_config (flatpak_dir_get_repo (dir));
if (priv->local_url_set)
g_key_file_set_string (config, group, "url", priv->local_url);
if (priv->local_title_set)
g_key_file_set_string (config, group, "xa.title", priv->local_title);
if (priv->local_gpg_verify_set)
{
g_key_file_set_boolean (config, group, "gpg-verify", priv->local_gpg_verify);
g_key_file_set_boolean (config, group, "gpg-verify-summary", priv->local_gpg_verify);
}
if (priv->local_noenumerate_set)
g_key_file_set_boolean (config, group, "xa.noenumerate", priv->local_noenumerate);
if (priv->local_disabled_set)
g_key_file_set_boolean (config, group, "xa.disable", priv->local_disabled);
if (priv->local_prio_set)
{
g_autofree char *prio_as_string = g_strdup_printf ("%d", priv->local_prio);
g_key_file_set_string (config, group, "xa.prio", prio_as_string);
}
return flatpak_dir_modify_remote (dir, priv->name, config, priv->local_gpg_key, cancellable, error);
}