From eb7c3d01a30b3e6f7a2ba9bae30a796480bed891 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 5 Mar 2012 11:32:48 -0500 Subject: [PATCH] core: Add 'cat' builtin --- Makefile-ostree.am | 1 + src/libostree/ostree-repo-file.c | 18 ++--- src/ostree/main.c | 1 + src/ostree/ot-builtin-cat.c | 114 +++++++++++++++++++++++++++++++ src/ostree/ot-builtins.h | 1 + tests/t0000-basic.sh | 7 +- tests/t0001-archive.sh | 7 +- 7 files changed, 139 insertions(+), 10 deletions(-) create mode 100644 src/ostree/ot-builtin-cat.c diff --git a/Makefile-ostree.am b/Makefile-ostree.am index 91aceb77..83333ebb 100644 --- a/Makefile-ostree.am +++ b/Makefile-ostree.am @@ -21,6 +21,7 @@ bin_PROGRAMS += ostree ostree_SOURCES = src/ostree/main.c \ src/ostree/ot-builtins.h \ + src/ostree/ot-builtin-cat.c \ src/ostree/ot-builtin-checkout.c \ src/ostree/ot-builtin-checksum.c \ src/ostree/ot-builtin-commit.c \ diff --git a/src/libostree/ostree-repo-file.c b/src/libostree/ostree-repo-file.c index dd22d380..625067dd 100644 --- a/src/libostree/ostree-repo-file.c +++ b/src/libostree/ostree-repo-file.c @@ -989,6 +989,7 @@ ostree_repo_file_read (GFile *file, GFile *local_file = NULL; GFileInputStream *ret_stream = NULL; OstreeRepoFile *self = OSTREE_REPO_FILE (file); + const char *checksum; if (self->tree_contents) { @@ -998,20 +999,21 @@ ostree_repo_file_read (GFile *file, goto out; } + checksum = ostree_repo_file_get_checksum (self); + if (ostree_repo_get_mode (self->repo) == OSTREE_REPO_MODE_ARCHIVE) { - g_set_error_literal (error, G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - "Can't open archived file (yet)"); - goto out; + local_file = ostree_repo_get_object_path (self->repo, checksum, + OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT); } else { - local_file = ostree_repo_file_nontree_get_local (self); - ret_stream = g_file_read (local_file, cancellable, error); - if (!ret_stream) - goto out; + local_file = ostree_repo_get_file_object_path (self->repo, checksum); } + + ret_stream = g_file_read (local_file, cancellable, error); + if (!ret_stream) + goto out; ret = TRUE; out: diff --git a/src/ostree/main.c b/src/ostree/main.c index d2e3eba3..71a2efc8 100644 --- a/src/ostree/main.c +++ b/src/ostree/main.c @@ -30,6 +30,7 @@ #include "ot-builtins.h" static OstreeBuiltin builtins[] = { + { "cat", ostree_builtin_cat, 0 }, { "checkout", ostree_builtin_checkout, 0 }, { "checksum", ostree_builtin_checksum, OSTREE_BUILTIN_FLAG_NO_REPO }, { "diff", ostree_builtin_diff, 0 }, diff --git a/src/ostree/ot-builtin-cat.c b/src/ostree/ot-builtin-cat.c new file mode 100644 index 00000000..0096f3a6 --- /dev/null +++ b/src/ostree/ot-builtin-cat.c @@ -0,0 +1,114 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2011 Colin Walters + * + * 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 + */ + +#include "config.h" + +#include "ot-builtins.h" +#include "ostree.h" +#include "ostree-repo-file.h" + +#include +#include + +static GOptionEntry options[] = { +}; + +static gboolean +cat_one_file (GFile *f, + GOutputStream *stdout_stream, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = FALSE; + GInputStream *in = NULL; + + if (!ostree_repo_file_ensure_resolved ((OstreeRepoFile*)f, NULL)) + g_assert_not_reached (); + + in = (GInputStream*)g_file_read (f, cancellable, error); + if (!in) + goto out; + + if (!g_output_stream_splice (stdout_stream, in, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE, + cancellable, error)) + goto out; + + ret = TRUE; + out: + g_clear_object (&in); + return ret; +} + +gboolean +ostree_builtin_cat (int argc, char **argv, GFile *repo_path, GError **error) +{ + GOptionContext *context; + gboolean ret = FALSE; + OstreeRepo *repo = NULL; + int i; + GCancellable *cancellable = NULL; + const char *rev; + GOutputStream *stdout_stream = NULL; + GFile *root = NULL; + GFile *f = NULL; + + context = g_option_context_new ("COMMIT PATH [PATH...] - Concatenate contents of files"); + g_option_context_add_main_entries (context, options, NULL); + + if (!g_option_context_parse (context, &argc, &argv, error)) + goto out; + + repo = ostree_repo_new (repo_path); + if (!ostree_repo_check (repo, error)) + goto out; + + if (argc <= 2) + { + ot_util_usage_error (context, "An COMMIT and at least one PATH argument are required", error); + goto out; + } + rev = argv[1]; + + if (!ostree_repo_read_commit (repo, rev, &root, NULL, error)) + goto out; + + stdout_stream = g_unix_output_stream_new (1, FALSE); + + for (i = 2; i < argc; i++) + { + g_clear_object (&f); + f = g_file_resolve_relative_path (root, argv[i]); + + if (!cat_one_file (f, stdout_stream, cancellable, error)) + goto out; + } + + ret = TRUE; + out: + g_clear_object (&root); + g_clear_object (&f); + g_clear_object (&stdout_stream); + if (context) + g_option_context_free (context); + g_clear_object (&repo); + return ret; +} diff --git a/src/ostree/ot-builtins.h b/src/ostree/ot-builtins.h index f35b7e27..befd2037 100644 --- a/src/ostree/ot-builtins.h +++ b/src/ostree/ot-builtins.h @@ -27,6 +27,7 @@ G_BEGIN_DECLS +gboolean ostree_builtin_cat (int argc, char **argv, GFile *repo_path, GError **error); gboolean ostree_builtin_checkout (int argc, char **argv, GFile *repo_path, GError **error); gboolean ostree_builtin_checksum (int argc, char **argv, GFile *repo_path, GError **error); gboolean ostree_builtin_commit (int argc, char **argv, GFile *repo_path, GError **error); diff --git a/tests/t0000-basic.sh b/tests/t0000-basic.sh index c3cd7a51..bffed6fd 100755 --- a/tests/t0000-basic.sh +++ b/tests/t0000-basic.sh @@ -19,7 +19,7 @@ set -e -echo "1..25" +echo "1..26" . libtest.sh @@ -185,3 +185,8 @@ echo "ok commit statoverridde" cd ${test_tmpdir} $OSTREE prune echo "ok prune didn't fail" + +cd ${test_tmpdir} +$OSTREE cat test2 /yet/another/tree/green > greenfile-contents +assert_file_has_content greenfile-contents "leaf" +echo "ok cat-file" diff --git a/tests/t0001-archive.sh b/tests/t0001-archive.sh index 7849c1d5..6bdc9aa5 100755 --- a/tests/t0001-archive.sh +++ b/tests/t0001-archive.sh @@ -21,7 +21,7 @@ set -e . libtest.sh -echo '1..9' +echo '1..10' setup_test_repository "archive" echo "ok setup" @@ -62,3 +62,8 @@ echo "ok uid0 ls" $OSTREE checkout -U test2-uid0 checkout-user-test2-uid0 echo "ok user checkout from uid 0" + +cd ${test_tmpdir} +$OSTREE cat test2 /baz/cow > cow-contents +assert_file_has_content cow-contents "moo" +echo "ok cat-file"