diff options
author | Alexander Larsson <alexl@redhat.com> | 2016-10-24 11:12:15 +0200 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2016-10-24 17:48:19 +0000 |
commit | d0e74cf3af73d6855eebe9c52f19105f7c84df0a (patch) | |
tree | 367b976fe0e4728c2f50e035accddab311082f5b /src/libostree/ostree-repo-traverse.c | |
parent | d3f14f02e3d9f7259c7ec6b25980ae43f03c4906 (diff) | |
download | ostree-d0e74cf3af73d6855eebe9c52f19105f7c84df0a.tar.gz |
Fix pruning of partial commits
If we have a partial commit it is not an error for a dirmeta to be
missing (in fact, that is likely), so instead of returning a not-found
error from ostree_repo_traverse_commit() we ignore the error and
continue.
In particular, this means we don't stop early at the first
missing dirmeta, which previously caused ostree_repo_prune() to
thing the dirmetas after that to be unreached and thus purged.
Also, we remove the special casing in ostree_repo_prune() to
not report errors for commitpartial, because these should not
be reported anymore.
This fixes https://github.com/ostreedev/ostree/issues/541
Closes: #542
Approved by: cgwalters
Diffstat (limited to 'src/libostree/ostree-repo-traverse.c')
-rw-r--r-- | src/libostree/ostree-repo-traverse.c | 60 |
1 files changed, 50 insertions, 10 deletions
diff --git a/src/libostree/ostree-repo-traverse.c b/src/libostree/ostree-repo-traverse.c index 516f39f5..5d994763 100644 --- a/src/libostree/ostree-repo-traverse.c +++ b/src/libostree/ostree-repo-traverse.c @@ -301,6 +301,7 @@ static gboolean traverse_dirtree (OstreeRepo *repo, const char *checksum, GHashTable *inout_reachable, + gboolean ignore_missing_dirs, GCancellable *cancellable, GError **error); @@ -308,6 +309,7 @@ static gboolean traverse_iter (OstreeRepo *repo, OstreeRepoCommitTraverseIter *iter, GHashTable *inout_reachable, + gboolean ignore_missing_dirs, GCancellable *cancellable, GError **error) { @@ -316,11 +318,26 @@ traverse_iter (OstreeRepo *repo, while (TRUE) { g_autoptr(GVariant) key = NULL; + g_autoptr(GError) local_error = NULL; OstreeRepoCommitIterResult iterres = - ostree_repo_commit_traverse_iter_next (iter, cancellable, error); - + ostree_repo_commit_traverse_iter_next (iter, cancellable, &local_error); + if (iterres == OSTREE_REPO_COMMIT_ITER_RESULT_ERROR) - goto out; + { + /* There is only one kind of not-found error, which is + failing to load the dirmeta itself, if so, we ignore that + (and the whole subtree) if told to. */ + if (ignore_missing_dirs && + g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) + { + g_debug ("Ignoring not-found dirmeta"); + ret = TRUE; + } + else + g_propagate_error (error, g_steal_pointer (&local_error)); + + goto out; + } else if (iterres == OSTREE_REPO_COMMIT_ITER_RESULT_END) break; else if (iterres == OSTREE_REPO_COMMIT_ITER_RESULT_FILE) @@ -357,7 +374,7 @@ traverse_iter (OstreeRepo *repo, key = NULL; if (!traverse_dirtree (repo, content_checksum, inout_reachable, - cancellable, error)) + ignore_missing_dirs, cancellable, error)) goto out; } } @@ -374,6 +391,7 @@ static gboolean traverse_dirtree (OstreeRepo *repo, const char *checksum, GHashTable *inout_reachable, + gboolean ignore_missing_dirs, GCancellable *cancellable, GError **error) { @@ -381,10 +399,22 @@ traverse_dirtree (OstreeRepo *repo, g_autoptr(GVariant) dirtree = NULL; ostree_cleanup_repo_commit_traverse_iter OstreeRepoCommitTraverseIter iter = { 0, }; + g_autoptr(GError) local_error = NULL; if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_DIR_TREE, checksum, - &dirtree, error)) - goto out; + &dirtree, &local_error)) + { + if (ignore_missing_dirs && + g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) + { + g_print ("Ignoring not-found dirmeta %s", checksum); + ret = TRUE; + } + else + g_propagate_error (error, g_steal_pointer (&local_error)); + + goto out; + } g_debug ("Traversing dirtree %s", checksum); if (!ostree_repo_commit_traverse_iter_init_dirtree (&iter, repo, dirtree, @@ -392,7 +422,7 @@ traverse_dirtree (OstreeRepo *repo, error)) goto out; - if (!traverse_iter (repo, &iter, inout_reachable, cancellable, error)) + if (!traverse_iter (repo, &iter, inout_reachable, ignore_missing_dirs, cancellable, error)) goto out; ret = TRUE; @@ -430,6 +460,8 @@ ostree_repo_traverse_commit_union (OstreeRepo *repo, g_autoptr(GVariant) commit = NULL; ostree_cleanup_repo_commit_traverse_iter OstreeRepoCommitTraverseIter iter = { 0, }; + OstreeRepoCommitState commitstate; + gboolean ignore_missing_dirs = FALSE; key = ostree_object_name_serialize (commit_checksum, OSTREE_OBJECT_TYPE_COMMIT); @@ -440,13 +472,21 @@ ostree_repo_traverse_commit_union (OstreeRepo *repo, commit_checksum, &commit, error)) goto out; - + /* Just return if the parent isn't found; we do expect most * people to have partial repositories. */ if (!commit) break; + /* See if the commit is partial, if so it's not an error to lack objects */ + if (!ostree_repo_load_commit (repo, commit_checksum, NULL, &commitstate, + error)) + goto out; + + if ((commitstate & OSTREE_REPO_COMMIT_STATE_PARTIAL) != 0) + ignore_missing_dirs = TRUE; + g_hash_table_add (inout_reachable, key); key = NULL; @@ -456,9 +496,9 @@ ostree_repo_traverse_commit_union (OstreeRepo *repo, error)) goto out; - if (!traverse_iter (repo, &iter, inout_reachable, cancellable, error)) + if (!traverse_iter (repo, &iter, inout_reachable, ignore_missing_dirs, cancellable, error)) goto out; - + if (maxdepth == -1 || maxdepth > 0) { g_free (tmp_checksum); |