[ostree] core: [INCOMPATIBLE CHANGE] Re-split archive content into .file and .filecontent



commit 27358a8de61ca785c52e8f439a21099cbbf80424
Author: Colin Walters <walters verbum org>
Date:   Fri May 4 11:02:15 2012 -0400

    core: [INCOMPATIBLE CHANGE] Re-split archive content into .file and .filecontent
    
    This will allow us to use hard links again for user-mode checkouts,
    rather than the hackish link cache.  It was pretty silly anyways to
    have file objects be stored with just a small metadata header
    prepended, but uncompressed.
    
    Either they should be hardlinkable, or compressed (in pack files).

 src/libostree/ostree-core.c  |   17 ++
 src/libostree/ostree-core.h  |    2 +
 src/libostree/ostree-repo.c  |  452 +++++++++++++++++++++++++++---------------
 src/libostree/ostree-repo.h  |    3 +
 src/ostree/ostree-pull.c     |   37 ++++-
 src/ostree/ot-builtin-init.c |    2 +-
 src/ostree/ot-builtin-pack.c |   18 ++-
 7 files changed, 364 insertions(+), 167 deletions(-)
---
diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c
index 77c31fe..20abeb6 100644
--- a/src/libostree/ostree-core.c
+++ b/src/libostree/ostree-core.c
@@ -922,6 +922,23 @@ ostree_get_relative_object_path (const char *checksum,
   return g_string_free (path, FALSE);
 }
 
+char *
+ostree_get_relative_archive_content_path (const char        *checksum)
+{
+  GString *path;
+
+  g_assert (strlen (checksum) == 64);
+
+  path = g_string_new ("objects/");
+
+  g_string_append_len (path, checksum, 2);
+  g_string_append_c (path, '/');
+  g_string_append (path, checksum + 2);
+  g_string_append (path, ".filecontent");
+
+  return g_string_free (path, FALSE);
+}
+
 static char *
 get_pack_name (gboolean        is_meta,
                gboolean        is_index,
diff --git a/src/libostree/ostree-core.h b/src/libostree/ostree-core.h
index a7b6a36..fd58ee3 100644
--- a/src/libostree/ostree-core.h
+++ b/src/libostree/ostree-core.h
@@ -169,6 +169,8 @@ void ostree_object_from_string (const char *str,
 char *ostree_get_relative_object_path (const char        *checksum,
                                        OstreeObjectType   type);
 
+char *ostree_get_relative_archive_content_path (const char        *checksum);
+
 char *ostree_get_pack_index_name (gboolean        is_meta,
                                   const char     *checksum);
 char *ostree_get_pack_data_name (gboolean        is_meta,
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index 011fde5..2e0b61a 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -692,7 +692,7 @@ ostree_repo_check (OstreeRepo *self, GError **error)
   if (!version)
     goto out;
 
-  if (strcmp (version, "0") != 0)
+  if (strcmp (version, "1") != 0)
     {
       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                    "Invalid repository version '%s'", version);
@@ -779,36 +779,66 @@ ostree_repo_get_file_object_path (OstreeRepo   *self,
   return ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_FILE);
 }
 
+GFile *
+ostree_repo_get_archive_content_path (OstreeRepo    *self,
+                                      const char    *checksum)
+{
+  OstreeRepoPrivate *priv = GET_PRIVATE (self);
+  ot_lfree char *path = NULL;
+
+  g_assert (ostree_repo_get_mode (self) == OSTREE_REPO_MODE_ARCHIVE);
+
+  path = ostree_get_relative_archive_content_path (checksum);
+  return g_file_resolve_relative_path (priv->repodir, path);
+}
+
 static gboolean
-commit_loose_object_trusted (OstreeRepo        *self,
-                             const char        *checksum,
-                             OstreeObjectType   objtype,
-                             GFile             *tempfile_path,
-                             GCancellable      *cancellable,
-                             GError           **error)
+commit_loose_object_impl (OstreeRepo        *self,
+                          GFile             *tempfile_path,
+                          GFile             *dest,
+                          GCancellable      *cancellable,
+                          GError           **error)
 {
   gboolean ret = FALSE;
-  ot_lobj GFile *dest_file = NULL;
-  ot_lobj GFile *checksum_dir = NULL;
-
-  dest_file = ostree_repo_get_object_path (self, checksum, objtype);
-  checksum_dir = g_file_get_parent (dest_file);
+  ot_lobj GFile *parent = NULL;
 
-  if (!ot_gfile_ensure_directory (checksum_dir, FALSE, error))
+  parent = g_file_get_parent (dest);
+  if (!ot_gfile_ensure_directory (parent, FALSE, error))
     goto out;
   
-  if (link (ot_gfile_get_path_cached (tempfile_path), ot_gfile_get_path_cached (dest_file)) < 0)
+  if (link (ot_gfile_get_path_cached (tempfile_path), ot_gfile_get_path_cached (dest)) < 0)
     {
       if (errno != EEXIST)
         {
           ot_util_set_error_from_errno (error, errno);
           g_prefix_error (error, "Storing file '%s': ",
-                          ot_gfile_get_path_cached (dest_file));
+                          ot_gfile_get_path_cached (dest));
           goto out;
         }
     }
 
   (void) unlink (ot_gfile_get_path_cached (tempfile_path));
+  ret = TRUE;
+ out:
+  return ret;
+}
+
+static gboolean
+commit_loose_object_trusted (OstreeRepo        *self,
+                             const char        *checksum,
+                             OstreeObjectType   objtype,
+                             GFile             *tempfile_path,
+                             GCancellable      *cancellable,
+                             GError           **error)
+{
+  gboolean ret = FALSE;
+  ot_lobj GFile *dest_file = NULL;
+
+  dest_file = ostree_repo_get_object_path (self, checksum, objtype);
+
+  if (!commit_loose_object_impl (self, tempfile_path, dest_file,
+                                 cancellable, error))
+    goto out;
 
   ret = TRUE;
  out:
@@ -821,19 +851,18 @@ typedef enum {
 } OstreeRepoStageFlags;
 
 static gboolean
-stage_object_impl (OstreeRepo         *self,
-                   OstreeRepoStageFlags flags,
-                   OstreeObjectType    objtype,
-                   GInputStream       *input,
-                   guint64             file_object_length,
-                   const char         *expected_checksum,
-                   guchar            **out_csum,
-                   GCancellable       *cancellable,
-                   GError            **error)
+stage_object_internal (OstreeRepo         *self,
+                       OstreeRepoStageFlags flags,
+                       OstreeObjectType    objtype,
+                       GInputStream       *input,
+                       guint64             file_object_length,
+                       const char         *expected_checksum,
+                       guchar            **out_csum,
+                       GCancellable       *cancellable,
+                       GError            **error)
 {
-  gboolean ret = FALSE;
+ gboolean ret = FALSE;
   OstreeRepoPrivate *priv = GET_PRIVATE (self);
-  guint64 pack_offset;
   const char *actual_checksum;
   gboolean do_commit;
   ot_lobj GFileInfo *temp_info = NULL;
@@ -843,156 +872,178 @@ stage_object_impl (OstreeRepo         *self,
   ot_lfree char *pack_checksum = NULL;
   ot_lfree guchar *ret_csum = NULL;
   ot_lobj OstreeChecksumInputStream *checksum_input = NULL;
-  ot_lvariant GVariant *file_header = NULL;
   GChecksum *checksum = NULL;
+  gboolean staged_raw_file = FALSE;
+  gboolean staged_archive_file = FALSE;
 
-  g_return_val_if_fail (priv->in_transaction, FALSE);
-  
-  if (g_cancellable_set_error_if_cancelled (cancellable, error))
-    return FALSE;
-
-  g_assert (expected_checksum || out_csum);
-
-  if (expected_checksum)
+  if (out_csum)
     {
-      if (!(flags & OSTREE_REPO_STAGE_FLAGS_STORE_IF_PACKED))
-        {
-          if (!repo_find_object (self, objtype, expected_checksum,
-                                 &stored_path, &pack_checksum, &pack_offset,
-                                 cancellable, error))
-            goto out;
-        }
-      else
-        {
-          if (!repo_find_object (self, objtype, expected_checksum,
-                                 &stored_path, NULL, NULL,
-                                 cancellable, error))
-            goto out;
-        }
+      checksum = g_checksum_new (G_CHECKSUM_SHA256);
+      if (input)
+        checksum_input = ostree_checksum_input_stream_new (input, checksum);
     }
 
-  if (stored_path == NULL && pack_checksum == NULL)
+  if (objtype == OSTREE_OBJECT_TYPE_FILE
+      && (flags & OSTREE_REPO_STAGE_FLAGS_LENGTH_VALID) > 0)
     {
-      ot_lvariant GVariant *file_header = NULL;
-      gboolean do_stage_bare_file;
+      ot_lobj GInputStream *file_input = NULL;
+      ot_lobj GFileInfo *file_info = NULL;
+      ot_lvariant GVariant *xattrs = NULL;
 
-      if (out_csum)
-        {
-          checksum = g_checksum_new (G_CHECKSUM_SHA256);
-          if (input)
-            checksum_input = ostree_checksum_input_stream_new (input, checksum);
-        }
+      if (!ostree_content_stream_parse (checksum_input ? (GInputStream*)checksum_input : input,
+                                        file_object_length, FALSE,
+                                        &file_input, &file_info, &xattrs,
+                                        cancellable, error))
+        goto out;
 
-      do_stage_bare_file = (flags & OSTREE_REPO_STAGE_FLAGS_LENGTH_VALID)
-        && objtype == OSTREE_OBJECT_TYPE_FILE
-        && priv->mode == OSTREE_REPO_MODE_BARE;
-      if (do_stage_bare_file)
+      if (ostree_repo_get_mode (self) == OSTREE_REPO_MODE_BARE)
         {
-          ot_lobj GInputStream *file_input = NULL;
-          ot_lobj GFileInfo *file_info = NULL;
-          ot_lvariant GVariant *xattrs = NULL;
-
-          if (!ostree_content_stream_parse (checksum_input ? (GInputStream*)checksum_input : input,
-                                            file_object_length, FALSE,
-                                            &file_input, &file_info, &xattrs,
-                                            cancellable, error))
-            goto out;
-
           if (!ostree_create_temp_file_from_input (priv->tmp_dir,
                                                    ostree_object_type_to_string (objtype), NULL,
                                                    file_info, xattrs, file_input,
                                                    &temp_file,
                                                    cancellable, error))
             goto out;
+          staged_raw_file = TRUE;
         }
       else
         {
+          ot_lvariant GVariant *file_meta = NULL;
+          ot_lobj GInputStream *file_meta_input = NULL;
+          ot_lobj GFileInfo *archive_content_file_info = NULL;
+
+          file_meta = ostree_file_header_new (file_info, xattrs);
+          file_meta_input = ot_variant_read (file_meta);
+
           if (!ostree_create_temp_file_from_input (priv->tmp_dir,
                                                    ostree_object_type_to_string (objtype), NULL,
-                                                   NULL, NULL,
-                                                   checksum_input ? (GInputStream*)checksum_input : input,
+                                                   NULL, NULL, file_meta_input,
                                                    &temp_file,
                                                    cancellable, error))
             goto out;
-        }
-          
-      if (!checksum)
-        actual_checksum = expected_checksum;
-      else
-        {
-          actual_checksum = g_checksum_get_string (checksum);
-          if (expected_checksum && strcmp (actual_checksum, expected_checksum) != 0)
+
+          if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
             {
-              g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                           "Corrupted %s object %s (actual checksum is %s)",
-                               ostree_object_type_to_string (objtype),
-                           expected_checksum, actual_checksum);
+              ot_lobj GOutputStream *content_out = NULL;
+              guint32 src_mode;
+              guint32 target_mode;
+
+              if (!ostree_create_temp_regular_file (priv->tmp_dir,
+                                                    ostree_object_type_to_string (objtype), NULL,
+                                                    &raw_temp_file, &content_out,
+                                                    cancellable, error))
+                goto out;
+
+              /* Don't make setuid files in the repository; all we want to preserve
+               * is file type and permissions.
+               */
+              src_mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode");
+              target_mode = src_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_IFMT);
+              
+              if (chmod (ot_gfile_get_path_cached (raw_temp_file), target_mode) < 0)
+                {
+                  ot_util_set_error_from_errno (error, errno);
                   goto out;
+                }
+
+              if (g_output_stream_splice (content_out, file_input,
+                                          G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
+                                          cancellable, error) < 0)
+                goto out;
+
+              staged_archive_file = TRUE;
             }
-          
         }
+    }
+  else
+    {
+      if (!ostree_create_temp_file_from_input (priv->tmp_dir,
+                                               ostree_object_type_to_string (objtype), NULL,
+                                               NULL, NULL,
+                                               checksum_input ? (GInputStream*)checksum_input : input,
+                                               &temp_file,
+                                               cancellable, error))
+        goto out;
+    }
           
-      if (!(flags & OSTREE_REPO_STAGE_FLAGS_STORE_IF_PACKED))
+  if (!checksum)
+    actual_checksum = expected_checksum;
+  else
+    {
+      actual_checksum = g_checksum_get_string (checksum);
+      if (expected_checksum && strcmp (actual_checksum, expected_checksum) != 0)
         {
-          gboolean have_obj;
+          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                       "Corrupted %s object %s (actual checksum is %s)",
+                       ostree_object_type_to_string (objtype),
+                       expected_checksum, actual_checksum);
+          goto out;
+        }
+    }
           
-          if (!ostree_repo_has_object (self, objtype, actual_checksum, &have_obj,
-                                       cancellable, error))
-            goto out;
+  if (!(flags & OSTREE_REPO_STAGE_FLAGS_STORE_IF_PACKED))
+    {
+      gboolean have_obj;
           
-          do_commit = !have_obj;
-        }
-      else
-        do_commit = TRUE;
+      if (!ostree_repo_has_object (self, objtype, actual_checksum, &have_obj,
+                                   cancellable, error))
+        goto out;
+          
+      do_commit = !have_obj;
+    }
+  else
+    do_commit = TRUE;
 
-      if (do_commit)
+  if (do_commit)
+    {
+      /* Only do this if we *didn't* stage a bare file above */
+      if (!staged_raw_file
+          && objtype == OSTREE_OBJECT_TYPE_FILE && priv->mode == OSTREE_REPO_MODE_BARE)
         {
-          /* Only do this if we *didn't* stage a bare file above */
-          if (!do_stage_bare_file
-              && objtype == OSTREE_OBJECT_TYPE_FILE && priv->mode == OSTREE_REPO_MODE_BARE)
-            {
-              ot_lobj GInputStream *file_input = NULL;
-              ot_lobj GFileInfo *file_info = NULL;
-              ot_lvariant GVariant *xattrs = NULL;
+          ot_lobj GInputStream *file_input = NULL;
+          ot_lobj GFileInfo *file_info = NULL;
+          ot_lvariant GVariant *xattrs = NULL;
               
-              /* TODO - for commits to raw repositories, if we were
-               * passed the total content length, we could avoid
-               * writing everything to a temporary file, then parsing
-               * it.
-               */
-              if (!ostree_content_file_parse (temp_file, FALSE, &file_input,
-                                              &file_info, &xattrs,
-                                              cancellable, error))
-                goto out;
+          if (!ostree_content_file_parse (temp_file, FALSE, &file_input,
+                                          &file_info, &xattrs,
+                                          cancellable, error))
+            goto out;
               
-              if (!ostree_create_temp_file_from_input (priv->tmp_dir,
-                                                       ostree_object_type_to_string (objtype), NULL,
-                                                       file_info, xattrs, file_input,
-                                                       &raw_temp_file,
-                                                       cancellable, error))
-                goto out;
+          if (!ostree_create_temp_file_from_input (priv->tmp_dir,
+                                                   ostree_object_type_to_string (objtype), NULL,
+                                                   file_info, xattrs, file_input,
+                                                   &raw_temp_file,
+                                                   cancellable, error))
+            goto out;
 
-              if (!commit_loose_object_trusted (self, actual_checksum, objtype, 
-                                                raw_temp_file, cancellable, error))
-                goto out;
-            }
-          else
+          if (!commit_loose_object_trusted (self, actual_checksum, objtype, 
+                                            raw_temp_file, cancellable, error))
+            goto out;
+          g_clear_object (&raw_temp_file);
+        }
+      else
+        {
+          /* Commit content first so the process is atomic */
+          if (staged_archive_file)
             {
-              if (!commit_loose_object_trusted (self, actual_checksum, objtype, 
-                                                temp_file, cancellable, error))
+              ot_lobj GFile *archive_content_dest = NULL;
+
+              archive_content_dest = ostree_repo_get_archive_content_path (self, actual_checksum);
+                                                                   
+              if (!commit_loose_object_impl (self, raw_temp_file, archive_content_dest,
+                                             cancellable, error))
                 goto out;
+              g_clear_object (&raw_temp_file);
             }
+          if (!commit_loose_object_trusted (self, actual_checksum, objtype, 
+                                            temp_file, cancellable, error))
+            goto out;
           g_clear_object (&temp_file);
         }
-      
-      if (checksum)
-        ret_csum = ot_csum_from_gchecksum (checksum);
-    }
-  else
-    {
-      g_assert (stored_path != NULL || pack_checksum != NULL);
-      /* Nothing to do */
     }
+      
+  if (checksum)
+    ret_csum = ot_csum_from_gchecksum (checksum);
 
   ret = TRUE;
   ot_transfer_out_value(out_csum, &ret_csum);
@@ -1005,6 +1056,64 @@ stage_object_impl (OstreeRepo         *self,
   return ret;
 }
 
+static gboolean
+stage_object (OstreeRepo         *self,
+              OstreeRepoStageFlags flags,
+              OstreeObjectType    objtype,
+              GInputStream       *input,
+              guint64             file_object_length,
+              const char         *expected_checksum,
+              guchar            **out_csum,
+              GCancellable       *cancellable,
+              GError            **error)
+{
+  gboolean ret = FALSE;
+  OstreeRepoPrivate *priv = GET_PRIVATE (self);
+  guint64 pack_offset;
+  ot_lobj GFile *stored_path = NULL;
+  ot_lfree char *pack_checksum = NULL;
+  ot_lfree guchar *ret_csum = NULL;
+
+  g_return_val_if_fail (priv->in_transaction, FALSE);
+  
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    return FALSE;
+
+  g_assert (expected_checksum || out_csum);
+
+  if (expected_checksum)
+    {
+      if (!(flags & OSTREE_REPO_STAGE_FLAGS_STORE_IF_PACKED))
+        {
+          if (!repo_find_object (self, objtype, expected_checksum,
+                                 &stored_path, &pack_checksum, &pack_offset,
+                                 cancellable, error))
+            goto out;
+        }
+      else
+        {
+          if (!repo_find_object (self, objtype, expected_checksum,
+                                 &stored_path, NULL, NULL,
+                                 cancellable, error))
+            goto out;
+        }
+    }
+
+  if (stored_path == NULL && pack_checksum == NULL)
+    {
+      if (!stage_object_internal (self, flags, objtype, input,
+                                  file_object_length, expected_checksum,
+                                  out_csum ? &ret_csum : NULL,
+                                  cancellable, error))
+        goto out;
+    }
+
+  ret = TRUE;
+  ot_transfer_out_value(out_csum, &ret_csum);
+ out:
+  return ret;
+}
+
 gboolean
 ostree_repo_prepare_transaction (OstreeRepo     *self,
                                  GCancellable   *cancellable,
@@ -1066,8 +1175,8 @@ stage_metadata_object (OstreeRepo         *self,
 
   input = ot_variant_read (variant);
   
-  if (!stage_object_impl (self, 0, type, input, 0, NULL,
-                          out_csum, cancellable, error))
+  if (!stage_object (self, 0, type, input, 0, NULL,
+                     out_csum, cancellable, error))
     goto out;
 
   ret = TRUE;
@@ -1128,9 +1237,9 @@ ostree_repo_stage_object_trusted (OstreeRepo   *self,
   int flags = 0;
   if (store_if_packed)
     flags |= OSTREE_REPO_STAGE_FLAGS_STORE_IF_PACKED;
-  return stage_object_impl (self, flags, objtype,
-                            object_input, 0, checksum, NULL,
-                            cancellable, error);
+  return stage_object (self, flags, objtype,
+                       object_input, 0, checksum, NULL,
+                       cancellable, error);
 }
 
 gboolean
@@ -1144,9 +1253,9 @@ ostree_repo_stage_object (OstreeRepo       *self,
   gboolean ret = FALSE;
   ot_lfree guchar *actual_csum = NULL;
   
-  if (!stage_object_impl (self, 0, objtype, 
-                          object_input, 0, expected_checksum, &actual_csum,
-                          cancellable, error))
+  if (!stage_object (self, 0, objtype, 
+                     object_input, 0, expected_checksum, &actual_csum,
+                     cancellable, error))
     goto out;
 
   ret = TRUE;
@@ -1166,9 +1275,9 @@ ostree_repo_stage_file_object_trusted (OstreeRepo       *self,
   int flags = OSTREE_REPO_STAGE_FLAGS_LENGTH_VALID;
   if (store_if_packed)
     flags |= OSTREE_REPO_STAGE_FLAGS_STORE_IF_PACKED;
-  return stage_object_impl (self, flags, OSTREE_OBJECT_TYPE_FILE,
-                            object_input, length, checksum, NULL,
-                            cancellable, error);
+  return stage_object (self, flags, OSTREE_OBJECT_TYPE_FILE,
+                       object_input, length, checksum, NULL,
+                       cancellable, error);
 }
 
 gboolean
@@ -1183,9 +1292,9 @@ ostree_repo_stage_file_object (OstreeRepo       *self,
   int flags = OSTREE_REPO_STAGE_FLAGS_LENGTH_VALID;
   ot_lfree guchar *actual_csum = NULL;
   
-  if (!stage_object_impl (self, flags, OSTREE_OBJECT_TYPE_FILE, 
-                          object_input, length, expected_checksum, &actual_csum,
-                          cancellable, error))
+  if (!stage_object (self, flags, OSTREE_OBJECT_TYPE_FILE, 
+                     object_input, length, expected_checksum, &actual_csum,
+                     cancellable, error))
     goto out;
 
   ret = TRUE;
@@ -2504,9 +2613,9 @@ stage_directory_to_mtree_internal (OstreeRepo           *self,
                                                           &file_object_input, &file_obj_length,
                                                           cancellable, error))
                     goto out;
-                  if (!stage_object_impl (self, OSTREE_REPO_STAGE_FLAGS_LENGTH_VALID,
-                                          OSTREE_OBJECT_TYPE_FILE, file_object_input, file_obj_length,
-                                          NULL, &child_file_csum, cancellable, error))
+                  if (!stage_object (self, OSTREE_REPO_STAGE_FLAGS_LENGTH_VALID,
+                                     OSTREE_OBJECT_TYPE_FILE, file_object_input, file_obj_length,
+                                     NULL, &child_file_csum, cancellable, error))
                     goto out;
 
                   g_free (tmp_checksum);
@@ -2697,9 +2806,9 @@ import_libarchive_entry_file (OstreeRepo           *self,
                                           &file_object_input, &length, cancellable, error))
     goto out;
   
-  if (!stage_object_impl (self, OSTREE_REPO_STAGE_FLAGS_LENGTH_VALID, OSTREE_OBJECT_TYPE_FILE,
-                          file_object_input, length, NULL, out_csum,
-                          cancellable, error))
+  if (!stage_object (self, OSTREE_REPO_STAGE_FLAGS_LENGTH_VALID, OSTREE_OBJECT_TYPE_FILE,
+                     file_object_input, length, NULL, out_csum,
+                     cancellable, error))
     goto out;
 
   ret = TRUE;
@@ -3195,9 +3304,7 @@ ostree_repo_load_file (OstreeRepo         *self,
   guint64 pack_len;
   guint64 pack_offset;
   ot_lvariant GVariant *packed_object = NULL;
-  ot_lvariant GVariant *archive_meta = NULL;
   ot_lvariant GVariant *file_data = NULL;
-  ot_lvariant GVariant *file_header = NULL;
   ot_lobj GFile *loose_path = NULL;
   ot_lobj GFileInfo *content_loose_info = NULL;
   ot_lfree char *pack_checksum = NULL;
@@ -3215,11 +3322,36 @@ ostree_repo_load_file (OstreeRepo         *self,
     {
       if (ostree_repo_get_mode (self) == OSTREE_REPO_MODE_ARCHIVE)
         {
-          if (!ostree_content_file_parse (loose_path, TRUE,
-                                          out_input ? &ret_input : NULL, 
-                                          &ret_file_info, &ret_xattrs,
-                                          cancellable, error))
+          ot_lvariant GVariant *archive_meta = NULL;
+
+          if (!ot_util_variant_map (loose_path, OSTREE_FILE_HEADER_GVARIANT_FORMAT,
+                                    &archive_meta, error))
+            goto out;
+
+          if (!ostree_file_header_parse (archive_meta, &ret_file_info, &ret_xattrs,
+                                         error))
             goto out;
+
+          if (g_file_info_get_file_type (ret_file_info) == G_FILE_TYPE_REGULAR)
+            {
+              ot_lobj GFile *archive_content_path = NULL;
+              ot_lobj GFileInfo *content_info = NULL;
+
+              archive_content_path = ostree_repo_get_archive_content_path (self, checksum);
+              content_info = g_file_query_info (archive_content_path, OSTREE_GIO_FAST_QUERYINFO,
+                                                G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+                                                cancellable, error);
+              if (!content_info)
+                goto out;
+
+              if (out_input)
+                {
+                  ret_input = (GInputStream*)g_file_read (archive_content_path, cancellable, error);
+                  if (!ret_input)
+                    goto out;
+                }
+              g_file_info_set_size (ret_file_info, g_file_info_get_size (content_info));
+            }
         }
       else
         {
diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h
index 1bff3e4..7f94c2f 100644
--- a/src/libostree/ostree-repo.h
+++ b/src/libostree/ostree-repo.h
@@ -77,6 +77,9 @@ GFile *       ostree_repo_get_object_path (OstreeRepo   *self,
                                            const char   *object,
                                            OstreeObjectType type);
 
+GFile *       ostree_repo_get_archive_content_path (OstreeRepo    *self,
+                                                    const char    *checksum);
+
 GFile *       ostree_repo_get_file_object_path (OstreeRepo   *self,
                                                 const char   *object);
 
diff --git a/src/ostree/ostree-pull.c b/src/ostree/ostree-pull.c
index 71b53f7..75c06bb 100644
--- a/src/ostree/ostree-pull.c
+++ b/src/ostree/ostree-pull.c
@@ -868,8 +868,10 @@ fetch_content (OtPullData           *pull_data,
   GHashTableIter hash_iter;
   gpointer key, value;
   ot_lobj GFile *temp_path = NULL;
+  ot_lobj GFile *content_temp_path = NULL;
   ot_lhash GHashTable *data_packs_to_fetch = NULL;
   ot_lhash GHashTable *loose_files = NULL;
+  SoupURI *content_uri = NULL;
   guint n_objects_to_fetch = 0;
 
   data_packs_to_fetch = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, 
@@ -953,14 +955,41 @@ fetch_content (OtPullData           *pull_data,
   while (g_hash_table_iter_next (&hash_iter, &key, &value))
     {
       const char *checksum = key;
+      guint64 length;
       ot_lobj GInputStream *file_object_input = NULL;
+      ot_lvariant GVariant *file_meta = NULL;
+      ot_lobj GFileInfo *file_info = NULL;
+      ot_lvariant GVariant *xattrs = NULL;
+      ot_lobj GInputStream *content_input = NULL;
 
       if (!fetch_loose_object (pull_data, checksum, OSTREE_OBJECT_TYPE_FILE, &temp_path,
                                cancellable, error))
         goto out;
 
-      file_object_input = (GInputStream*)g_file_read (temp_path, cancellable, error);
-      if (!file_object_input)
+      if (!ot_util_variant_map (temp_path, OSTREE_FILE_HEADER_GVARIANT_FORMAT, &file_meta,
+                                error))
+        goto out;
+
+      if (!ostree_file_header_parse (file_meta, &file_info, &xattrs, error))
+        goto out;
+
+      if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
+        {
+          ot_lfree char *content_path = ostree_get_relative_archive_content_path (checksum);
+          content_uri = suburi_new (pull_data->base_uri, content_path, NULL);
+
+          if (!fetch_uri (pull_data, content_uri, "filecontent", &content_temp_path,
+                          cancellable, error))
+            goto out;
+
+          content_input = (GInputStream*)g_file_read (content_temp_path, cancellable, error);
+          if (!content_input)
+            goto out;
+        }
+
+      if (!ostree_raw_file_to_content_stream (content_input, file_info, xattrs,
+                                              &file_object_input, &length,
+                                              cancellable, error))
         goto out;
 
       if (!ostree_repo_stage_object (pull_data->repo, OSTREE_OBJECT_TYPE_FILE, checksum,
@@ -971,8 +1000,12 @@ fetch_content (OtPullData           *pull_data,
 
   ret = TRUE;
  out:
+  if (content_uri)
+    soup_uri_free (content_uri);
   if (temp_path)
     (void) ot_gfile_unlink (temp_path, NULL, NULL);
+  if (content_temp_path)
+    (void) ot_gfile_unlink (content_temp_path, NULL, NULL);
   return ret;
 }
 
diff --git a/src/ostree/ot-builtin-init.c b/src/ostree/ot-builtin-init.c
index 73631b5..6c8c052 100644
--- a/src/ostree/ot-builtin-init.c
+++ b/src/ostree/ot-builtin-init.c
@@ -35,7 +35,7 @@ static GOptionEntry options[] = {
 };
 
 #define DEFAULT_CONFIG_CONTENTS ("[core]\n" \
-                                 "repo_version=0\n")
+                                 "repo_version=1\n")
 
 
 gboolean
diff --git a/src/ostree/ot-builtin-pack.c b/src/ostree/ot-builtin-pack.c
index 2a62dbf..7edee9e 100644
--- a/src/ostree/ot-builtin-pack.c
+++ b/src/ostree/ot-builtin-pack.c
@@ -192,7 +192,7 @@ delete_loose_object (OtRepackData     *data,
 {
   gboolean ret = FALSE;
   ot_lobj GFile *object_path = NULL;
-  ot_lobj GFile *content_object_path = NULL;
+  ot_lobj GFile *file_content_object_path = NULL;
   ot_lvariant GVariant *archive_meta = NULL;
   ot_lobj GFileInfo *file_info = NULL;
   ot_lvariant GVariant *xattrs = NULL;
@@ -206,6 +206,19 @@ delete_loose_object (OtRepackData     *data,
       goto out;
     }
 
+  if (objtype == OSTREE_OBJECT_TYPE_FILE
+      && ostree_repo_get_mode (data->repo) == OSTREE_REPO_MODE_ARCHIVE)
+    {
+      ot_lobj GFile *content_object_path = NULL;
+
+      content_object_path = ostree_repo_get_archive_content_path (data->repo, checksum);
+
+      /* Ignoring errors for now; later should only be trying to
+       * delete files with content.
+       */
+      (void) ot_gfile_unlink (object_path, NULL, NULL);
+    }
+
   ret = TRUE;
  out:
   return ret;
@@ -252,7 +265,6 @@ pack_one_data_object (OtRepackData        *data,
   gboolean ret = FALSE;
   guchar entry_flags = 0;
   GInputStream *read_object_in; /* nofree */
-  ot_lobj GFile *object_path = NULL;
   ot_lobj GInputStream *input = NULL;
   ot_lobj GFileInfo *file_info = NULL;
   ot_lvariant GVariant *xattrs = NULL;
@@ -275,8 +287,6 @@ pack_one_data_object (OtRepackData        *data,
       }
     }
 
-  object_path = ostree_repo_get_object_path (data->repo, checksum, objtype);
-
   if (!ostree_repo_load_file (data->repo, checksum, &input, &file_info, &xattrs,
                               cancellable, error))
     goto out;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]