cli/rev-parse: Add `--single` option
authorColin Walters <walters@verbum.org>
Tue, 16 Aug 2022 21:27:46 +0000 (17:27 -0400)
committerColin Walters <walters@verbum.org>
Thu, 18 Aug 2022 15:08:17 +0000 (11:08 -0400)
In the current "ostree native container" flow, we're inserting
a commit object into the repo but with no refs.

We have hacks in a few places to find the commit digest via e.g.
`find repo/objects -name *.commit` but that's a horrible hack.
Add `ostree rev-parse --single` which will print the single commit,
and error out if there is not exactly one commit.

Co-authored-by: Jonathan Lebon <jonathan@jlebon.com>
man/ostree-rev-parse.xml
src/ostree/ot-builtin-rev-parse.c
tests/basic-test.sh

index 74c585fd83336a8b5835ba4d32278de48ba20134..f39868a6d37fb3497f4c3756850a09492d26f7c3 100644 (file)
@@ -54,6 +54,19 @@ License along with this library. If not, see <https://www.gnu.org/licenses/>.
     </refsynopsisdiv>
 
 
+    <refsect1>
+        <title>Options</title>
+        <variablelist>
+            <varlistentry>
+                <term><option>--single</option>, <option>-S</option></term>
+
+                <listitem><para>
+                    If the repository has exactly one commit, then print it; any other case will result in an error.
+                </para></listitem>
+            </varlistentry>
+        </variablelist>
+    </refsect1>
+
 <!-- Is this accurate for all cases?  This is what I observed -->
     <refsect1>
         <title>Description</title>
index 521d2159ecbbc8e9127a849e7621fd58c89a07ec..95cb45aba56d6ec22d78fe04f3687a70484fb55b 100644 (file)
 #include "ot-builtins.h"
 #include "ostree.h"
 #include "otutil.h"
+#include <stdbool.h>
 
 /* ATTENTION:
  * Please remember to update the bash-completion script (bash/ostree) and
  * man page (man/ostree-rev-parse.xml) when changing the option list.
  */
 
+static gboolean opt_single;
+
 static GOptionEntry options[] = {
+  { "single", 'S', 0, G_OPTION_ARG_NONE, &opt_single, "If the repository has exactly one commit, then print it; any other case will result in an error", NULL },
   { NULL }
 };
 
@@ -43,11 +47,43 @@ ostree_builtin_rev_parse (int argc, char **argv, OstreeCommandInvocation *invoca
   if (!ostree_option_context_parse (context, options, &argc, &argv, invocation, &repo, cancellable, error))
     return FALSE;
 
+  if (opt_single)
+    {
+      if (argc >= 2)
+        {
+          ot_util_usage_error (context, "Cannot specify arguments with --single", error);
+          return FALSE;
+        }
+
+      g_autoptr(GHashTable) objects = NULL;
+      if (!ostree_repo_list_commit_objects_starting_with (repo, "", &objects, cancellable, error))
+        return FALSE;
+
+      GVariant *found = NULL;
+      GLNX_HASH_TABLE_FOREACH (objects, GVariant*, key)
+        {
+          if (found)
+            return glnx_throw (error, "Multiple commit objects found");
+          found = key;
+        }
+      if (!found)
+        return glnx_throw (error, "No commit objects found");
+      const char *checksum;
+      OstreeObjectType objtype;
+      ostree_object_name_deserialize (found, &checksum, &objtype);
+      g_assert (objtype == OSTREE_OBJECT_TYPE_COMMIT);
+
+      g_print ("%s\n", checksum);
+
+      return TRUE; /* Note early return */
+    }
+
   if (argc < 2)
     {
       ot_util_usage_error (context, "REV must be specified", error);
       return FALSE;
     }
+
   for (gint i = 1; i < argc; i++)
     {
       const char *rev = argv[i];
index 04506c3d1f60ab23e17d329122d3c22c78ea279e..67d57ddac24ef888d98f6a210ae1319f5d621cf3 100644 (file)
@@ -19,7 +19,7 @@
 
 set -euo pipefail
 
-echo "1..$((87 + ${extra_basic_tests:-0}))"
+echo "1..$((88 + ${extra_basic_tests:-0}))"
 
 CHECKOUT_U_ARG=""
 CHECKOUT_H_ARGS="-H"
@@ -97,6 +97,22 @@ $OSTREE rev-parse 'test2^'
 $OSTREE rev-parse 'test2^^' 2>/dev/null && fatal "rev-parse test2^^ unexpectedly succeeded!"
 echo "ok rev-parse"
 
+if $OSTREE rev-parse -S 2>err.txt; then
+    fatal "rev parse multiple"
+fi
+assert_file_has_content_literal err.txt 'Multiple commit objects found'
+$CMD_PREFIX ostree --repo=repo-copy init --mode=archive
+if $CMD_PREFIX ostree --repo=repo-copy rev-parse -S 2>err.txt; then
+    fatal "rev parse none"
+fi
+assert_file_has_content_literal err.txt 'No commit objects found'
+rev=$($OSTREE rev-parse test2)
+$CMD_PREFIX ostree --repo=repo-copy pull-local repo test2
+rev2=$($CMD_PREFIX ostree --repo=repo-copy rev-parse -S)
+assert_streq "${rev}" "${rev2}"
+echo "ok rev-parse -S"
+
+
 checksum=$($OSTREE rev-parse test2)
 partial=${checksum:0:6} 
 echo "partial:" $partial