[ostree/wip/packfile-rebase2] core: More progress on pack files
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ostree/wip/packfile-rebase2] core: More progress on pack files
- Date: Fri, 23 Mar 2012 00:32:07 +0000 (UTC)
commit 1a1c11dd3f4ed9bfc35d20712498baf5f97cbbf9
Author: Colin Walters <walters verbum org>
Date: Thu Mar 22 20:31:17 2012 -0400
core: More progress on pack files
src/libostree/README.md | 17 ++-
src/libostree/ostree-core.c | 94 ++++++++
src/libostree/ostree-core.h | 43 +++--
src/libostree/ostree-repo-file.c | 45 +----
src/libostree/ostree-repo.c | 480 ++++++++++++++++++++++++--------------
src/libostree/ostree-repo.h | 16 +-
src/ostree/ostree-pull.c | 7 +-
src/ostree/ot-builtin-repack.c | 128 ++++++-----
tests/t0000-basic.sh | 13 +-
tests/t0001-archive.sh | 13 +-
10 files changed, 546 insertions(+), 310 deletions(-)
---
diff --git a/src/libostree/README.md b/src/libostree/README.md
index aa1425b..c1d5f68 100644
--- a/src/libostree/README.md
+++ b/src/libostree/README.md
@@ -18,6 +18,7 @@ Key differences versus git
--------------------------
* As mentioned above, extended attributes and owner uid/gid are versioned
+ * Optimized for Unix hardlinks between repository and checkout
* SHA256 instead of SHA1
* Support for empty directories
@@ -28,9 +29,16 @@ While this is still in planning, I plan to heavily optimize OSTree for
versioning ELF operating systems. In industry jargon, this would be
"content-aware storage".
+Trimming history
+----------------
+
+OSTree will also be optimized to trim intermediate history; in theory
+one can regenerate binaries from corresponding (git) source code, so
+we don't need to keep all possible builds over time.
+
MILESTONE 1
-----------
-* Basic pack files
+* Basic pack files (like git)
MILESTONE 2
-----------
@@ -38,12 +46,17 @@ MILESTONE 2
* Drop version/metadata from tree/dirmeta objects
* Restructure repository so that links can be generated as a cache;
i.e. objects/raw, pack files are now the canonical
-* Commits generate a pack?
* For files, checksum combination of metadata variant + raw data
MILESTONE 3
-----------
+* Drop archive/raw distinction - archive repositories always generate
+ packfiles per commit
+* Include git packv4 ideas:
+ - split packfile implementations between metadata and data
+ - metadata packfiles have string dictionary (tree filenames and checksums)
+ - data packfiles match up similar objects
* Rolling checksums for partitioning large files? Kernel debuginfo
* Improved pack clustering
- file fingerprinting?
diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c
index 376504c..d57dca3 100644
--- a/src/libostree/ostree-core.c
+++ b/src/libostree/ostree-core.c
@@ -597,6 +597,24 @@ ostree_hash_object_name (gconstpointer a)
return g_str_hash (checksum) + g_int_hash (&objtype_int);
}
+int
+ostree_cmp_checksum_bytes (GVariant *a,
+ GVariant *b)
+{
+ gconstpointer a_data;
+ gconstpointer b_data;
+ gsize a_n_elts;
+ gsize b_n_elts;
+
+ a_data = g_variant_get_fixed_array (a, &a_n_elts, 1);
+ g_assert (a_n_elts == 32);
+ b_data = g_variant_get_fixed_array (b, &b_n_elts, 1);
+ g_assert (b_n_elts == 32);
+
+ return memcmp (a_data, b_data, 32);
+}
+
+
GVariant *
ostree_object_name_serialize (const char *checksum,
OstreeObjectType objtype)
@@ -614,6 +632,82 @@ ostree_object_name_deserialize (GVariant *variant,
*out_objtype = (OstreeObjectType)objtype_u32;
}
+GVariant *
+ostree_checksum_to_bytes (const char *sha256)
+{
+ guchar result[32];
+ guint i = 0;
+
+ for (i = 0; i < 32; i += 2)
+ {
+ gint big, little;
+
+ g_assert (sha256[i]);
+ g_assert (sha256[i+1]);
+
+ big = g_ascii_xdigit_value (sha256[i]);
+ little = g_ascii_xdigit_value (sha256[i+1]);
+
+ result[i] += (big << 4) | little;
+ }
+
+ return g_variant_new_fixed_array (G_VARIANT_TYPE ("y"),
+ result, 32, 1);
+}
+
+char *
+ostree_checksum_from_bytes (GVariant *csum_bytes)
+{
+ GString *ret = g_string_new ("");
+ const guchar *bytes;
+ gsize n_elts;
+ guint i;
+
+ bytes = g_variant_get_fixed_array (csum_bytes, &n_elts, 1);
+ g_assert (n_elts == 32);
+
+ for (i = 0; i < 32; i++)
+ g_string_append_printf (ret, "%x", bytes[i]);
+
+ return g_string_free (ret, FALSE);
+}
+
+GVariant *
+ostree_object_name_serialize_v2 (const char *checksum,
+ OstreeObjectType objtype)
+{
+ return g_variant_new ("(u ay)", (guint32)objtype, ostree_checksum_to_bytes (checksum));
+}
+
+void
+ostree_object_name_deserialize_v2_hex (GVariant *variant,
+ char **out_checksum,
+ OstreeObjectType *out_objtype)
+{
+ GVariant *csum_bytes;
+ guint32 objtype_u32;
+
+ g_variant_get (variant, "(u ay)", &objtype_u32, &csum_bytes);
+ g_variant_ref_sink (csum_bytes);
+ *out_checksum = ostree_checksum_from_bytes (csum_bytes);
+ g_variant_unref (csum_bytes);
+ *out_objtype = (OstreeObjectType)objtype_u32;
+}
+
+void
+ostree_object_name_deserialize_v2_bytes (GVariant *variant,
+ const guchar **out_checksum,
+ OstreeObjectType *out_objtype)
+{
+ GVariant *csum_bytes;
+ guint32 objtype_u32;
+ gsize n_elts;
+
+ g_variant_get (variant, "(u ay)", &objtype_u32, &csum_bytes);
+ *out_checksum = (guchar*)g_variant_get_fixed_array (csum_bytes, &n_elts, 1);
+ *out_objtype = (OstreeObjectType)objtype_u32;
+}
+
char *
ostree_get_relative_object_path (const char *checksum,
OstreeObjectType type)
diff --git a/src/libostree/ostree-core.h b/src/libostree/ostree-core.h
index 5feee23..447e338 100644
--- a/src/libostree/ostree-core.h
+++ b/src/libostree/ostree-core.h
@@ -106,36 +106,35 @@ typedef enum {
#define OSTREE_PACK_SUPER_INDEX_VARIANT_FORMAT G_VARIANT_TYPE ("(sua{sv}a(say))")
/* Pack index
- * s - OSTPACKINDEX
- * u - Version
+ * s - OSTv0PACKINDEX
* a{sv} - Metadata
- * a(sut) - (checksum, objtype, offset into packfile)
+ * a(uayt) - (objtype, checksum, offset into packfile)
*/
-#define OSTREE_PACK_INDEX_VARIANT_FORMAT G_VARIANT_TYPE ("(sua{sv}a(sut))")
+#define OSTREE_PACK_INDEX_VARIANT_FORMAT G_VARIANT_TYPE ("(sa{sv}a(uayt))")
typedef enum {
- OSTREE_PACK_FILE_ENTRY_TYPE_GZIP_RAW = (1 << 0)
+ OSTREE_PACK_FILE_ENTRY_FLAG_NONE = 0,
+ OSTREE_PACK_FILE_ENTRY_FLAG_GZIP = (1 << 0)
} OstreePackFileEntryFlag;
/* Pack files
- * s - OSTPACKFILE
- * u - Version
+ * s - OSTv0PACKFILE
* a{sv} - Metadata
- * u - number of entries
+ * t - number of entries
*
- * Repeating tuple of:
- * <padding to alignment of 4>
- * <32 bit BE integer containing variant length>
+ * Repeating pair of:
* <padding to alignment of 8>
- * ( tuys ) - content_length, objtype, flags, checksum
+ * ( uyayay ) - objtype, flags, checksum, data
*/
-#define OSTREE_PACK_FILE_VARIANT_FORMAT G_VARIANT_TYPE ("(sua{sv}t)")
+#define OSTREE_PACK_FILE_VARIANT_FORMAT G_VARIANT_TYPE ("(sa{sv}t)")
-#define OSTREE_PACK_FILE_CONTENT_VARIANT_FORMAT G_VARIANT_TYPE ("(tuys)")
+#define OSTREE_PACK_FILE_CONTENT_VARIANT_FORMAT G_VARIANT_TYPE ("(uyayay)")
gboolean ostree_validate_checksum_string (const char *sha256,
GError **error);
+GVariant *ostree_checksum_to_bytes (const char *sha256);
+
gboolean ostree_validate_rev (const char *rev, GError **error);
void ostree_checksum_update_stat (GChecksum *checksum, guint32 uid, guint32 gid, guint32 mode);
@@ -146,6 +145,8 @@ OstreeObjectType ostree_object_type_from_string (const char *str);
guint ostree_hash_object_name (gconstpointer a);
+int ostree_cmp_checksum_bytes (GVariant *a, GVariant *b);
+
GVariant *ostree_object_name_serialize (const char *checksum,
OstreeObjectType objtype);
@@ -153,6 +154,20 @@ void ostree_object_name_deserialize (GVariant *variant,
const char **out_checksum,
OstreeObjectType *out_objtype);
+GVariant *ostree_object_name_serialize_v2 (const char *checksum,
+ OstreeObjectType objtype);
+
+void ostree_object_name_deserialize_v2_hex (GVariant *variant,
+ char **out_checksum,
+ OstreeObjectType *out_objtype);
+
+void ostree_object_name_deserialize_v2_bytes (GVariant *variant,
+ const guchar **out_checksum,
+ OstreeObjectType *out_objtype);
+
+GVariant * ostree_checksum_to_bytes (const char *sha256);
+char * ostree_checksum_from_bytes (GVariant *bytes);
+
char * ostree_object_to_string (const char *checksum,
OstreeObjectType objtype);
diff --git a/src/libostree/ostree-repo-file.c b/src/libostree/ostree-repo-file.c
index 9cc7b82..0370bcc 100644
--- a/src/libostree/ostree-repo-file.c
+++ b/src/libostree/ostree-repo-file.c
@@ -817,13 +817,9 @@ ostree_repo_file_tree_query_child (OstreeRepoFile *self,
const char *name = NULL;
gboolean ret = FALSE;
GFileInfo *ret_info = NULL;
- GFile *archive_data_path = NULL;
- GFileInfo *archive_data_info = NULL;
- GVariant *archive_metadata = NULL;
GVariant *files_variant = NULL;
GVariant *dirs_variant = NULL;
GVariant *tree_child_metadata = NULL;
- GFile *local_child = NULL;
GFileAttributeMatcher *matcher = NULL;
int c;
@@ -844,40 +840,9 @@ ostree_repo_file_tree_query_child (OstreeRepoFile *self,
g_variant_get_child (files_variant, n, "(&s&s)", &name, &checksum);
- local_child = ostree_repo_get_file_object_path (self->repo, checksum);
-
- if (ostree_repo_get_mode (self->repo) == OSTREE_REPO_MODE_ARCHIVE)
- {
- if (!ostree_map_metadata_file (local_child, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META,
- &archive_metadata, error))
- goto out;
- if (!ostree_parse_archived_file_meta (archive_metadata, &ret_info, NULL, error))
- goto out;
-
- archive_data_path = ostree_repo_get_object_path (self->repo, checksum,
- OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT);
- archive_data_info = g_file_query_info (archive_data_path,
- OSTREE_GIO_FAST_QUERYINFO,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- cancellable,
- error);
- if (!archive_data_info)
- goto out;
-
- g_file_info_set_attribute_uint64 (ret_info, "standard::size",
- g_file_info_get_attribute_uint64 (archive_data_info,
- "standard::size"));
- }
- else
- {
- ret_info = g_file_query_info (local_child,
- OSTREE_GIO_FAST_QUERYINFO,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- cancellable,
- error);
- if (!ret_info)
- goto out;
- }
+ if (!ostree_repo_load_file (self->repo, checksum, NULL, &ret_info, NULL,
+ cancellable, error))
+ goto out;
}
else
{
@@ -918,12 +883,8 @@ ostree_repo_file_tree_query_child (OstreeRepoFile *self,
ot_transfer_out_value(out_info, &ret_info);
out:
g_clear_object (&ret_info);
- g_clear_object (&local_child);
- g_clear_object (&archive_data_path);
- g_clear_object (&archive_data_info);
if (matcher)
g_file_attribute_matcher_unref (matcher);
- ot_clear_gvariant (&archive_metadata);
ot_clear_gvariant (&tree_child_metadata);
ot_clear_gvariant (&files_variant);
ot_clear_gvariant (&dirs_variant);
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index ff2486f..323c6da 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -967,6 +967,7 @@ stage_object_impl (OstreeRepo *self,
GFile *stored_path = NULL;
GFile *pending_path = NULL;
char *pack_checksum = NULL;
+ guint64 pack_offset;
const char *actual_checksum;
g_return_val_if_fail (priv->in_transaction, FALSE);
@@ -980,7 +981,7 @@ stage_object_impl (OstreeRepo *self,
{
if (!ostree_repo_find_object (self, objtype, expected_checksum,
&stored_path, &pending_path,
- &pack_checksum,
+ &pack_checksum, &pack_offset,
cancellable, error))
goto out;
}
@@ -1208,33 +1209,6 @@ stage_gvariant_object (OstreeRepo *self,
return ret;
}
-gboolean
-ostree_repo_load_variant (OstreeRepo *self,
- OstreeObjectType expected_type,
- const char *sha256,
- GVariant **out_variant,
- GError **error)
-{
- gboolean ret = FALSE;
- GFile *object_path = NULL;
- GFile *tmpfile = NULL;
- GVariant *ret_variant = NULL;
-
- g_return_val_if_fail (OSTREE_OBJECT_TYPE_IS_META (expected_type), FALSE);
-
- object_path = ostree_repo_get_object_path (self, sha256, expected_type);
- if (!ostree_map_metadata_file (object_path, expected_type, &ret_variant, error))
- goto out;
-
- ret = TRUE;
- ot_transfer_out_value (out_variant, &ret_variant);
- out:
- g_clear_object (&object_path);
- g_clear_object (&tmpfile);
- ot_clear_gvariant (&ret_variant);
- return ret;
-}
-
static gboolean
stage_directory_meta (OstreeRepo *self,
GFileInfo *file_info,
@@ -2618,7 +2592,7 @@ ostree_repo_map_pack_file (OstreeRepo *self,
static gboolean
bsearch_in_pack_index (GVariant *index_contents,
- const char *checksum,
+ GVariant *csum_bytes,
OstreeObjectType objtype,
guint64 *out_offset)
{
@@ -2633,15 +2607,15 @@ bsearch_in_pack_index (GVariant *index_contents,
while (i <= n)
{
- const char *cur_checksum;
+ GVariant *cur_csum_bytes;
guint32 cur_objtype;
guint64 cur_offset;
int c;
m = i + ((n - i) / 2);
- g_variant_get_child (index_contents, m, "&sut", &cur_checksum, &cur_objtype, &cur_offset);
- c = strcmp (cur_checksum, checksum);
+ g_variant_get_child (index_contents, m, "(u ayt)", &cur_objtype, &cur_csum_bytes, &cur_offset);
+ c = ostree_cmp_checksum_bytes (cur_csum_bytes, csum_bytes);
if (c == 0)
{
if (cur_objtype < target_objtype)
@@ -2649,6 +2623,7 @@ bsearch_in_pack_index (GVariant *index_contents,
else if (cur_objtype > target_objtype)
c = 1;
}
+ g_variant_unref (cur_csum_bytes);
if (c < 0)
i = m + 1;
@@ -2665,25 +2640,19 @@ bsearch_in_pack_index (GVariant *index_contents,
}
static gboolean
-parse_pack_entry (gboolean trusted,
- guchar *pack_data,
- guint64 pack_len,
- guint64 offset,
- GVariant **out_header,
- GInputStream **out_input,
- GCancellable *cancellable,
- GError **error)
+read_pack_entry (gboolean trusted,
+ guchar *pack_data,
+ guint64 pack_len,
+ guint64 offset,
+ GVariant **out_entry,
+ GCancellable *cancellable,
+ GError **error)
{
gboolean ret = FALSE;
- GVariant *ret_header = NULL;
- GConverter *decompressor = NULL;
- GInputStream *raw_input = NULL;
- GInputStream *ret_input = NULL;
- guint64 data_offset;
- guint64 header_start;
- guint64 header_end;
- guint32 header_len;
- guchar entry_type;
+ GVariant *ret_entry = NULL;
+ guint64 entry_start;
+ guint64 entry_end;
+ guint32 entry_len;
if (G_UNLIKELY (!(offset < pack_len)))
{
@@ -2701,117 +2670,201 @@ parse_pack_entry (gboolean trusted,
}
g_assert ((((guint64)pack_data+offset) & 0x3) == 0);
- header_len = GUINT32_FROM_BE (*((guint32*)(pack_data+offset)));
- header_end = offset + header_len;
- if (G_UNLIKELY (!(header_end < pack_len)))
+ entry_len = GUINT32_FROM_BE (*((guint32*)(pack_data+offset)));
+ entry_end = offset + entry_len;
+ if (G_UNLIKELY (!(entry_end < pack_len)))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Corrupted pack index; out of range header length %u",
- header_len);
+ "Corrupted pack index; out of range entry length %u",
+ entry_len);
goto out;
}
- header_start = offset + 4;
- if (G_UNLIKELY (!(header_start < pack_len)))
+ entry_start = offset + 4;
+ if (G_UNLIKELY (!(entry_start < pack_len)))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Corrupted pack index; out of range data offset %" G_GUINT64_FORMAT,
- header_start);
+ entry_start);
goto out;
}
- ret_header = g_variant_new_from_data (OSTREE_PACK_FILE_CONTENT_VARIANT_FORMAT,
- pack_data+header_start, header_len,
- trusted, NULL, NULL);
+ ret_entry = g_variant_new_from_data (OSTREE_PACK_FILE_CONTENT_VARIANT_FORMAT,
+ pack_data+entry_start, entry_len,
+ trusted, NULL, NULL);
+ ret = TRUE;
+ ot_transfer_out_value (out_entry, &ret_entry);
+ out:
+ ot_clear_gvariant (&ret_entry);
+ return ret;
+}
- g_variant_get_child (ret_header, 2, "y", &entry_type);
-
- if (entry_type != OSTREE_PACK_FILE_ENTRY_TYPE_GZIP_RAW)
+static GInputStream *
+get_pack_entry_stream (GVariant *pack_entry)
+{
+ GInputStream *memory_input;
+ GInputStream *ret_input = NULL;
+ GVariant *pack_data = NULL;
+ guchar entry_flags;
+ gconstpointer data_ptr;
+ gsize data_len;
+
+ g_variant_get_child (pack_entry, 1, "y", &entry_flags);
+ g_variant_get_child (pack_entry, 3, "@ay", &pack_data);
+ g_variant_ref_sink (pack_data);
+
+ data_ptr = g_variant_get_fixed_array (pack_data, &data_len, 1);
+ memory_input = g_memory_input_stream_new_from_data (data_ptr, data_len, NULL);
+ g_object_set_data_full ((GObject*)memory_input, "ostree-mem-gvariant",
+ pack_data, (GDestroyNotify) g_variant_unref);
+
+ if (entry_flags & OSTREE_PACK_FILE_ENTRY_FLAG_GZIP)
{
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Corrupted pack; invalid entry type %u",
- entry_type);
- goto out;
- }
+ GConverter *decompressor;
- /* Skip 4 bytes for the header len, the actual header, then align to
- * 8.
- */
- data_offset = (offset + 4 + header_len + 7) & ~0x7;
- if (G_UNLIKELY (!(data_offset < pack_len)))
+ decompressor = (GConverter*)g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
+ ret_input = (GInputStream*)g_object_new (G_TYPE_CONVERTER_INPUT_STREAM,
+ "converter", decompressor,
+ "base-stream", memory_input,
+ "close-base-stream", TRUE,
+ NULL);
+ g_object_unref (decompressor);
+ }
+ else
{
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Corrupted pack index; out of range offset %" G_GUINT64_FORMAT,
- offset);
- goto out;
+ ret_input = memory_input;
+ memory_input = NULL;
}
- raw_input = (GInputStream*)g_memory_input_stream_new_from_data (pack_data + data_offset,
- pack_len - data_offset,
- NULL);
+ return ret_input;
+}
- decompressor = (GConverter*)g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
- ret_input = (GInputStream*)g_object_new (G_TYPE_CONVERTER_INPUT_STREAM,
- "converter", decompressor,
- "base-stream", raw_input,
- "close-base-stream", TRUE,
- NULL);
+static GVariant *
+get_pack_entry_as_variant (GVariant *pack_entry,
+ const GVariantType *type,
+ gboolean trusted)
+{
+ GVariant *pack_data;
+ GVariant *ret_variant;
+ gconstpointer data_ptr;
+ gsize data_len;
- ret = TRUE;
- ot_transfer_out_value (out_header, &ret_header);
- ot_transfer_out_value (out_input, &ret_input);
- out:
- ot_clear_gvariant (&ret_header);
- g_clear_object (&raw_input);
- g_clear_object (&decompressor);
- g_clear_object (&ret_input);
- return ret;
+ g_variant_get_child (pack_entry, 3, "@ay", &pack_data);
+ data_ptr = g_variant_get_fixed_array (pack_data, &data_len, 1);
+ ret_variant = g_variant_new_from_data (type, data_ptr, data_len, trusted,
+ (GDestroyNotify)g_variant_unref,
+ pack_data);
+ return ret_variant;
}
gboolean
-ostree_repo_load_pack_entry (OstreeRepo *self,
- const char *pack_sha256,
- const char *entry_sha256,
- OstreeObjectType objtype,
- GInputStream **out_input,
- GCancellable *cancellable,
- GError **error)
+ostree_repo_load_file (OstreeRepo *self,
+ const char *checksum,
+ GInputStream **out_input,
+ GFileInfo **out_file_info,
+ GVariant **out_xattrs,
+ GCancellable *cancellable,
+ GError **error)
{
gboolean ret = FALSE;
- guint64 offset;
- guchar *pack_data;
- guint64 pack_len;
- GVariant *index = NULL;
- GVariant *index_contents = NULL;
+ GVariant *archive_meta = NULL;
+ GFile *content_loose_path = NULL;
+ GFileInfo *content_loose_info = NULL;
+ char *content_pack_checksum = NULL;
+ guint64 content_pack_offset;
+ guchar *content_pack_data;
+ guint64 content_pack_len;
+ GVariant *packed_object = NULL;
GInputStream *ret_input = NULL;
+ GFileInfo *ret_file_info = NULL;
+ GVariant *ret_xattrs = NULL;
- if (!ostree_repo_load_pack_index (self, pack_sha256, &index, cancellable, error))
- goto out;
-
- index_contents = g_variant_get_child_value (index, 3);
-
- if (!bsearch_in_pack_index (index_contents, entry_sha256, objtype, &offset))
+ if (ostree_repo_get_mode (self) == OSTREE_REPO_MODE_ARCHIVE)
{
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Object '%s' of type %u not in pack",
- entry_sha256, (guint32)objtype);
- goto out;
- }
+ /* First, read the metadata */
+ if (!ostree_repo_load_variant (self, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META, checksum,
+ &archive_meta, error))
+ goto out;
+ if (!ostree_parse_archived_file_meta (archive_meta,
+ &ret_file_info,
+ &ret_xattrs,
+ error))
+ goto out;
- if (!ostree_repo_map_pack_file (self, pack_sha256, &pack_data, &pack_len,
- cancellable, error))
- goto out;
+ /* Blah, right now we need to look up the content too to get the file size */
+ if (!ostree_repo_find_object (self, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT,
+ checksum, &content_loose_path, NULL,
+ &content_pack_checksum, &content_pack_offset,
+ cancellable, error))
+ goto out;
- if (!parse_pack_entry (TRUE, pack_data, pack_len, offset, NULL, &ret_input,
- cancellable, error))
- goto out;
+ if (content_loose_path)
+ {
+ content_loose_info = g_file_query_info (content_loose_path, OSTREE_GIO_FAST_QUERYINFO,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable, error);
+ if (!content_loose_info)
+ goto out;
+
+ g_file_info_set_attribute_uint64 (ret_file_info,
+ "standard::size",
+ g_file_info_get_attribute_uint64 (content_loose_info, "standard::size"));
+ }
+ /* fixme - don't have file size for packed =/ */
+
+ /* Now, look for the content */
+ if (g_file_info_get_file_type (ret_file_info) == G_FILE_TYPE_REGULAR
+ && out_input)
+ {
+ if (content_pack_checksum != NULL)
+ {
+ if (!ostree_repo_map_pack_file (self, content_pack_checksum,
+ &content_pack_data, &content_pack_len,
+ cancellable, error))
+ goto out;
+ if (!read_pack_entry (TRUE, content_pack_data, content_pack_len, content_pack_offset,
+ &packed_object, cancellable, error))
+ goto out;
+ ret_input = get_pack_entry_stream (packed_object);
+ }
+ else if (content_loose_path != NULL)
+ {
+ ret_input = (GInputStream*)g_file_read (content_loose_path, cancellable, error);
+ if (!ret_input)
+ goto out;
+ }
+ else
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+ "Couldn't find object '%s'", checksum);
+ goto out;
+ }
+ }
+ }
+ else
+ {
+ content_loose_path = ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_RAW_FILE);
+ ret_file_info = g_file_query_info (content_loose_path, OSTREE_GIO_FAST_QUERYINFO,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable, error);
+ if (!ret_file_info)
+ goto out;
+ if (out_xattrs)
+ {
+ ret_xattrs = ostree_get_xattrs_for_file (content_loose_path, error);
+ if (!ret_xattrs)
+ goto out;
+ }
+ }
ret = TRUE;
ot_transfer_out_value (out_input, &ret_input);
+ ot_transfer_out_value (out_file_info, &ret_file_info);
+ ot_transfer_out_value (out_xattrs, &ret_xattrs);
out:
- ot_clear_gvariant (&index);
- ot_clear_gvariant (&index_contents);
+ g_free (content_pack_checksum);
g_clear_object (&ret_input);
+ g_clear_object (&content_loose_info);
+ g_clear_object (&ret_file_info);
+ ot_clear_gvariant (&ret_xattrs);
return ret;
}
@@ -2827,7 +2880,8 @@ list_objects_in_index (OstreeRepo *self,
GVariant *index_variant = NULL;
GVariant *contents;
GVariantIter content_iter;
- const char *checksum;
+ GVariant *csum_bytes;
+ char *checksum = NULL;
guint32 objtype_u32;
guint64 offset;
@@ -2839,7 +2893,7 @@ list_objects_in_index (OstreeRepo *self,
contents = g_variant_get_child_value (index_variant, 3);
g_variant_iter_init (&content_iter, contents);
- while (g_variant_iter_loop (&content_iter, "(&sut)", &checksum, &objtype_u32, &offset))
+ while (g_variant_iter_loop (&content_iter, "(&u ayt)", &objtype_u32, &csum_bytes, &offset))
{
GVariant *obj_key;
GVariant *objdata;
@@ -2849,7 +2903,9 @@ list_objects_in_index (OstreeRepo *self,
g_variant_builder_init (&pack_contents_builder,
G_VARIANT_TYPE_STRING_ARRAY);
-
+
+ g_free (checksum);
+ checksum = ostree_checksum_from_bytes (csum_bytes);
obj_key = ostree_object_name_serialize (checksum, objtype);
objdata = g_hash_table_lookup (inout_objects, obj_key);
@@ -2880,6 +2936,7 @@ list_objects_in_index (OstreeRepo *self,
ret = TRUE;
out:
+ g_free (checksum);
g_clear_object (&index_path);
ot_clear_gvariant (&index_variant);
ot_clear_gvariant (&contents);
@@ -2953,17 +3010,22 @@ find_object_in_packs (OstreeRepo *self,
const char *checksum,
OstreeObjectType objtype,
char **out_pack_checksum,
+ guint64 *out_pack_offset,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
GPtrArray *index_checksums = NULL;
char *ret_pack_checksum = NULL;
+ guint64 ret_pack_offset;
GFile *index_path = NULL;
+ GVariant *csum_bytes = NULL;
GVariant *index_variant = NULL;
GVariant *index_contents = NULL;
guint i;
+ csum_bytes = ostree_checksum_to_bytes (checksum);
+
if (!ostree_repo_list_pack_indexes (self, &index_checksums, cancellable, error))
goto out;
@@ -2982,21 +3044,25 @@ find_object_in_packs (OstreeRepo *self,
ot_clear_gvariant (&index_contents);
index_contents = g_variant_get_child_value (index_variant, 3);
- if (!bsearch_in_pack_index (index_contents, checksum, objtype, &offset))
+ if (!bsearch_in_pack_index (index_contents, csum_bytes, objtype, &offset))
continue;
ret_pack_checksum = g_strdup (checksum);
+ ret_pack_offset = offset;
break;
}
ret = TRUE;
ot_transfer_out_value (out_pack_checksum, &ret_pack_checksum);
+ if (out_pack_offset)
+ *out_pack_offset = ret_pack_offset;
out:
g_free (ret_pack_checksum);
if (index_checksums)
g_ptr_array_unref (index_checksums);
g_clear_object (&index_path);
ot_clear_gvariant (&index_variant);
+ ot_clear_gvariant (&csum_bytes);
ot_clear_gvariant (&index_contents);
return ret;
}
@@ -3008,48 +3074,129 @@ ostree_repo_find_object (OstreeRepo *self,
GFile **out_stored_path,
GFile **out_pending_path,
char **out_pack_checksum,
+ guint64 *out_pack_offset,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
GFile *object_path = NULL;
+ GFile *ret_stored_path = NULL;
+ GFile *ret_pending_path = NULL;
char *ret_pack_checksum = NULL;
+ guint64 ret_pack_offset = 0;
struct stat stbuf;
- g_return_val_if_fail (out_stored_path, FALSE);
- g_return_val_if_fail (out_pending_path, FALSE);
-
object_path = ostree_repo_get_object_path (self, checksum, objtype);
- *out_stored_path = NULL;
- *out_pending_path = NULL;
if (lstat (ot_gfile_get_path_cached (object_path), &stbuf) == 0)
{
- *out_stored_path = object_path;
+ ret_stored_path = object_path;
object_path = NULL;
}
else
{
g_clear_object (&object_path);
- object_path = get_pending_object_path (self, checksum, objtype);
- if (lstat (ot_gfile_get_path_cached (object_path), &stbuf) == 0)
+ if (out_pending_path)
{
- *out_pending_path = object_path;
- object_path = NULL;
+ object_path = get_pending_object_path (self, checksum, objtype);
+ if (lstat (ot_gfile_get_path_cached (object_path), &stbuf) == 0)
+ {
+ ret_pending_path = object_path;
+ object_path = NULL;
+ }
}
- if (!find_object_in_packs (self, checksum, objtype, &ret_pack_checksum,
+ }
+
+ if (out_pack_checksum)
+ {
+ if (!find_object_in_packs (self, checksum, objtype,
+ &ret_pack_checksum, &ret_pack_offset,
cancellable, error))
goto out;
}
ret = TRUE;
+ ot_transfer_out_value (out_stored_path, &ret_stored_path);
+ ot_transfer_out_value (out_pending_path, &ret_pending_path);
ot_transfer_out_value (out_pack_checksum, &ret_pack_checksum);
+ if (out_pack_offset)
+ *out_pack_offset = ret_pack_offset;
out:
g_clear_object (&object_path);
+ g_clear_object (&ret_stored_path);
+ g_clear_object (&ret_pending_path);
g_free (ret_pack_checksum);
return ret;
}
+gboolean
+ostree_repo_load_variant (OstreeRepo *self,
+ OstreeObjectType expected_type,
+ const char *sha256,
+ GVariant **out_variant,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ GFile *object_path = NULL;
+ GVariant *packed_object = NULL;
+ GVariant *container_variant = NULL;
+ GVariant *ret_variant = NULL;
+ char *pack_checksum = NULL;
+ guchar *pack_data;
+ guint64 pack_len;
+ guint64 object_offset;
+ GCancellable *cancellable = NULL;
+
+ g_return_val_if_fail (OSTREE_OBJECT_TYPE_IS_META (expected_type), FALSE);
+
+ if (!ostree_repo_find_object (self, expected_type, sha256, &object_path, NULL,
+ &pack_checksum, &object_offset,
+ cancellable, error))
+ goto out;
+
+ /* Prefer loose metadata for now */
+ if (object_path != NULL)
+ {
+ if (!ostree_map_metadata_file (object_path, expected_type, &ret_variant, error))
+ goto out;
+ }
+ else
+ {
+ guint32 actual_type;
+
+ if (!ostree_repo_map_pack_file (self, pack_checksum, &pack_data, &pack_len,
+ cancellable, error))
+ goto out;
+
+ if (!read_pack_entry (TRUE, pack_data, pack_len, object_offset, &packed_object,
+ cancellable, error))
+ goto out;
+
+ container_variant = get_pack_entry_as_variant (packed_object, OSTREE_SERIALIZED_VARIANT_FORMAT, TRUE);
+
+ g_variant_get (container_variant, "(uv)",
+ &actual_type, &ret_variant);
+ ot_util_variant_take_ref (ret_variant);
+
+ if (actual_type != expected_type)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Corrupted metadata object '%s'; found type %u, expected %u",
+ sha256, actual_type, (guint32)expected_type);
+ goto out;
+ }
+ }
+
+ ret = TRUE;
+ ot_transfer_out_value (out_variant, &ret_variant);
+ out:
+ g_clear_object (&object_path);
+ g_free (pack_checksum);
+ ot_clear_gvariant (&ret_variant);
+ ot_clear_gvariant (&packed_object);
+ ot_clear_gvariant (&container_variant);
+ return ret;
+}
/**
* ostree_repo_list_objects:
* @self:
@@ -3256,58 +3403,46 @@ checkout_one_file (OstreeRepo *self,
{
gboolean ret = FALSE;
OstreeRepoPrivate *priv = GET_PRIVATE (self);
- GVariant *archive_metadata = NULL;
+ GFile *possible_loose_path = NULL;
+ GInputStream *input = NULL;
GVariant *xattrs = NULL;
const char *checksum;
- GFile *content_object_path = NULL;
- GInputStream *content_input = NULL;
- GFile *object_path = NULL;
+ struct stat stbuf;
checksum = ostree_repo_file_get_checksum ((OstreeRepoFile*)src);
+ /* First check for a loose object */
if (priv->mode == OSTREE_REPO_MODE_ARCHIVE && mode == OSTREE_REPO_CHECKOUT_MODE_USER)
{
- object_path = ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT);
-
- if (!checkout_file_hardlink (self, mode, overwrite_mode, object_path, destination, cancellable, error) < 0)
- goto out;
+ possible_loose_path = ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT);
}
- else if (priv->mode == OSTREE_REPO_MODE_ARCHIVE)
+ else if (priv->mode == OSTREE_REPO_MODE_BARE && mode == OSTREE_REPO_CHECKOUT_MODE_NONE)
{
- if (!ostree_repo_load_variant (self, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META, checksum, &archive_metadata, error))
- goto out;
-
- if (!ostree_parse_archived_file_meta (archive_metadata, NULL, &xattrs, error))
- goto out;
-
- content_object_path = ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT);
-
- if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
- {
- content_input = (GInputStream*)g_file_read (content_object_path, cancellable, error);
- if (!content_input)
- goto out;
- }
+ possible_loose_path = ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_RAW_FILE);
+ }
- if (!checkout_file_from_input (destination, mode, overwrite_mode, file_info, xattrs,
- content_input, cancellable, error))
+ if (possible_loose_path && lstat (ot_gfile_get_path_cached (possible_loose_path), &stbuf) >= 0)
+ {
+ /* If we found one, we can just hardlink */
+ if (!checkout_file_hardlink (self, mode, overwrite_mode, possible_loose_path, destination,
+ cancellable, error) < 0)
goto out;
}
else
{
- object_path = ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_RAW_FILE);
+ if (!ostree_repo_load_file (self, checksum, &input, NULL, &xattrs, cancellable, error))
+ goto out;
- if (!checkout_file_hardlink (self, mode, overwrite_mode, object_path, destination, cancellable, error) < 0)
+ if (!checkout_file_from_input (destination, mode, overwrite_mode, file_info, xattrs,
+ input, cancellable, error))
goto out;
}
ret = TRUE;
out:
- g_clear_object (&object_path);
- ot_clear_gvariant (&archive_metadata);
+ g_clear_object (&possible_loose_path);
+ g_clear_object (&input);
ot_clear_gvariant (&xattrs);
- g_clear_object (&content_object_path);
- g_clear_object (&content_input);
return ret;
}
@@ -3393,6 +3528,7 @@ ostree_repo_checkout_tree (OstreeRepo *self,
g_free (dest_path);
return ret;
}
+
gboolean
ostree_repo_read_commit (OstreeRepo *self,
const char *rev,
diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h
index 2fc4508..a825d48 100644
--- a/src/libostree/ostree-repo.h
+++ b/src/libostree/ostree-repo.h
@@ -98,6 +98,7 @@ gboolean ostree_repo_find_object (OstreeRepo *self,
GFile **out_stored_path,
GFile **out_pending_path,
char **out_pack_checksum,
+ guint64 *out_pack_offset,
GCancellable *cancellable,
GError **error);
@@ -161,13 +162,14 @@ gboolean ostree_repo_map_pack_file (OstreeRepo *self,
GCancellable *cancellable,
GError **error);
-gboolean ostree_repo_load_pack_entry (OstreeRepo *self,
- const char *pack_sha256,
- const char *entry_sha256,
- OstreeObjectType objtype,
- GInputStream **object_input,
- GCancellable *cancellable,
- GError **error);
+gboolean ostree_repo_load_file (OstreeRepo *self,
+ const char *entry_sha256,
+ GInputStream **out_input,
+ GFileInfo **out_file_info,
+ GVariant **out_xattrs,
+ GCancellable *cancellable,
+ GError **error);
+
typedef enum {
OSTREE_REPO_COMMIT_FILTER_ALLOW,
OSTREE_REPO_COMMIT_FILTER_SKIP
diff --git a/src/ostree/ostree-pull.c b/src/ostree/ostree-pull.c
index 619042e..b9a76a5 100644
--- a/src/ostree/ostree-pull.c
+++ b/src/ostree/ostree-pull.c
@@ -234,7 +234,8 @@ fetch_and_store_object (OstreeRepo *repo,
g_assert (objtype != OSTREE_OBJECT_TYPE_RAW_FILE);
if (!ostree_repo_find_object (repo, objtype, checksum,
- &stored_path, &pending_path, &pack_checksum,
+ &stored_path, &pending_path,
+ &pack_checksum, NULL,
cancellable, error))
goto out;
@@ -351,14 +352,14 @@ fetch_and_store_tree_recurse (OstreeRepo *repo,
if (ostree_repo_get_mode (repo) == OSTREE_REPO_MODE_BARE)
{
if (!ostree_repo_find_object (repo, OSTREE_OBJECT_TYPE_RAW_FILE, checksum,
- &stored_path, &pending_path, &pack_checksum,
+ &stored_path, &pending_path, &pack_checksum, NULL,
cancellable, error))
goto out;
}
else
{
if (!ostree_repo_find_object (repo, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT, checksum,
- &stored_path, &pending_path, &pack_checksum,
+ &stored_path, &pending_path, &pack_checksum, NULL,
cancellable, error))
goto out;
}
diff --git a/src/ostree/ot-builtin-repack.c b/src/ostree/ot-builtin-repack.c
index 40c92f9..ceefd6d 100644
--- a/src/ostree/ot-builtin-repack.c
+++ b/src/ostree/ot-builtin-repack.c
@@ -188,17 +188,17 @@ compare_index_content (gconstpointer ap,
gpointer b = *((gpointer*)bp);
GVariant *a_v = a;
GVariant *b_v = b;
- const char *a_checksum;
- const char *b_checksum;
+ GVariant *a_csum_bytes;
+ GVariant *b_csum_bytes;
guint32 a_objtype;
guint32 b_objtype;
guint64 a_offset;
guint64 b_offset;
int c;
- g_variant_get (a_v, "(&sut)", &a_checksum, &a_objtype, &a_offset);
- g_variant_get (b_v, "(&sut)", &b_checksum, &b_objtype, &b_offset);
- c = strcmp (a_checksum, b_checksum);
+ g_variant_get (a_v, "(u ayt)", &a_objtype, &a_csum_bytes, &a_offset);
+ g_variant_get (b_v, "(u ayt)", &b_objtype, &b_csum_bytes, &b_offset);
+ c = ostree_cmp_checksum_bytes (a_csum_bytes, b_csum_bytes);
if (c == 0)
{
if (a_objtype < b_objtype)
@@ -232,13 +232,14 @@ create_pack_file (OtRepackData *data,
gsize bytes_written;
GPtrArray *index_content_list = NULL;
GVariant *pack_header = NULL;
- GVariant *object_header = NULL;
+ GVariant *packed_object = NULL;
GVariant *index_content = NULL;
GVariantBuilder index_content_builder;
GChecksum *pack_checksum = NULL;
char *pack_name = NULL;
GFile *pack_file_path = NULL;
GFile *pack_index_path = NULL;
+ GMemoryOutputStream *object_data_stream = NULL;
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return FALSE;
@@ -262,10 +263,10 @@ create_pack_file (OtRepackData *data,
offset = 0;
pack_checksum = g_checksum_new (G_CHECKSUM_SHA256);
- pack_header = g_variant_new ("(su a{sv}u)",
- "OSTPACK", GUINT32_TO_BE (0),
+ pack_header = g_variant_new ("(s a{sv}t)",
+ "OSTv0PACKFILE",
g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0),
- objects->len);
+ (guint64)objects->len);
if (!write_variant_with_size (pack_out, pack_header, pack_checksum, &offset,
cancellable, error))
@@ -281,8 +282,9 @@ create_pack_file (OtRepackData *data,
guint64 obj_bytes_written;
guint64 expected_objsize;
guint64 objsize;
- GOutputStream *write_pack_out;
- guchar entry_type;
+ GOutputStream *write_object_out;
+ guchar entry_flags = 0;
+ GVariant *index_entry;
g_variant_get (object_data, "(&sut)", &checksum, &objtype_u32, &expected_objsize);
@@ -292,21 +294,30 @@ create_pack_file (OtRepackData *data,
goto out;
/* offset points to aligned header size */
- g_ptr_array_add (index_content_list,
- g_variant_ref_sink (g_variant_new ("(sut)", checksum, (guint32)objtype, offset)));
+ index_entry = g_variant_new ("(uayt)",
+ (guint32)objtype, ostree_checksum_to_bytes (checksum), offset);
+ g_ptr_array_add (index_content_list, g_variant_ref_sink (index_entry));
- ot_clear_gvariant (&object_header);
- switch (data->int_compression)
+ if (objtype == OSTREE_OBJECT_TYPE_DIR_TREE
+ || objtype == OSTREE_OBJECT_TYPE_DIR_META
+ || objtype == OSTREE_OBJECT_TYPE_COMMIT)
{
- case OT_COMPRESSION_GZIP:
- {
- entry_type = OSTREE_PACK_FILE_ENTRY_TYPE_GZIP_RAW;
- break;
- }
- default:
- {
- g_assert_not_reached ();
- }
+ ;
+ }
+ else
+ {
+ switch (data->int_compression)
+ {
+ case OT_COMPRESSION_GZIP:
+ {
+ entry_flags |= OSTREE_PACK_FILE_ENTRY_FLAG_GZIP;
+ break;
+ }
+ default:
+ {
+ g_assert_not_reached ();
+ }
+ }
}
g_clear_object (&object_path);
@@ -326,38 +337,26 @@ create_pack_file (OtRepackData *data,
g_assert_cmpint (objsize, ==, expected_objsize);
- ot_clear_gvariant (&object_header);
- object_header = g_variant_new ("(tuys)", GUINT64_TO_BE (objsize),
- GUINT32_TO_BE ((guint32)objtype),
- entry_type,
- checksum);
-
- if (!write_variant_with_size (pack_out, object_header, pack_checksum,
- &offset, cancellable, error))
- goto out;
+ g_clear_object (&object_data_stream);
+ object_data_stream = (GMemoryOutputStream*)g_memory_output_stream_new (NULL, 0, NULL, NULL);
- if (data->int_compression != OT_COMPRESSION_NONE)
+ if (entry_flags & OSTREE_PACK_FILE_ENTRY_FLAG_GZIP)
{
g_clear_object (&compressor);
- switch (data->int_compression)
- {
- case OT_COMPRESSION_GZIP:
- compressor = (GConverter*)g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP, OT_GZIP_COMPRESSION_LEVEL);
- break;
- default:
- g_assert_not_reached ();
- }
+ compressor = (GConverter*)g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP, OT_GZIP_COMPRESSION_LEVEL);
g_clear_object (&compressed_object_output);
compressed_object_output = (GConverterOutputStream*)g_object_new (G_TYPE_CONVERTER_OUTPUT_STREAM,
"converter", compressor,
- "base-stream", pack_out,
- "close-base-stream", FALSE,
+ "base-stream", object_data_stream,
+ "close-base-stream", TRUE,
NULL);
- write_pack_out = (GOutputStream*)compressed_object_output;
+ write_object_out = (GOutputStream*)compressed_object_output;
}
else
- write_pack_out = (GOutputStream*)pack_out;
+ {
+ write_object_out = (GOutputStream*)object_data_stream;
+ }
obj_bytes_written = 0;
do
@@ -367,7 +366,7 @@ create_pack_file (OtRepackData *data,
g_checksum_update (pack_checksum, (guint8*)buf, bytes_read);
if (bytes_read > 0)
{
- if (!g_output_stream_write_all (write_pack_out, buf, bytes_read, &bytes_written, cancellable, error))
+ if (!g_output_stream_write_all (write_object_out, buf, bytes_read, &bytes_written, cancellable, error))
goto out;
offset += bytes_written;
obj_bytes_written += bytes_written;
@@ -375,14 +374,24 @@ create_pack_file (OtRepackData *data,
}
while (bytes_read > 0);
- if (compressed_object_output)
- {
- if (!g_output_stream_flush ((GOutputStream*)compressed_object_output, cancellable, error))
- goto out;
- }
+ if (!g_output_stream_close (write_object_out, cancellable, error))
+ goto out;
g_assert_cmpint (obj_bytes_written, ==, objsize);
+ ot_clear_gvariant (&packed_object);
+ packed_object = g_variant_new ("(uy ay@ay)", GUINT32_TO_BE ((guint32)objtype),
+ entry_flags,
+ g_variant_new_fixed_array (G_VARIANT_TYPE ("y"),
+ g_memory_output_stream_get_data (object_data_stream),
+ g_memory_output_stream_get_data_size (object_data_stream),
+ 1),
+ ostree_checksum_to_bytes (checksum));
+ g_clear_object (&object_data_stream);
+
+ if (!write_variant_with_size (pack_out, packed_object, pack_checksum,
+ &offset, cancellable, error))
+ goto out;
}
if (!g_output_stream_close (pack_out, cancellable, error))
@@ -414,8 +423,8 @@ create_pack_file (OtRepackData *data,
GVariant *index_item = index_content_list->pdata[i];
g_variant_builder_add_value (&index_content_builder, index_item);
}
- index_content = g_variant_new ("(su a{sv}@a(sut))",
- "OSTPACKINDEX", GUINT32_TO_BE(0),
+ index_content = g_variant_new ("(s a{sv}@a(uayt))",
+ "OSTv0PACKINDEX",
g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0),
g_variant_builder_end (&index_content_builder));
@@ -460,7 +469,6 @@ create_pack_file (OtRepackData *data,
g_clear_object (&compressor);
g_clear_object (&compressed_object_output);
g_clear_object (&object_file_info);
- ot_clear_gvariant (&object_header);
if (pack_checksum)
g_checksum_free (pack_checksum);
g_clear_object (&pack_dir);
@@ -544,7 +552,7 @@ cluster_objects_stupidly (OtRepackData *data,
g_variant_get_child (objdata, 2, "t", &objsize);
- if (current_size + objsize > data->pack_size)
+ if (current_size + objsize > data->pack_size || i == (object_list->len - 1))
{
guint j;
GPtrArray *current = g_ptr_array_new ();
@@ -708,7 +716,6 @@ do_stats_gather_loose (OtRepackData *data,
{
GVariant *copy = g_variant_ref (serialized_key);
g_hash_table_replace (ret_loose_and_packed, copy, copy);
- n_loose++;
n_loose_and_packed++;
}
else if (is_loose)
@@ -793,6 +800,13 @@ ostree_builtin_repack (int argc, char **argv, GFile *repo_path, GError **error)
if (!ostree_repo_check (repo, error))
goto out;
+ if (ostree_repo_get_mode (repo) != OSTREE_REPO_MODE_ARCHIVE)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "Can't repack bare repositories yet");
+ goto out;
+ }
+
data.repo = repo;
data.error = error;
diff --git a/tests/t0000-basic.sh b/tests/t0000-basic.sh
index df27bfc..2d55e20 100755
--- a/tests/t0000-basic.sh
+++ b/tests/t0000-basic.sh
@@ -19,7 +19,7 @@
set -e
-echo "1..31"
+echo "1..28"
. libtest.sh
@@ -206,14 +206,3 @@ cmp union-files-count{,.new}
cd checkout-test2-union
assert_file_has_content ./yet/another/tree/green "leaf"
echo "ok checkout union 1"
-
-cd ${test_tmpdir}
-$OSTREE repack
-echo "ok repack"
-
-cd ${test_tmpdir}
-$OSTREE repack
-echo "ok repack again"
-
-$OSTREE checkout test2 checkout-test2-from-packed
-echo "ok checkout union 1"
diff --git a/tests/t0001-archive.sh b/tests/t0001-archive.sh
index 6bdc9aa..b07b988 100755
--- a/tests/t0001-archive.sh
+++ b/tests/t0001-archive.sh
@@ -21,7 +21,7 @@ set -e
. libtest.sh
-echo '1..10'
+echo '1..13'
setup_test_repository "archive"
echo "ok setup"
@@ -67,3 +67,14 @@ cd ${test_tmpdir}
$OSTREE cat test2 /baz/cow > cow-contents
assert_file_has_content cow-contents "moo"
echo "ok cat-file"
+
+cd ${test_tmpdir}
+$OSTREE repack
+echo "ok repack"
+
+cd ${test_tmpdir}
+$OSTREE repack
+echo "ok repack again"
+
+$OSTREE checkout test2 checkout-test2-from-packed
+echo "ok checkout union 1"
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]