repo: Don't require a txn for writing

The current "transaction" symlink was introduced to fix issues with
interrupted pulls; normally we assume that if we have a metadata
object, we also have all objects to which it refers.

There used to be a "summary" which had all the available refs, but I
deleted it because it wasn't really used, and was still racy despite
the transaction bits.

We still want the pull process to use the transaction link, so don't
delete the APIs, just relax the restriction on object writing, and
introduce a new ostree_repo_set_ref_immediate().
This commit is contained in:
Colin Walters 2014-05-26 18:32:17 -04:00
parent a4d01976bb
commit f1ccaa581e
5 changed files with 65 additions and 23 deletions

View File

@ -368,8 +368,6 @@ write_object (OstreeRepo *self,
gsize unpacked_size = 0;
gboolean indexable = FALSE;
g_return_val_if_fail (self->in_transaction, FALSE);
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return FALSE;
@ -930,6 +928,31 @@ ostree_repo_transaction_set_ref (OstreeRepo *self,
g_hash_table_replace (self->txn_refs, refspec, g_strdup (checksum));
}
/**
* ostree_repo_set_ref_immediate:
* @self: An #OstreeRepo
* @remote: (allow-none): A remote for the ref
* @ref: The ref to write
* @checksum: The checksum to point it to
* @cancellable: GCancellable
* @error: GError
*
* This is like ostree_repo_transaction_set_ref(), except it may be
* invoked outside of a transaction. This is presently safe for the
* case where we're creating or overwriting an existing ref.
*/
gboolean
ostree_repo_set_ref_immediate (OstreeRepo *self,
const char *remote,
const char *ref,
const char *checksum,
GCancellable *cancellable,
GError **error)
{
return _ostree_repo_write_ref (self, remote, ref, checksum,
cancellable, error);
}
/**
* ostree_repo_commit_transaction:
* @self: An #OstreeRepo

View File

@ -122,6 +122,14 @@ _ostree_repo_update_refs (OstreeRepo *self,
GCancellable *cancellable,
GError **error);
gboolean
_ostree_repo_write_ref (OstreeRepo *self,
const char *remote,
const char *ref,
const char *rev,
GCancellable *cancellable,
GError **error);
OstreeRepoFile *
_ostree_repo_file_new_for_commit (OstreeRepo *repo,
const char *commit,

View File

@ -570,21 +570,17 @@ ostree_repo_list_refs (OstreeRepo *self,
return ret;
}
static gboolean
write_refspec (OstreeRepo *self,
const char *refspec,
const char *rev,
GCancellable *cancellable,
GError **error)
gboolean
_ostree_repo_write_ref (OstreeRepo *self,
const char *remote,
const char *ref,
const char *rev,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
gs_free char *remote = NULL;
gs_free char *name = NULL;
gs_unref_object GFile *dir = NULL;
if (!ostree_parse_refspec (refspec, &remote, &name, error))
goto out;
if (remote == NULL)
dir = g_object_ref (self->local_heads_dir);
else
@ -600,7 +596,7 @@ write_refspec (OstreeRepo *self,
if (rev == NULL)
{
gs_unref_object GFile *child = g_file_resolve_relative_path (dir, name);
gs_unref_object GFile *child = g_file_resolve_relative_path (dir, ref);
if (g_file_query_exists (child, cancellable))
{
@ -610,7 +606,7 @@ write_refspec (OstreeRepo *self,
}
else
{
if (!write_checksum_file (dir, name, rev, cancellable, error))
if (!write_checksum_file (dir, ref, rev, cancellable, error))
goto out;
}
@ -634,8 +630,14 @@ _ostree_repo_update_refs (OstreeRepo *self,
{
const char *refspec = key;
const char *rev = value;
gs_free char *remote = NULL;
gs_free char *ref = NULL;
if (!write_refspec (self, refspec, rev, cancellable, error))
if (!ostree_parse_refspec (refspec, &remote, &ref, error))
goto out;
if (!_ostree_repo_write_ref (self, remote, ref, rev,
cancellable, error))
goto out;
}

View File

@ -133,6 +133,13 @@ void ostree_repo_transaction_set_ref (OstreeRepo *self,
const char *ref,
const char *checksum);
gboolean ostree_repo_set_ref_immediate (OstreeRepo *self,
const char *remote,
const char *ref,
const char *checksum,
GCancellable *cancellable,
GError **error);
gboolean ostree_repo_has_object (OstreeRepo *self,
OstreeObjectType objtype,
const char *checksum,

View File

@ -67,18 +67,20 @@ ostree_builtin_refs (int argc, char **argv, OstreeRepo *repo, GCancellable *canc
}
else
{
if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error))
goto out;
g_hash_table_iter_init (&hashiter, refs);
while (g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue))
{
const char *refspec = hashkey;
ostree_repo_transaction_set_refspec (repo, refspec, NULL);
}
gs_free char *remote = NULL;
gs_free char *ref = NULL;
if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error))
goto out;
if (!ostree_parse_refspec (refspec, &remote, &ref, error))
goto out;
if (!ostree_repo_set_ref_immediate (repo, remote, ref, NULL,
cancellable, error))
goto out;
}
}
ret = TRUE;