libostree: Rename ostree-traverse.h into OstreeRepo namespace
This operates on the repo, it might as well be methods on it.
This commit is contained in:
1 parent
cb6b69616c
commit
2aa0251b1b
8 files changed
+43
-73
No files matched your search
@@ -0,0 +1,227 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2011 Colin Walters <walters@verbum.org>
|
||||
*
|
||||
* This library 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 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, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: Colin Walters <walters@verbum.org>
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "ostree.h"
|
||||
#include "otutil.h"
|
||||
|
||||
GHashTable *
|
||||
ostree_repo_traverse_new_reachable (void)
|
||||
{
|
||||
return g_hash_table_new_full (ostree_hash_object_name, g_variant_equal,
|
||||
(GDestroyNotify)g_variant_unref, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
traverse_dirtree_internal (OstreeRepo *repo,
|
||||
const char *dirtree_checksum,
|
||||
int recursion_depth,
|
||||
GHashTable *inout_reachable,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
int n, i;
|
||||
gs_unref_variant GVariant *key = NULL;
|
||||
gs_unref_variant GVariant *tree = NULL;
|
||||
gs_unref_variant GVariant *files_variant = NULL;
|
||||
gs_unref_variant GVariant *dirs_variant = NULL;
|
||||
gs_unref_variant GVariant *csum_v = NULL;
|
||||
gs_unref_variant GVariant *content_csum_v = NULL;
|
||||
gs_unref_variant GVariant *metadata_csum_v = NULL;
|
||||
gs_free char *tmp_checksum = NULL;
|
||||
|
||||
if (recursion_depth > OSTREE_MAX_RECURSION)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Maximum recursion limit reached during traversal");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!ostree_repo_load_variant_if_exists (repo, OSTREE_OBJECT_TYPE_DIR_TREE, dirtree_checksum, &tree, error))
|
||||
goto out;
|
||||
|
||||
if (!tree)
|
||||
return TRUE;
|
||||
|
||||
key = ostree_object_name_serialize (dirtree_checksum, OSTREE_OBJECT_TYPE_DIR_TREE);
|
||||
if (!g_hash_table_lookup (inout_reachable, key))
|
||||
{
|
||||
g_hash_table_insert (inout_reachable, key, key);
|
||||
key = NULL;
|
||||
|
||||
/* PARSE OSTREE_SERIALIZED_TREE_VARIANT */
|
||||
files_variant = g_variant_get_child_value (tree, 0);
|
||||
n = g_variant_n_children (files_variant);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
const char *filename;
|
||||
|
||||
g_clear_pointer (&csum_v, (GDestroyNotify) g_variant_unref);
|
||||
g_variant_get_child (files_variant, i, "(&s@ay)", &filename, &csum_v);
|
||||
g_free (tmp_checksum);
|
||||
tmp_checksum = ostree_checksum_from_bytes_v (csum_v);
|
||||
key = ostree_object_name_serialize (tmp_checksum, OSTREE_OBJECT_TYPE_FILE);
|
||||
g_hash_table_replace (inout_reachable, key, key);
|
||||
key = NULL;
|
||||
}
|
||||
|
||||
dirs_variant = g_variant_get_child_value (tree, 1);
|
||||
n = g_variant_n_children (dirs_variant);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
const char *dirname;
|
||||
|
||||
g_clear_pointer (&content_csum_v, (GDestroyNotify) g_variant_unref);
|
||||
g_clear_pointer (&metadata_csum_v, (GDestroyNotify) g_variant_unref);
|
||||
g_variant_get_child (dirs_variant, i, "(&s@ay@ay)",
|
||||
&dirname, &content_csum_v, &metadata_csum_v);
|
||||
|
||||
g_free (tmp_checksum);
|
||||
tmp_checksum = ostree_checksum_from_bytes_v (content_csum_v);
|
||||
if (!traverse_dirtree_internal (repo, tmp_checksum, recursion_depth + 1,
|
||||
inout_reachable, cancellable, error))
|
||||
goto out;
|
||||
|
||||
g_free (tmp_checksum);
|
||||
tmp_checksum = ostree_checksum_from_bytes_v (metadata_csum_v);
|
||||
key = ostree_object_name_serialize (tmp_checksum, OSTREE_OBJECT_TYPE_DIR_META);
|
||||
g_hash_table_replace (inout_reachable, key, key);
|
||||
key = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ostree_repo_traverse_dirtree (OstreeRepo *repo,
|
||||
const char *dirtree_checksum,
|
||||
GHashTable *inout_reachable,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
return traverse_dirtree_internal (repo, dirtree_checksum, 0,
|
||||
inout_reachable, cancellable, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_traverse_commit:
|
||||
*
|
||||
* Add to @inout_reachable all objects reachable from
|
||||
* @commit_checksum, traversing @maxdepth parent commits.
|
||||
*/
|
||||
gboolean
|
||||
ostree_repo_traverse_commit (OstreeRepo *repo,
|
||||
const char *commit_checksum,
|
||||
int maxdepth,
|
||||
GHashTable *inout_reachable,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
gs_free char*tmp_checksum = NULL;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
gboolean recurse = FALSE;
|
||||
gs_unref_variant GVariant *parent_csum_bytes = NULL;
|
||||
gs_unref_variant GVariant *meta_csum_bytes = NULL;
|
||||
gs_unref_variant GVariant *content_csum_bytes = NULL;
|
||||
gs_unref_variant GVariant *key = NULL;
|
||||
gs_unref_variant GVariant *commit = NULL;
|
||||
|
||||
key = ostree_object_name_serialize (commit_checksum, OSTREE_OBJECT_TYPE_COMMIT);
|
||||
|
||||
if (g_hash_table_contains (inout_reachable, key))
|
||||
break;
|
||||
|
||||
/* PARSE OSTREE_SERIALIZED_COMMIT_VARIANT */
|
||||
if (!ostree_repo_load_variant_if_exists (repo, OSTREE_OBJECT_TYPE_COMMIT, 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;
|
||||
|
||||
g_hash_table_add (inout_reachable, key);
|
||||
key = NULL;
|
||||
|
||||
g_variant_get_child (commit, 7, "@ay", &meta_csum_bytes);
|
||||
g_free (tmp_checksum);
|
||||
if (G_UNLIKELY (g_variant_n_children (meta_csum_bytes) == 0))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Corrupted commit '%s'; invalid tree metadata",
|
||||
commit_checksum);
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmp_checksum = ostree_checksum_from_bytes_v (meta_csum_bytes);
|
||||
key = ostree_object_name_serialize (tmp_checksum, OSTREE_OBJECT_TYPE_DIR_META);
|
||||
g_hash_table_replace (inout_reachable, key, key);
|
||||
key = NULL;
|
||||
|
||||
g_variant_get_child (commit, 6, "@ay", &content_csum_bytes);
|
||||
g_free (tmp_checksum);
|
||||
if (G_UNLIKELY (g_variant_n_children (content_csum_bytes) == 0))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Corrupted commit '%s'; invalid tree content",
|
||||
commit_checksum);
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmp_checksum = ostree_checksum_from_bytes_v (content_csum_bytes);
|
||||
if (!ostree_repo_traverse_dirtree (repo, tmp_checksum, inout_reachable, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (maxdepth == -1 || maxdepth > 0)
|
||||
{
|
||||
g_variant_get_child (commit, 1, "@ay", &parent_csum_bytes);
|
||||
|
||||
if (g_variant_n_children (parent_csum_bytes) > 0)
|
||||
{
|
||||
g_free (tmp_checksum);
|
||||
tmp_checksum = ostree_checksum_from_bytes_v (parent_csum_bytes);
|
||||
commit_checksum = tmp_checksum;
|
||||
if (maxdepth > 0)
|
||||
maxdepth -= 1;
|
||||
recurse = TRUE;
|
||||
}
|
||||
}
|
||||
if (!recurse)
|
||||
break;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user