[ostree] core: Add --skip-if-unchanged option for commit



commit dab4611263e5cd2dbf8fd1ecbde88e8ac5e68ac6
Author: Colin Walters <walters verbum org>
Date:   Thu Dec 22 18:47:30 2011 -0500

    core: Add --skip-if-unchanged option for commit
    
    There's not much point for OS builds to have "empty" commits.

 src/libostree/ostree-repo.c    |   33 ++++++++++++++++++++++++
 src/libostree/ostree-repo.h    |    4 +++
 src/ostree/ot-builtin-commit.c |   55 +++++++++++++++++++++++++++++++++------
 tests/t0000-basic.sh           |    8 +++++-
 4 files changed, 90 insertions(+), 10 deletions(-)
---
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index 220994d..9c295aa 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -1044,6 +1044,39 @@ ostree_repo_commit_transaction (OstreeRepo     *self,
   return ret;
 }
 
+gboolean
+ostree_repo_abort_transaction (OstreeRepo     *self,
+                               GCancellable   *cancellable,
+                               GError        **error)
+{
+  gboolean ret = FALSE;
+  OstreeRepoPrivate *priv = GET_PRIVATE (self);
+  GFile *f = NULL;
+  GHashTableIter iter;
+  gpointer key, value;
+
+  g_return_val_if_fail (priv->in_transaction == TRUE, FALSE);
+
+  priv->in_transaction = FALSE;
+
+  g_hash_table_iter_init (&iter, priv->pending_transaction_tmpfiles);
+  while (g_hash_table_iter_next (&iter, &key, &value))
+    {
+      const char *filename = value;
+
+      g_clear_object (&f);
+      f = g_file_get_child (priv->tmp_dir, filename);
+      
+      (void) unlink (ot_gfile_get_path_cached (f));
+    }
+
+  ret = TRUE;
+ out:
+  g_hash_table_remove_all (priv->pending_transaction_tmpfiles);
+  g_clear_object (&f);
+  return ret;
+}
+
 static gboolean
 stage_gvariant_object (OstreeRepo         *self,
                        OstreeObjectType    type,
diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h
index 272d159..08ebd58 100644
--- a/src/libostree/ostree-repo.h
+++ b/src/libostree/ostree-repo.h
@@ -88,6 +88,10 @@ gboolean      ostree_repo_commit_transaction (OstreeRepo     *self,
                                               GCancellable   *cancellable,
                                               GError        **error);
 
+gboolean      ostree_repo_abort_transaction (OstreeRepo     *self,
+                                             GCancellable   *cancellable,
+                                             GError        **error);
+
 gboolean      ostree_repo_has_object (OstreeRepo           *self,
                                       OstreeObjectType      objtype,
                                       const char           *checksum,
diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c
index d97c27d..5fcc037 100644
--- a/src/ostree/ot-builtin-commit.c
+++ b/src/ostree/ot-builtin-commit.c
@@ -35,6 +35,7 @@ static char *subject;
 static char *body;
 static char *parent;
 static char *branch;
+static gboolean skip_if_unchanged;
 static char **trees;
 static gint owner_uid = -1;
 static gint owner_gid = -1;
@@ -49,6 +50,7 @@ static GOptionEntry options[] = {
   { "tree", 0, 0, G_OPTION_ARG_STRING_ARRAY, &trees, "Overlay the given argument as a tree", "NAME" },
   { "owner-uid", 0, 0, G_OPTION_ARG_INT, &owner_uid, "Set file ownership user id", "UID" },
   { "owner-gid", 0, 0, G_OPTION_ARG_INT, &owner_gid, "Set file ownership group id", "GID" },
+  { "skip-if-unchanged", 0, 0, G_OPTION_ARG_NONE, &skip_if_unchanged, "If the contents are unchanged from previous commit, do nothing", NULL },
   { NULL }
 };
 
@@ -61,6 +63,7 @@ ostree_builtin_commit (int argc, char **argv, GFile *repo_path, GError **error)
   GFile *arg = NULL;
   char *parent = NULL;
   char *commit_checksum = NULL;
+  GVariant *parent_commit = NULL;
   GVariant *metadata = NULL;
   GMappedFile *metadata_mappedf = NULL;
   GFile *metadata_f = NULL;
@@ -69,6 +72,7 @@ ostree_builtin_commit (int argc, char **argv, GFile *repo_path, GError **error)
   GCancellable *cancellable = NULL;
   OstreeMutableTree *mtree = NULL;
   char *tree_type = NULL;
+  gboolean skip_commit = FALSE;
 
   context = g_option_context_new ("[ARG] - Commit a new revision");
   g_option_context_add_main_entries (context, options, NULL);
@@ -128,6 +132,13 @@ ostree_builtin_commit (int argc, char **argv, GFile *repo_path, GError **error)
   if (!ostree_repo_resolve_rev (repo, branch, TRUE, &parent, error))
     goto out;
 
+  if (skip_if_unchanged && parent)
+    {
+      if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT,
+                                     parent, &parent_commit, error))
+        goto out;
+    }
+
   if (!ostree_repo_prepare_transaction (repo, cancellable, error))
     goto out;
 
@@ -200,24 +211,50 @@ ostree_builtin_commit (int argc, char **argv, GFile *repo_path, GError **error)
   if (!ostree_repo_stage_mtree (repo, mtree, &contents_checksum, cancellable, error))
     goto out;
 
-  if (!ostree_repo_stage_commit (repo, branch, parent, subject, body, metadata,
-                                 contents_checksum, ostree_mutable_tree_get_metadata_checksum (mtree),
-                                 &commit_checksum, cancellable, error))
-    goto out;
+  if (skip_if_unchanged && parent_commit)
+    {
+      const char *parent_contents_checksum;
+      const char *parent_metadata_checksum;
 
-  if (!ostree_repo_commit_transaction (repo, cancellable, error))
-    goto out;
+      g_variant_get_child (parent_commit, 6, "&s", &parent_contents_checksum);
+      g_variant_get_child (parent_commit, 7, "&s", &parent_metadata_checksum);
 
-  if (!ostree_repo_write_ref (repo, NULL, branch, commit_checksum, error))
-    goto out;
+      if (strcmp (contents_checksum, parent_contents_checksum) == 0
+          && strcmp (ostree_mutable_tree_get_metadata_checksum (mtree),
+                     parent_metadata_checksum) == 0)
+        skip_commit = TRUE;
+    }
+
+  if (!skip_commit)
+    {
+      if (!ostree_repo_stage_commit (repo, branch, parent, subject, body, metadata,
+                                     contents_checksum, ostree_mutable_tree_get_metadata_checksum (mtree),
+                                     &commit_checksum, cancellable, error))
+        goto out;
+
+      if (!ostree_repo_commit_transaction (repo, cancellable, error))
+        goto out;
+      
+      if (!ostree_repo_write_ref (repo, NULL, branch, commit_checksum, error))
+        goto out;
+
+      g_print ("%s\n", commit_checksum);
+    }
+  else
+    {
+      if (!ostree_repo_abort_transaction (repo, cancellable, error))
+        goto out;
+
+      g_print ("%s\n", parent);
+    }
 
   ret = TRUE;
-  g_print ("%s\n", commit_checksum);
  out:
   g_clear_object (&arg);
   g_clear_object (&mtree);
   g_free (contents_checksum);
   g_free (parent);
+  ot_clear_gvariant(&parent_commit);
   g_free (tree_type);
   if (metadata_mappedf)
     g_mapped_file_unref (metadata_mappedf);
diff --git a/tests/t0000-basic.sh b/tests/t0000-basic.sh
index 62e15b1..9176d8f 100755
--- a/tests/t0000-basic.sh
+++ b/tests/t0000-basic.sh
@@ -19,7 +19,7 @@
 
 set -e
 
-echo "1..20"
+echo "1..21"
 
 . libtest.sh
 
@@ -158,3 +158,9 @@ echo "ok commit from ref"
 $OSTREE commit -b trees/test2 -s 'ref with / in it' --tree=ref=test2
 echo "ok commit ref with /"
 
+old_rev=$($OSTREE rev-parse test2)
+$OSTREE commit --skip-if-unchanged -b test2 -s 'should not be committed' --tree=ref=test2
+new_rev=$($OSTREE rev-parse test2)
+assert_streq "${old_rev}" "${new_rev}"
+echo "ok commit --skip-if-unchanged"
+



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