Merge tag 'upstream/2016.12' into debian/master
Upstream version 2016.12
This commit is contained in:
commit
bc870baa58
|
|
@ -6122,6 +6122,7 @@ The following are currently defined:</p>
|
||||||
<li class="listitem"><p>refs (as): Array of string refs</p></li>
|
<li class="listitem"><p>refs (as): Array of string refs</p></li>
|
||||||
<li class="listitem"><p>flags (i): An instance of <a class="link" href="ostree-Content-addressed-object-store.html#OstreeRepoPullFlags" title="enum OstreeRepoPullFlags"><span class="type">OstreeRepoPullFlags</span></a></p></li>
|
<li class="listitem"><p>flags (i): An instance of <a class="link" href="ostree-Content-addressed-object-store.html#OstreeRepoPullFlags" title="enum OstreeRepoPullFlags"><span class="type">OstreeRepoPullFlags</span></a></p></li>
|
||||||
<li class="listitem"><p>subdir (s): Pull just this subdirectory</p></li>
|
<li class="listitem"><p>subdir (s): Pull just this subdirectory</p></li>
|
||||||
|
<li class="listitem"><p>subdirs (as): Pull just these subdirectories</p></li>
|
||||||
<li class="listitem"><p>override-remote-name (s): If local, add this remote to refspec</p></li>
|
<li class="listitem"><p>override-remote-name (s): If local, add this remote to refspec</p></li>
|
||||||
<li class="listitem"><p>gpg-verify (b): GPG verify commits</p></li>
|
<li class="listitem"><p>gpg-verify (b): GPG verify commits</p></li>
|
||||||
<li class="listitem"><p>gpg-verify-summary (b): GPG verify summary</p></li>
|
<li class="listitem"><p>gpg-verify-summary (b): GPG verify summary</p></li>
|
||||||
|
|
@ -6131,6 +6132,7 @@ The following are currently defined:</p>
|
||||||
<li class="listitem"><p>override-commit-ids (as): Array of specific commit IDs to fetch for refs</p></li>
|
<li class="listitem"><p>override-commit-ids (as): Array of specific commit IDs to fetch for refs</p></li>
|
||||||
<li class="listitem"><p>dry-run (b): Only print information on what will be downloaded (requires static deltas)</p></li>
|
<li class="listitem"><p>dry-run (b): Only print information on what will be downloaded (requires static deltas)</p></li>
|
||||||
<li class="listitem"><p>override-url (s): Fetch objects from this URL if remote specifies no metalink in options</p></li>
|
<li class="listitem"><p>override-url (s): Fetch objects from this URL if remote specifies no metalink in options</p></li>
|
||||||
|
<li class="listitem"><p>inherit-transaction (b): Don't initiate, finish or abort a transaction, usefult to do mutliple pulls in one transaction.</p></li>
|
||||||
</ul></div>
|
</ul></div>
|
||||||
<div class="refsect3">
|
<div class="refsect3">
|
||||||
<a name="ostree-repo-pull-with-options.parameters"></a><h4>Parameters</h4>
|
<a name="ostree-repo-pull-with-options.parameters"></a><h4>Parameters</h4>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# Guess values for system-dependent variables and create Makefiles.
|
||||||
# Generated by GNU Autoconf 2.69 for ostree 2016.11.
|
# Generated by GNU Autoconf 2.69 for ostree 2016.12.
|
||||||
#
|
#
|
||||||
# Report bugs to <walters@verbum.org>.
|
# Report bugs to <walters@verbum.org>.
|
||||||
#
|
#
|
||||||
|
|
@ -590,8 +590,8 @@ MAKEFLAGS=
|
||||||
# Identity of this package.
|
# Identity of this package.
|
||||||
PACKAGE_NAME='ostree'
|
PACKAGE_NAME='ostree'
|
||||||
PACKAGE_TARNAME='ostree'
|
PACKAGE_TARNAME='ostree'
|
||||||
PACKAGE_VERSION='2016.11'
|
PACKAGE_VERSION='2016.12'
|
||||||
PACKAGE_STRING='ostree 2016.11'
|
PACKAGE_STRING='ostree 2016.12'
|
||||||
PACKAGE_BUGREPORT='walters@verbum.org'
|
PACKAGE_BUGREPORT='walters@verbum.org'
|
||||||
PACKAGE_URL=''
|
PACKAGE_URL=''
|
||||||
|
|
||||||
|
|
@ -1480,7 +1480,7 @@ if test "$ac_init_help" = "long"; then
|
||||||
# Omit some internal or obsolete options to make the list less imposing.
|
# Omit some internal or obsolete options to make the list less imposing.
|
||||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||||
cat <<_ACEOF
|
cat <<_ACEOF
|
||||||
\`configure' configures ostree 2016.11 to adapt to many kinds of systems.
|
\`configure' configures ostree 2016.12 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
|
|
@ -1550,7 +1550,7 @@ fi
|
||||||
|
|
||||||
if test -n "$ac_init_help"; then
|
if test -n "$ac_init_help"; then
|
||||||
case $ac_init_help in
|
case $ac_init_help in
|
||||||
short | recursive ) echo "Configuration of ostree 2016.11:";;
|
short | recursive ) echo "Configuration of ostree 2016.12:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
|
|
@ -1759,7 +1759,7 @@ fi
|
||||||
test -n "$ac_init_help" && exit $ac_status
|
test -n "$ac_init_help" && exit $ac_status
|
||||||
if $ac_init_version; then
|
if $ac_init_version; then
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
ostree configure 2016.11
|
ostree configure 2016.12
|
||||||
generated by GNU Autoconf 2.69
|
generated by GNU Autoconf 2.69
|
||||||
|
|
||||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||||
|
|
@ -2174,7 +2174,7 @@ cat >config.log <<_ACEOF
|
||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
||||||
It was created by ostree $as_me 2016.11, which was
|
It was created by ostree $as_me 2016.12, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
|
|
@ -3041,7 +3041,7 @@ fi
|
||||||
|
|
||||||
# Define the identity of the package.
|
# Define the identity of the package.
|
||||||
PACKAGE='ostree'
|
PACKAGE='ostree'
|
||||||
VERSION='2016.11'
|
VERSION='2016.12'
|
||||||
|
|
||||||
|
|
||||||
# Some tools Automake needs.
|
# Some tools Automake needs.
|
||||||
|
|
@ -17092,7 +17092,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||||
# report actual input values of CONFIG_FILES etc. instead of their
|
# report actual input values of CONFIG_FILES etc. instead of their
|
||||||
# values after options handling.
|
# values after options handling.
|
||||||
ac_log="
|
ac_log="
|
||||||
This file was extended by ostree $as_me 2016.11, which was
|
This file was extended by ostree $as_me 2016.12, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
|
|
@ -17158,7 +17158,7 @@ _ACEOF
|
||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
ostree config.status 2016.11
|
ostree config.status 2016.12
|
||||||
configured by $0, generated by GNU Autoconf 2.69,
|
configured by $0, generated by GNU Autoconf 2.69,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
AC_PREREQ([2.63])
|
AC_PREREQ([2.63])
|
||||||
dnl If incrementing the version here, remember to update libostree.sym too
|
dnl If incrementing the version here, remember to update libostree.sym too
|
||||||
AC_INIT([ostree], [2016.11], [walters@verbum.org])
|
AC_INIT([ostree], [2016.12], [walters@verbum.org])
|
||||||
AC_CONFIG_HEADER([config.h])
|
AC_CONFIG_HEADER([config.h])
|
||||||
AC_CONFIG_MACRO_DIR([buildutil])
|
AC_CONFIG_MACRO_DIR([buildutil])
|
||||||
AC_CONFIG_AUX_DIR([build-aux])
|
AC_CONFIG_AUX_DIR([build-aux])
|
||||||
|
|
|
||||||
|
|
@ -356,6 +356,7 @@ global:
|
||||||
/* No new symbols in 2016.9 */
|
/* No new symbols in 2016.9 */
|
||||||
/* No new symbols in 2016.10 */
|
/* No new symbols in 2016.10 */
|
||||||
/* No new symbols in 2016.11 */
|
/* No new symbols in 2016.11 */
|
||||||
|
/* No new symbols in 2016.12 */
|
||||||
|
|
||||||
/* NOTE NOTE NOTE
|
/* NOTE NOTE NOTE
|
||||||
* Versions above here are released. Only add symbols below this line.
|
* Versions above here are released. Only add symbols below this line.
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,9 @@ typedef struct {
|
||||||
|
|
||||||
/* Also protected by output_stream_set_lock. */
|
/* Also protected by output_stream_set_lock. */
|
||||||
guint64 total_downloaded;
|
guint64 total_downloaded;
|
||||||
|
|
||||||
|
GError *oob_error;
|
||||||
|
|
||||||
} ThreadClosure;
|
} ThreadClosure;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -159,6 +162,8 @@ thread_closure_unref (ThreadClosure *thread_closure)
|
||||||
g_clear_pointer (&thread_closure->output_stream_set, g_hash_table_unref);
|
g_clear_pointer (&thread_closure->output_stream_set, g_hash_table_unref);
|
||||||
g_mutex_clear (&thread_closure->output_stream_set_lock);
|
g_mutex_clear (&thread_closure->output_stream_set_lock);
|
||||||
|
|
||||||
|
g_clear_pointer (&thread_closure->oob_error, g_error_free);
|
||||||
|
|
||||||
g_slice_free (ThreadClosure, thread_closure);
|
g_slice_free (ThreadClosure, thread_closure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -276,6 +281,29 @@ session_thread_config_flags (ThreadClosure *thread_closure,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_authenticate (SoupSession *session, SoupMessage *msg, SoupAuth *auth,
|
||||||
|
gboolean retrying, gpointer user_data)
|
||||||
|
{
|
||||||
|
ThreadClosure *thread_closure = user_data;
|
||||||
|
|
||||||
|
if (msg->status_code == SOUP_STATUS_PROXY_UNAUTHORIZED)
|
||||||
|
{
|
||||||
|
SoupURI *uri = NULL;
|
||||||
|
g_object_get (session, SOUP_SESSION_PROXY_URI, &uri, NULL);
|
||||||
|
if (retrying)
|
||||||
|
{
|
||||||
|
g_autofree char *s = soup_uri_to_string (uri, FALSE);
|
||||||
|
g_set_error (&thread_closure->oob_error,
|
||||||
|
G_IO_ERROR, G_IO_ERROR_PROXY_AUTH_FAILED,
|
||||||
|
"Invalid username or password for proxy '%s'", s);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
soup_auth_authenticate (auth, soup_uri_get_user (uri),
|
||||||
|
soup_uri_get_password (uri));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
session_thread_set_proxy_cb (ThreadClosure *thread_closure,
|
session_thread_set_proxy_cb (ThreadClosure *thread_closure,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
|
|
@ -285,6 +313,17 @@ session_thread_set_proxy_cb (ThreadClosure *thread_closure,
|
||||||
g_object_set (thread_closure->session,
|
g_object_set (thread_closure->session,
|
||||||
SOUP_SESSION_PROXY_URI,
|
SOUP_SESSION_PROXY_URI,
|
||||||
proxy_uri, NULL);
|
proxy_uri, NULL);
|
||||||
|
|
||||||
|
/* libsoup won't necessarily pass any embedded username and password to proxy
|
||||||
|
* requests, so we have to be ready to handle 407 and handle them ourselves.
|
||||||
|
* See also: https://bugzilla.gnome.org/show_bug.cgi?id=772932
|
||||||
|
* */
|
||||||
|
if (soup_uri_get_user (proxy_uri) &&
|
||||||
|
soup_uri_get_password (proxy_uri))
|
||||||
|
{
|
||||||
|
g_signal_connect (thread_closure->session, "authenticate",
|
||||||
|
G_CALLBACK (on_authenticate), thread_closure);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LIBSOUP_CLIENT_CERTS
|
#ifdef HAVE_LIBSOUP_CLIENT_CERTS
|
||||||
|
|
@ -998,10 +1037,23 @@ on_request_sent (GObject *object,
|
||||||
code = G_IO_ERROR_FAILED;
|
code = G_IO_ERROR_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
local_error = g_error_new (G_IO_ERROR, code,
|
{
|
||||||
"Server returned status %u: %s",
|
g_autofree char *errmsg =
|
||||||
msg->status_code,
|
g_strdup_printf ("Server returned status %u: %s",
|
||||||
soup_status_get_phrase (msg->status_code));
|
msg->status_code,
|
||||||
|
soup_status_get_phrase (msg->status_code));
|
||||||
|
|
||||||
|
/* Let's make OOB errors be the final one since they're probably
|
||||||
|
* the cause for the error here. */
|
||||||
|
if (pending->thread_closure->oob_error)
|
||||||
|
{
|
||||||
|
local_error =
|
||||||
|
g_error_copy (pending->thread_closure->oob_error);
|
||||||
|
g_prefix_error (&local_error, "%s: ", errmsg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
local_error = g_error_new_literal (G_IO_ERROR, code, errmsg);
|
||||||
|
}
|
||||||
|
|
||||||
if (pending->mirrorlist->len > 1)
|
if (pending->mirrorlist->len > 1)
|
||||||
g_prefix_error (&local_error,
|
g_prefix_error (&local_error,
|
||||||
|
|
|
||||||
|
|
@ -437,7 +437,7 @@ checkout_one_file_at (OstreeRepo *repo,
|
||||||
|
|
||||||
need_copy = FALSE;
|
need_copy = FALSE;
|
||||||
}
|
}
|
||||||
else if (!is_symlink)
|
else
|
||||||
{
|
{
|
||||||
gboolean did_hardlink = FALSE;
|
gboolean did_hardlink = FALSE;
|
||||||
/* Try to do a hardlink first, if it's a regular file. This also
|
/* Try to do a hardlink first, if it's a regular file. This also
|
||||||
|
|
@ -450,7 +450,9 @@ checkout_one_file_at (OstreeRepo *repo,
|
||||||
gboolean is_bare = ((current_repo->mode == OSTREE_REPO_MODE_BARE
|
gboolean is_bare = ((current_repo->mode == OSTREE_REPO_MODE_BARE
|
||||||
&& options->mode == OSTREE_REPO_CHECKOUT_MODE_NONE) ||
|
&& options->mode == OSTREE_REPO_CHECKOUT_MODE_NONE) ||
|
||||||
(current_repo->mode == OSTREE_REPO_MODE_BARE_USER
|
(current_repo->mode == OSTREE_REPO_MODE_BARE_USER
|
||||||
&& options->mode == OSTREE_REPO_CHECKOUT_MODE_USER));
|
&& options->mode == OSTREE_REPO_CHECKOUT_MODE_USER
|
||||||
|
/* NOTE: bare-user symlinks are not stored as symlinks */
|
||||||
|
&& !is_symlink));
|
||||||
gboolean current_can_cache = (options->enable_uncompressed_cache
|
gboolean current_can_cache = (options->enable_uncompressed_cache
|
||||||
&& current_repo->enable_uncompressed_cache);
|
&& current_repo->enable_uncompressed_cache);
|
||||||
gboolean is_archive_z2_with_cache = (current_repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2
|
gboolean is_archive_z2_with_cache = (current_repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2
|
||||||
|
|
|
||||||
|
|
@ -2036,7 +2036,8 @@ ostree_repo_read_commit_detached_metadata (OstreeRepo *self,
|
||||||
|
|
||||||
_ostree_loose_path (buf, checksum, OSTREE_OBJECT_TYPE_COMMIT_META, self->mode);
|
_ostree_loose_path (buf, checksum, OSTREE_OBJECT_TYPE_COMMIT_META, self->mode);
|
||||||
|
|
||||||
if (!ot_util_variant_map_at (self->objects_dir_fd, buf,
|
if (self->commit_stagedir_fd != -1 &&
|
||||||
|
!ot_util_variant_map_at (self->commit_stagedir_fd, buf,
|
||||||
G_VARIANT_TYPE ("a{sv}"),
|
G_VARIANT_TYPE ("a{sv}"),
|
||||||
OT_VARIANT_MAP_ALLOW_NOENT | OT_VARIANT_MAP_TRUSTED, &ret_metadata, error))
|
OT_VARIANT_MAP_ALLOW_NOENT | OT_VARIANT_MAP_TRUSTED, &ret_metadata, error))
|
||||||
{
|
{
|
||||||
|
|
@ -2044,6 +2045,21 @@ ostree_repo_read_commit_detached_metadata (OstreeRepo *self,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret_metadata == NULL &&
|
||||||
|
!ot_util_variant_map_at (self->objects_dir_fd, buf,
|
||||||
|
G_VARIANT_TYPE ("a{sv}"),
|
||||||
|
OT_VARIANT_MAP_ALLOW_NOENT | OT_VARIANT_MAP_TRUSTED, &ret_metadata, error))
|
||||||
|
{
|
||||||
|
g_prefix_error (error, "Unable to read existing detached metadata: ");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret_metadata == NULL && self->parent_repo)
|
||||||
|
return ostree_repo_read_commit_detached_metadata (self->parent_repo,
|
||||||
|
checksum,
|
||||||
|
out_metadata,
|
||||||
|
cancellable,
|
||||||
|
error);
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
ot_transfer_out_value (out_metadata, &ret_metadata);
|
ot_transfer_out_value (out_metadata, &ret_metadata);
|
||||||
out:
|
out:
|
||||||
|
|
@ -2073,10 +2089,16 @@ ostree_repo_write_commit_detached_metadata (OstreeRepo *self,
|
||||||
g_autoptr(GVariant) normalized = NULL;
|
g_autoptr(GVariant) normalized = NULL;
|
||||||
gsize normalized_size = 0;
|
gsize normalized_size = 0;
|
||||||
const guint8 *data = NULL;
|
const guint8 *data = NULL;
|
||||||
|
int dest_dfd;
|
||||||
|
|
||||||
|
if (self->in_transaction)
|
||||||
|
dest_dfd = self->commit_stagedir_fd;
|
||||||
|
else
|
||||||
|
dest_dfd = self->objects_dir_fd;
|
||||||
|
|
||||||
_ostree_loose_path (pathbuf, checksum, OSTREE_OBJECT_TYPE_COMMIT_META, self->mode);
|
_ostree_loose_path (pathbuf, checksum, OSTREE_OBJECT_TYPE_COMMIT_META, self->mode);
|
||||||
|
|
||||||
if (!_ostree_repo_ensure_loose_objdir_at (self->objects_dir_fd, checksum,
|
if (!_ostree_repo_ensure_loose_objdir_at (dest_dfd, checksum,
|
||||||
cancellable, error))
|
cancellable, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
|
@ -2090,7 +2112,7 @@ ostree_repo_write_commit_detached_metadata (OstreeRepo *self,
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
data = (guint8*)"";
|
data = (guint8*)"";
|
||||||
|
|
||||||
if (!glnx_file_replace_contents_at (self->objects_dir_fd, pathbuf,
|
if (!glnx_file_replace_contents_at (dest_dfd, pathbuf,
|
||||||
data, normalized_size,
|
data, normalized_size,
|
||||||
0, cancellable, error))
|
0, cancellable, error))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ typedef struct {
|
||||||
gboolean is_commit_only;
|
gboolean is_commit_only;
|
||||||
gboolean is_untrusted;
|
gboolean is_untrusted;
|
||||||
|
|
||||||
char *dir;
|
GPtrArray *dirs;
|
||||||
gboolean commitpartial_exists;
|
gboolean commitpartial_exists;
|
||||||
|
|
||||||
gboolean have_previous_bytes;
|
gboolean have_previous_bytes;
|
||||||
|
|
@ -117,6 +117,7 @@ typedef struct {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
OtPullData *pull_data;
|
OtPullData *pull_data;
|
||||||
GVariant *object;
|
GVariant *object;
|
||||||
|
char *path;
|
||||||
gboolean is_detached_meta;
|
gboolean is_detached_meta;
|
||||||
|
|
||||||
/* Only relevant when is_detached_meta is TRUE. Controls
|
/* Only relevant when is_detached_meta is TRUE. Controls
|
||||||
|
|
@ -133,6 +134,7 @@ typedef struct {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
guchar csum[OSTREE_SHA256_DIGEST_LEN];
|
guchar csum[OSTREE_SHA256_DIGEST_LEN];
|
||||||
|
char *path;
|
||||||
OstreeObjectType objtype;
|
OstreeObjectType objtype;
|
||||||
guint recursion_depth;
|
guint recursion_depth;
|
||||||
} ScanObjectQueueData;
|
} ScanObjectQueueData;
|
||||||
|
|
@ -140,16 +142,19 @@ typedef struct {
|
||||||
static void queue_scan_one_metadata_object (OtPullData *pull_data,
|
static void queue_scan_one_metadata_object (OtPullData *pull_data,
|
||||||
const char *csum,
|
const char *csum,
|
||||||
OstreeObjectType objtype,
|
OstreeObjectType objtype,
|
||||||
|
const char *path,
|
||||||
guint recursion_depth);
|
guint recursion_depth);
|
||||||
|
|
||||||
static void queue_scan_one_metadata_object_c (OtPullData *pull_data,
|
static void queue_scan_one_metadata_object_c (OtPullData *pull_data,
|
||||||
const guchar *csum,
|
const guchar *csum,
|
||||||
OstreeObjectType objtype,
|
OstreeObjectType objtype,
|
||||||
|
const char *path,
|
||||||
guint recursion_depth);
|
guint recursion_depth);
|
||||||
|
|
||||||
static gboolean scan_one_metadata_object_c (OtPullData *pull_data,
|
static gboolean scan_one_metadata_object_c (OtPullData *pull_data,
|
||||||
const guchar *csum,
|
const guchar *csum,
|
||||||
OstreeObjectType objtype,
|
OstreeObjectType objtype,
|
||||||
|
const char *path,
|
||||||
guint recursion_depth,
|
guint recursion_depth,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
@ -278,11 +283,13 @@ idle_worker (gpointer user_data)
|
||||||
scan_one_metadata_object_c (pull_data,
|
scan_one_metadata_object_c (pull_data,
|
||||||
scan_data->csum,
|
scan_data->csum,
|
||||||
scan_data->objtype,
|
scan_data->objtype,
|
||||||
|
scan_data->path,
|
||||||
scan_data->recursion_depth,
|
scan_data->recursion_depth,
|
||||||
pull_data->cancellable,
|
pull_data->cancellable,
|
||||||
&error);
|
&error);
|
||||||
check_outstanding_requests_handle_error (pull_data, error);
|
check_outstanding_requests_handle_error (pull_data, error);
|
||||||
|
|
||||||
|
g_free (scan_data->path);
|
||||||
g_free (scan_data);
|
g_free (scan_data);
|
||||||
return G_SOURCE_CONTINUE;
|
return G_SOURCE_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
@ -381,12 +388,80 @@ static void
|
||||||
enqueue_one_object_request (OtPullData *pull_data,
|
enqueue_one_object_request (OtPullData *pull_data,
|
||||||
const char *checksum,
|
const char *checksum,
|
||||||
OstreeObjectType objtype,
|
OstreeObjectType objtype,
|
||||||
|
const char *path,
|
||||||
gboolean is_detached_meta,
|
gboolean is_detached_meta,
|
||||||
gboolean object_is_stored);
|
gboolean object_is_stored);
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
matches_pull_dir (const char *current_file,
|
||||||
|
const char *pull_dir,
|
||||||
|
gboolean current_file_is_dir)
|
||||||
|
{
|
||||||
|
const char *rest;
|
||||||
|
|
||||||
|
if (g_str_has_prefix (pull_dir, current_file))
|
||||||
|
{
|
||||||
|
rest = pull_dir + strlen (current_file);
|
||||||
|
if (*rest == 0)
|
||||||
|
{
|
||||||
|
/* The current file is exactly the same as the specified
|
||||||
|
pull dir. This matches always, even if the file is not a
|
||||||
|
directory. */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*rest == '/')
|
||||||
|
{
|
||||||
|
/* The current file is a directory-prefix of the pull_dir.
|
||||||
|
Match only if this is supposed to be a directory */
|
||||||
|
return current_file_is_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Matched a non-directory prefix such as /foo being a prefix of /fooo,
|
||||||
|
no match */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_str_has_prefix (current_file, pull_dir))
|
||||||
|
{
|
||||||
|
rest = current_file + strlen (pull_dir);
|
||||||
|
/* Only match if the prefix match matched the entire directory
|
||||||
|
component */
|
||||||
|
return *rest == '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
pull_matches_subdir (OtPullData *pull_data,
|
||||||
|
const char *path,
|
||||||
|
const char *basename,
|
||||||
|
gboolean basename_is_dir)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
g_autofree char *file = NULL;
|
||||||
|
|
||||||
|
if (pull_data->dirs == NULL)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
file = g_strconcat (path, basename, NULL);
|
||||||
|
|
||||||
|
for (i = 0; i < pull_data->dirs->len; i++)
|
||||||
|
{
|
||||||
|
const char *pull_dir = g_ptr_array_index (pull_data->dirs, i);
|
||||||
|
if (matches_pull_dir (file, pull_dir, basename_is_dir))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
scan_dirtree_object (OtPullData *pull_data,
|
scan_dirtree_object (OtPullData *pull_data,
|
||||||
const char *checksum,
|
const char *checksum,
|
||||||
|
const char *path,
|
||||||
int recursion_depth,
|
int recursion_depth,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
GError **error)
|
||||||
|
|
@ -396,7 +471,6 @@ scan_dirtree_object (OtPullData *pull_data,
|
||||||
g_autoptr(GVariant) tree = NULL;
|
g_autoptr(GVariant) tree = NULL;
|
||||||
g_autoptr(GVariant) files_variant = NULL;
|
g_autoptr(GVariant) files_variant = NULL;
|
||||||
g_autoptr(GVariant) dirs_variant = NULL;
|
g_autoptr(GVariant) dirs_variant = NULL;
|
||||||
char *subdir_target = NULL;
|
|
||||||
const char *dirname = NULL;
|
const char *dirname = NULL;
|
||||||
|
|
||||||
if (recursion_depth > OSTREE_MAX_RECURSION)
|
if (recursion_depth > OSTREE_MAX_RECURSION)
|
||||||
|
|
@ -429,10 +503,7 @@ scan_dirtree_object (OtPullData *pull_data,
|
||||||
|
|
||||||
/* Skip files if we're traversing a request only directory, unless it exactly
|
/* Skip files if we're traversing a request only directory, unless it exactly
|
||||||
* matches the path */
|
* matches the path */
|
||||||
if (pull_data->dir &&
|
if (!pull_matches_subdir (pull_data, path, filename, FALSE))
|
||||||
/* Should always an initial slash, we assert it in scan_dirtree_object */
|
|
||||||
pull_data->dir[0] == '/' &&
|
|
||||||
strcmp (pull_data->dir+1, filename) != 0)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
file_checksum = ostree_checksum_from_bytes_v (csum);
|
file_checksum = ostree_checksum_from_bytes_v (csum);
|
||||||
|
|
@ -451,32 +522,11 @@ scan_dirtree_object (OtPullData *pull_data,
|
||||||
else if (!file_is_stored && !g_hash_table_lookup (pull_data->requested_content, file_checksum))
|
else if (!file_is_stored && !g_hash_table_lookup (pull_data->requested_content, file_checksum))
|
||||||
{
|
{
|
||||||
g_hash_table_insert (pull_data->requested_content, file_checksum, file_checksum);
|
g_hash_table_insert (pull_data->requested_content, file_checksum, file_checksum);
|
||||||
enqueue_one_object_request (pull_data, file_checksum, OSTREE_OBJECT_TYPE_FILE, FALSE, FALSE);
|
enqueue_one_object_request (pull_data, file_checksum, OSTREE_OBJECT_TYPE_FILE, path, FALSE, FALSE);
|
||||||
file_checksum = NULL; /* Transfer ownership */
|
file_checksum = NULL; /* Transfer ownership */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pull_data->dir)
|
|
||||||
{
|
|
||||||
const char *subpath = NULL;
|
|
||||||
const char *nextslash = NULL;
|
|
||||||
g_autofree char *dir_data = NULL;
|
|
||||||
|
|
||||||
g_assert (pull_data->dir[0] == '/'); // assert it starts with / like "/usr/share/rpm"
|
|
||||||
subpath = pull_data->dir + 1; // refers to name minus / like "usr/share/rpm"
|
|
||||||
nextslash = strchr (subpath, '/'); //refers to start of next slash like "/share/rpm"
|
|
||||||
dir_data = pull_data->dir; // keep the original pointer around since strchr() points into it
|
|
||||||
pull_data->dir = NULL;
|
|
||||||
|
|
||||||
if (nextslash)
|
|
||||||
{
|
|
||||||
subdir_target = g_strndup (subpath, nextslash - subpath); // refers to first dir, like "usr"
|
|
||||||
pull_data->dir = g_strdup (nextslash); // sets dir to new deeper level like "/share/rpm"
|
|
||||||
}
|
|
||||||
else // we're as deep as it goes, i.e. subpath = "rpm"
|
|
||||||
subdir_target = g_strdup (subpath);
|
|
||||||
}
|
|
||||||
|
|
||||||
n = g_variant_n_children (dirs_variant);
|
n = g_variant_n_children (dirs_variant);
|
||||||
|
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
|
|
@ -485,6 +535,7 @@ scan_dirtree_object (OtPullData *pull_data,
|
||||||
g_autoptr(GVariant) meta_csum = NULL;
|
g_autoptr(GVariant) meta_csum = NULL;
|
||||||
const guchar *tree_csum_bytes;
|
const guchar *tree_csum_bytes;
|
||||||
const guchar *meta_csum_bytes;
|
const guchar *meta_csum_bytes;
|
||||||
|
g_autofree char *subpath = NULL;
|
||||||
|
|
||||||
g_variant_get_child (dirs_variant, i, "(&s@ay@ay)",
|
g_variant_get_child (dirs_variant, i, "(&s@ay@ay)",
|
||||||
&dirname, &tree_csum, &meta_csum);
|
&dirname, &tree_csum, &meta_csum);
|
||||||
|
|
@ -492,7 +543,7 @@ scan_dirtree_object (OtPullData *pull_data,
|
||||||
if (!ot_util_filename_validate (dirname, error))
|
if (!ot_util_filename_validate (dirname, error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (subdir_target && strcmp (subdir_target, dirname) != 0)
|
if (!pull_matches_subdir (pull_data, path, dirname, TRUE))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
tree_csum_bytes = ostree_checksum_bytes_peek_validate (tree_csum, error);
|
tree_csum_bytes = ostree_checksum_bytes_peek_validate (tree_csum, error);
|
||||||
|
|
@ -503,10 +554,12 @@ scan_dirtree_object (OtPullData *pull_data,
|
||||||
if (meta_csum_bytes == NULL)
|
if (meta_csum_bytes == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
subpath = g_strconcat (path, dirname, "/", NULL);
|
||||||
|
|
||||||
queue_scan_one_metadata_object_c (pull_data, tree_csum_bytes,
|
queue_scan_one_metadata_object_c (pull_data, tree_csum_bytes,
|
||||||
OSTREE_OBJECT_TYPE_DIR_TREE, recursion_depth + 1);
|
OSTREE_OBJECT_TYPE_DIR_TREE, subpath, recursion_depth + 1);
|
||||||
queue_scan_one_metadata_object_c (pull_data, meta_csum_bytes,
|
queue_scan_one_metadata_object_c (pull_data, meta_csum_bytes,
|
||||||
OSTREE_OBJECT_TYPE_DIR_META, recursion_depth + 1);
|
OSTREE_OBJECT_TYPE_DIR_META, subpath, recursion_depth + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
|
|
@ -583,6 +636,14 @@ lookup_commit_checksum_from_summary (OtPullData *pull_data,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fetch_object_data_free (FetchObjectData *fetch_data)
|
||||||
|
{
|
||||||
|
g_variant_unref (fetch_data->object);
|
||||||
|
g_free (fetch_data->path);
|
||||||
|
g_free (fetch_data);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
content_fetch_on_write_complete (GObject *object,
|
content_fetch_on_write_complete (GObject *object,
|
||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
|
|
@ -622,8 +683,7 @@ content_fetch_on_write_complete (GObject *object,
|
||||||
out:
|
out:
|
||||||
pull_data->n_outstanding_content_write_requests--;
|
pull_data->n_outstanding_content_write_requests--;
|
||||||
check_outstanding_requests_handle_error (pull_data, local_error);
|
check_outstanding_requests_handle_error (pull_data, local_error);
|
||||||
g_variant_unref (fetch_data->object);
|
fetch_object_data_free (fetch_data);
|
||||||
g_free (fetch_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -712,10 +772,7 @@ content_fetch_on_complete (GObject *object,
|
||||||
pull_data->n_outstanding_content_fetches--;
|
pull_data->n_outstanding_content_fetches--;
|
||||||
check_outstanding_requests_handle_error (pull_data, local_error);
|
check_outstanding_requests_handle_error (pull_data, local_error);
|
||||||
if (free_fetch_data)
|
if (free_fetch_data)
|
||||||
{
|
fetch_object_data_free (fetch_data);
|
||||||
g_variant_unref (fetch_data->object);
|
|
||||||
g_free (fetch_data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -753,12 +810,11 @@ on_metadata_written (GObject *object,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
queue_scan_one_metadata_object_c (pull_data, csum, objtype, 0);
|
queue_scan_one_metadata_object_c (pull_data, csum, objtype, fetch_data->path, 0);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
pull_data->n_outstanding_metadata_write_requests--;
|
pull_data->n_outstanding_metadata_write_requests--;
|
||||||
g_variant_unref (fetch_data->object);
|
fetch_object_data_free (fetch_data);
|
||||||
g_free (fetch_data);
|
|
||||||
|
|
||||||
check_outstanding_requests_handle_error (pull_data, local_error);
|
check_outstanding_requests_handle_error (pull_data, local_error);
|
||||||
}
|
}
|
||||||
|
|
@ -796,7 +852,7 @@ meta_fetch_on_complete (GObject *object,
|
||||||
/* There isn't any detached metadata, just fetch the commit */
|
/* There isn't any detached metadata, just fetch the commit */
|
||||||
g_clear_error (&local_error);
|
g_clear_error (&local_error);
|
||||||
if (!fetch_data->object_is_stored)
|
if (!fetch_data->object_is_stored)
|
||||||
enqueue_one_object_request (pull_data, checksum, objtype, FALSE, FALSE);
|
enqueue_one_object_request (pull_data, checksum, objtype, fetch_data->path, FALSE, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When traversing parents, do not fail on a missing commit.
|
/* When traversing parents, do not fail on a missing commit.
|
||||||
|
|
@ -811,7 +867,7 @@ meta_fetch_on_complete (GObject *object,
|
||||||
if (pull_data->has_tombstone_commits)
|
if (pull_data->has_tombstone_commits)
|
||||||
{
|
{
|
||||||
enqueue_one_object_request (pull_data, checksum, OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT,
|
enqueue_one_object_request (pull_data, checksum, OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT,
|
||||||
FALSE, FALSE);
|
fetch_data->path, FALSE, FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -844,7 +900,7 @@ meta_fetch_on_complete (GObject *object,
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!fetch_data->object_is_stored)
|
if (!fetch_data->object_is_stored)
|
||||||
enqueue_one_object_request (pull_data, checksum, objtype, FALSE, FALSE);
|
enqueue_one_object_request (pull_data, checksum, objtype, fetch_data->path, FALSE, FALSE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -874,10 +930,7 @@ meta_fetch_on_complete (GObject *object,
|
||||||
pull_data->n_fetched_metadata++;
|
pull_data->n_fetched_metadata++;
|
||||||
check_outstanding_requests_handle_error (pull_data, local_error);
|
check_outstanding_requests_handle_error (pull_data, local_error);
|
||||||
if (free_fetch_data)
|
if (free_fetch_data)
|
||||||
{
|
fetch_object_data_free (fetch_data);
|
||||||
g_variant_unref (fetch_data->object);
|
|
||||||
g_free (fetch_data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1053,7 +1106,8 @@ scan_commit_object (OtPullData *pull_data,
|
||||||
if (parent_csum_bytes != NULL && pull_data->maxdepth == -1)
|
if (parent_csum_bytes != NULL && pull_data->maxdepth == -1)
|
||||||
{
|
{
|
||||||
queue_scan_one_metadata_object_c (pull_data, parent_csum_bytes,
|
queue_scan_one_metadata_object_c (pull_data, parent_csum_bytes,
|
||||||
OSTREE_OBJECT_TYPE_COMMIT, recursion_depth + 1);
|
OSTREE_OBJECT_TYPE_COMMIT, NULL,
|
||||||
|
recursion_depth + 1);
|
||||||
}
|
}
|
||||||
else if (parent_csum_bytes != NULL && depth > 0)
|
else if (parent_csum_bytes != NULL && depth > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -1078,7 +1132,9 @@ scan_commit_object (OtPullData *pull_data,
|
||||||
g_hash_table_insert (pull_data->commit_to_depth, g_strdup (parent_checksum),
|
g_hash_table_insert (pull_data->commit_to_depth, g_strdup (parent_checksum),
|
||||||
GINT_TO_POINTER (parent_depth));
|
GINT_TO_POINTER (parent_depth));
|
||||||
queue_scan_one_metadata_object_c (pull_data, parent_csum_bytes,
|
queue_scan_one_metadata_object_c (pull_data, parent_csum_bytes,
|
||||||
OSTREE_OBJECT_TYPE_COMMIT, recursion_depth + 1);
|
OSTREE_OBJECT_TYPE_COMMIT,
|
||||||
|
NULL,
|
||||||
|
recursion_depth + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1101,10 +1157,10 @@ scan_commit_object (OtPullData *pull_data,
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
queue_scan_one_metadata_object_c (pull_data, tree_contents_csum_bytes,
|
queue_scan_one_metadata_object_c (pull_data, tree_contents_csum_bytes,
|
||||||
OSTREE_OBJECT_TYPE_DIR_TREE, recursion_depth + 1);
|
OSTREE_OBJECT_TYPE_DIR_TREE, "/", recursion_depth + 1);
|
||||||
|
|
||||||
queue_scan_one_metadata_object_c (pull_data, tree_meta_csum_bytes,
|
queue_scan_one_metadata_object_c (pull_data, tree_meta_csum_bytes,
|
||||||
OSTREE_OBJECT_TYPE_DIR_META, recursion_depth + 1);
|
OSTREE_OBJECT_TYPE_DIR_META, NULL, recursion_depth + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
|
|
@ -1116,23 +1172,26 @@ static void
|
||||||
queue_scan_one_metadata_object (OtPullData *pull_data,
|
queue_scan_one_metadata_object (OtPullData *pull_data,
|
||||||
const char *csum,
|
const char *csum,
|
||||||
OstreeObjectType objtype,
|
OstreeObjectType objtype,
|
||||||
|
const char *path,
|
||||||
guint recursion_depth)
|
guint recursion_depth)
|
||||||
{
|
{
|
||||||
guchar buf[OSTREE_SHA256_DIGEST_LEN];
|
guchar buf[OSTREE_SHA256_DIGEST_LEN];
|
||||||
ostree_checksum_inplace_to_bytes (csum, buf);
|
ostree_checksum_inplace_to_bytes (csum, buf);
|
||||||
queue_scan_one_metadata_object_c (pull_data, buf, objtype, recursion_depth);
|
queue_scan_one_metadata_object_c (pull_data, buf, objtype, path, recursion_depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
queue_scan_one_metadata_object_c (OtPullData *pull_data,
|
queue_scan_one_metadata_object_c (OtPullData *pull_data,
|
||||||
const guchar *csum,
|
const guchar *csum,
|
||||||
OstreeObjectType objtype,
|
OstreeObjectType objtype,
|
||||||
|
const char *path,
|
||||||
guint recursion_depth)
|
guint recursion_depth)
|
||||||
{
|
{
|
||||||
ScanObjectQueueData *scan_data = g_new0 (ScanObjectQueueData, 1);
|
ScanObjectQueueData *scan_data = g_new0 (ScanObjectQueueData, 1);
|
||||||
|
|
||||||
memcpy (scan_data->csum, csum, sizeof (scan_data->csum));
|
memcpy (scan_data->csum, csum, sizeof (scan_data->csum));
|
||||||
scan_data->objtype = objtype;
|
scan_data->objtype = objtype;
|
||||||
|
scan_data->path = g_strdup (path);
|
||||||
scan_data->recursion_depth = recursion_depth;
|
scan_data->recursion_depth = recursion_depth;
|
||||||
|
|
||||||
g_queue_push_tail (&pull_data->scan_object_queue, scan_data);
|
g_queue_push_tail (&pull_data->scan_object_queue, scan_data);
|
||||||
|
|
@ -1143,6 +1202,7 @@ static gboolean
|
||||||
scan_one_metadata_object_c (OtPullData *pull_data,
|
scan_one_metadata_object_c (OtPullData *pull_data,
|
||||||
const guchar *csum,
|
const guchar *csum,
|
||||||
OstreeObjectType objtype,
|
OstreeObjectType objtype,
|
||||||
|
const char *path,
|
||||||
guint recursion_depth,
|
guint recursion_depth,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
GError **error)
|
||||||
|
|
@ -1190,7 +1250,7 @@ scan_one_metadata_object_c (OtPullData *pull_data,
|
||||||
g_hash_table_insert (pull_data->requested_metadata, duped_checksum, duped_checksum);
|
g_hash_table_insert (pull_data->requested_metadata, duped_checksum, duped_checksum);
|
||||||
|
|
||||||
do_fetch_detached = (objtype == OSTREE_OBJECT_TYPE_COMMIT);
|
do_fetch_detached = (objtype == OSTREE_OBJECT_TYPE_COMMIT);
|
||||||
enqueue_one_object_request (pull_data, tmp_checksum, objtype, do_fetch_detached, FALSE);
|
enqueue_one_object_request (pull_data, tmp_checksum, objtype, path, do_fetch_detached, FALSE);
|
||||||
}
|
}
|
||||||
else if (objtype == OSTREE_OBJECT_TYPE_COMMIT && pull_data->is_commit_only)
|
else if (objtype == OSTREE_OBJECT_TYPE_COMMIT && pull_data->is_commit_only)
|
||||||
{
|
{
|
||||||
|
|
@ -1207,7 +1267,7 @@ scan_one_metadata_object_c (OtPullData *pull_data,
|
||||||
|
|
||||||
/* For commits, always refetch detached metadata. */
|
/* For commits, always refetch detached metadata. */
|
||||||
if (objtype == OSTREE_OBJECT_TYPE_COMMIT)
|
if (objtype == OSTREE_OBJECT_TYPE_COMMIT)
|
||||||
enqueue_one_object_request (pull_data, tmp_checksum, objtype, TRUE, TRUE);
|
enqueue_one_object_request (pull_data, tmp_checksum, objtype, path, TRUE, TRUE);
|
||||||
|
|
||||||
/* For commits, check whether we only had a partial fetch */
|
/* For commits, check whether we only had a partial fetch */
|
||||||
if (!do_scan && objtype == OSTREE_OBJECT_TYPE_COMMIT)
|
if (!do_scan && objtype == OSTREE_OBJECT_TYPE_COMMIT)
|
||||||
|
|
@ -1245,7 +1305,7 @@ scan_one_metadata_object_c (OtPullData *pull_data,
|
||||||
case OSTREE_OBJECT_TYPE_DIR_META:
|
case OSTREE_OBJECT_TYPE_DIR_META:
|
||||||
break;
|
break;
|
||||||
case OSTREE_OBJECT_TYPE_DIR_TREE:
|
case OSTREE_OBJECT_TYPE_DIR_TREE:
|
||||||
if (!scan_dirtree_object (pull_data, tmp_checksum, recursion_depth,
|
if (!scan_dirtree_object (pull_data, tmp_checksum, path, recursion_depth,
|
||||||
pull_data->cancellable, error))
|
pull_data->cancellable, error))
|
||||||
goto out;
|
goto out;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1267,6 +1327,7 @@ static void
|
||||||
enqueue_one_object_request (OtPullData *pull_data,
|
enqueue_one_object_request (OtPullData *pull_data,
|
||||||
const char *checksum,
|
const char *checksum,
|
||||||
OstreeObjectType objtype,
|
OstreeObjectType objtype,
|
||||||
|
const char *path,
|
||||||
gboolean is_detached_meta,
|
gboolean is_detached_meta,
|
||||||
gboolean object_is_stored)
|
gboolean object_is_stored)
|
||||||
{
|
{
|
||||||
|
|
@ -1308,6 +1369,7 @@ enqueue_one_object_request (OtPullData *pull_data,
|
||||||
fetch_data = g_new0 (FetchObjectData, 1);
|
fetch_data = g_new0 (FetchObjectData, 1);
|
||||||
fetch_data->pull_data = pull_data;
|
fetch_data->pull_data = pull_data;
|
||||||
fetch_data->object = ostree_object_name_serialize (checksum, objtype);
|
fetch_data->object = ostree_object_name_serialize (checksum, objtype);
|
||||||
|
fetch_data->path = g_strdup (path);
|
||||||
fetch_data->is_detached_meta = is_detached_meta;
|
fetch_data->is_detached_meta = is_detached_meta;
|
||||||
fetch_data->object_is_stored = object_is_stored;
|
fetch_data->object_is_stored = object_is_stored;
|
||||||
|
|
||||||
|
|
@ -1478,7 +1540,7 @@ process_one_static_delta_fallback (OtPullData *pull_data,
|
||||||
g_hash_table_insert (pull_data->requested_metadata, checksum, checksum);
|
g_hash_table_insert (pull_data->requested_metadata, checksum, checksum);
|
||||||
|
|
||||||
do_fetch_detached = (objtype == OSTREE_OBJECT_TYPE_COMMIT);
|
do_fetch_detached = (objtype == OSTREE_OBJECT_TYPE_COMMIT);
|
||||||
enqueue_one_object_request (pull_data, checksum, objtype, do_fetch_detached, FALSE);
|
enqueue_one_object_request (pull_data, checksum, objtype, NULL, do_fetch_detached, FALSE);
|
||||||
checksum = NULL; /* Transfer ownership */
|
checksum = NULL; /* Transfer ownership */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1487,7 +1549,7 @@ process_one_static_delta_fallback (OtPullData *pull_data,
|
||||||
if (!g_hash_table_lookup (pull_data->requested_content, checksum))
|
if (!g_hash_table_lookup (pull_data->requested_content, checksum))
|
||||||
{
|
{
|
||||||
g_hash_table_insert (pull_data->requested_content, checksum, checksum);
|
g_hash_table_insert (pull_data->requested_content, checksum, checksum);
|
||||||
enqueue_one_object_request (pull_data, checksum, OSTREE_OBJECT_TYPE_FILE, FALSE, FALSE);
|
enqueue_one_object_request (pull_data, checksum, OSTREE_OBJECT_TYPE_FILE, NULL, FALSE, FALSE);
|
||||||
checksum = NULL; /* Transfer ownership */
|
checksum = NULL; /* Transfer ownership */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2227,6 +2289,7 @@ repo_remote_fetch_summary (OstreeRepo *self,
|
||||||
* * refs (as): Array of string refs
|
* * refs (as): Array of string refs
|
||||||
* * flags (i): An instance of #OstreeRepoPullFlags
|
* * flags (i): An instance of #OstreeRepoPullFlags
|
||||||
* * subdir (s): Pull just this subdirectory
|
* * subdir (s): Pull just this subdirectory
|
||||||
|
* * subdirs (as): Pull just these subdirectories
|
||||||
* * override-remote-name (s): If local, add this remote to refspec
|
* * override-remote-name (s): If local, add this remote to refspec
|
||||||
* * gpg-verify (b): GPG verify commits
|
* * gpg-verify (b): GPG verify commits
|
||||||
* * gpg-verify-summary (b): GPG verify summary
|
* * gpg-verify-summary (b): GPG verify summary
|
||||||
|
|
@ -2236,6 +2299,7 @@ repo_remote_fetch_summary (OstreeRepo *self,
|
||||||
* * override-commit-ids (as): Array of specific commit IDs to fetch for refs
|
* * override-commit-ids (as): Array of specific commit IDs to fetch for refs
|
||||||
* * dry-run (b): Only print information on what will be downloaded (requires static deltas)
|
* * dry-run (b): Only print information on what will be downloaded (requires static deltas)
|
||||||
* * override-url (s): Fetch objects from this URL if remote specifies no metalink in options
|
* * override-url (s): Fetch objects from this URL if remote specifies no metalink in options
|
||||||
|
* * inherit-transaction (b): Don't initiate, finish or abort a transaction, usefult to do mutliple pulls in one transaction.
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
ostree_repo_pull_with_options (OstreeRepo *self,
|
ostree_repo_pull_with_options (OstreeRepo *self,
|
||||||
|
|
@ -2262,6 +2326,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||||
guint64 end_time;
|
guint64 end_time;
|
||||||
OstreeRepoPullFlags flags = 0;
|
OstreeRepoPullFlags flags = 0;
|
||||||
const char *dir_to_pull = NULL;
|
const char *dir_to_pull = NULL;
|
||||||
|
g_autofree char **dirs_to_pull = NULL;
|
||||||
g_autofree char **refs_to_fetch = NULL;
|
g_autofree char **refs_to_fetch = NULL;
|
||||||
char **override_commit_ids = NULL;
|
char **override_commit_ids = NULL;
|
||||||
GSource *update_timeout = NULL;
|
GSource *update_timeout = NULL;
|
||||||
|
|
@ -2273,6 +2338,8 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||||
g_autofree char *base_meta_url = NULL;
|
g_autofree char *base_meta_url = NULL;
|
||||||
g_autofree char *base_content_url = NULL;
|
g_autofree char *base_content_url = NULL;
|
||||||
gboolean mirroring_into_archive;
|
gboolean mirroring_into_archive;
|
||||||
|
gboolean inherit_transaction = FALSE;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (options)
|
if (options)
|
||||||
{
|
{
|
||||||
|
|
@ -2282,6 +2349,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||||
/* Reduce risk of issues if enum happens to be 64 bit for some reason */
|
/* Reduce risk of issues if enum happens to be 64 bit for some reason */
|
||||||
flags = flags_i;
|
flags = flags_i;
|
||||||
(void) g_variant_lookup (options, "subdir", "&s", &dir_to_pull);
|
(void) g_variant_lookup (options, "subdir", "&s", &dir_to_pull);
|
||||||
|
(void) g_variant_lookup (options, "subdirs", "^a&s", &dirs_to_pull);
|
||||||
(void) g_variant_lookup (options, "override-remote-name", "s", &pull_data->remote_name);
|
(void) g_variant_lookup (options, "override-remote-name", "s", &pull_data->remote_name);
|
||||||
opt_gpg_verify_set =
|
opt_gpg_verify_set =
|
||||||
g_variant_lookup (options, "gpg-verify", "b", &pull_data->gpg_verify);
|
g_variant_lookup (options, "gpg-verify", "b", &pull_data->gpg_verify);
|
||||||
|
|
@ -2293,6 +2361,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||||
(void) g_variant_lookup (options, "override-commit-ids", "^a&s", &override_commit_ids);
|
(void) g_variant_lookup (options, "override-commit-ids", "^a&s", &override_commit_ids);
|
||||||
(void) g_variant_lookup (options, "dry-run", "b", &pull_data->dry_run);
|
(void) g_variant_lookup (options, "dry-run", "b", &pull_data->dry_run);
|
||||||
(void) g_variant_lookup (options, "override-url", "&s", &url_override);
|
(void) g_variant_lookup (options, "override-url", "&s", &url_override);
|
||||||
|
(void) g_variant_lookup (options, "inherit-transaction", "b", &inherit_transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_return_val_if_fail (pull_data->maxdepth >= -1, FALSE);
|
g_return_val_if_fail (pull_data->maxdepth >= -1, FALSE);
|
||||||
|
|
@ -2302,6 +2371,9 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||||
if (dir_to_pull)
|
if (dir_to_pull)
|
||||||
g_return_val_if_fail (dir_to_pull[0] == '/', FALSE);
|
g_return_val_if_fail (dir_to_pull[0] == '/', FALSE);
|
||||||
|
|
||||||
|
for (i = 0; dirs_to_pull != NULL && dirs_to_pull[i] != NULL; i++)
|
||||||
|
g_return_val_if_fail (dirs_to_pull[i][0] == '/', FALSE);
|
||||||
|
|
||||||
g_return_val_if_fail (!(disable_static_deltas && require_static_deltas), FALSE);
|
g_return_val_if_fail (!(disable_static_deltas && require_static_deltas), FALSE);
|
||||||
/* We only do dry runs with static deltas, because we don't really have any
|
/* We only do dry runs with static deltas, because we don't really have any
|
||||||
* in-advance information for bare fetches.
|
* in-advance information for bare fetches.
|
||||||
|
|
@ -2340,7 +2412,19 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||||
(GDestroyNotify)g_free, NULL);
|
(GDestroyNotify)g_free, NULL);
|
||||||
pull_data->requested_metadata = g_hash_table_new_full (g_str_hash, g_str_equal,
|
pull_data->requested_metadata = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
(GDestroyNotify)g_free, NULL);
|
(GDestroyNotify)g_free, NULL);
|
||||||
pull_data->dir = g_strdup (dir_to_pull);
|
if (dir_to_pull != NULL || dirs_to_pull != NULL)
|
||||||
|
{
|
||||||
|
pull_data->dirs = g_ptr_array_new_with_free_func (g_free);
|
||||||
|
if (dir_to_pull != NULL)
|
||||||
|
g_ptr_array_add (pull_data->dirs, g_strdup (dir_to_pull));
|
||||||
|
|
||||||
|
if (dirs_to_pull != NULL)
|
||||||
|
{
|
||||||
|
for (i = 0; dirs_to_pull[i] != NULL; i++)
|
||||||
|
g_ptr_array_add (pull_data->dirs, g_strdup (dirs_to_pull[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g_queue_init (&pull_data->scan_object_queue);
|
g_queue_init (&pull_data->scan_object_queue);
|
||||||
|
|
||||||
pull_data->start_time = g_get_monotonic_time ();
|
pull_data->start_time = g_get_monotonic_time ();
|
||||||
|
|
@ -2822,7 +2906,9 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||||
if (pull_data->fetcher == NULL)
|
if (pull_data->fetcher == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!ostree_repo_prepare_transaction (pull_data->repo, &pull_data->legacy_transaction_resuming,
|
pull_data->legacy_transaction_resuming = FALSE;
|
||||||
|
if (!inherit_transaction &&
|
||||||
|
!ostree_repo_prepare_transaction (pull_data->repo, &pull_data->legacy_transaction_resuming,
|
||||||
cancellable, error))
|
cancellable, error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
@ -2833,7 +2919,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||||
while (g_hash_table_iter_next (&hash_iter, &key, &value))
|
while (g_hash_table_iter_next (&hash_iter, &key, &value))
|
||||||
{
|
{
|
||||||
const char *commit = value;
|
const char *commit = value;
|
||||||
queue_scan_one_metadata_object (pull_data, commit, OSTREE_OBJECT_TYPE_COMMIT, 0);
|
queue_scan_one_metadata_object (pull_data, commit, OSTREE_OBJECT_TYPE_COMMIT, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_hash_table_iter_init (&hash_iter, requested_refs_to_fetch);
|
g_hash_table_iter_init (&hash_iter, requested_refs_to_fetch);
|
||||||
|
|
@ -2866,7 +2952,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
g_debug ("no delta superblock for %s-%s", from_revision ? from_revision : "empty", to_revision);
|
g_debug ("no delta superblock for %s-%s", from_revision ? from_revision : "empty", to_revision);
|
||||||
queue_scan_one_metadata_object (pull_data, to_revision, OSTREE_OBJECT_TYPE_COMMIT, 0);
|
queue_scan_one_metadata_object (pull_data, to_revision, OSTREE_OBJECT_TYPE_COMMIT, NULL, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -2954,7 +3040,8 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ostree_repo_commit_transaction (pull_data->repo, NULL, cancellable, error))
|
if (!inherit_transaction &&
|
||||||
|
!ostree_repo_commit_transaction (pull_data->repo, NULL, cancellable, error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
end_time = g_get_monotonic_time ();
|
end_time = g_get_monotonic_time ();
|
||||||
|
|
@ -2988,7 +3075,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* iterate over commits fetched and delete any commitpartial files */
|
/* iterate over commits fetched and delete any commitpartial files */
|
||||||
if (!dir_to_pull && !pull_data->is_commit_only)
|
if (pull_data->dirs == NULL && !pull_data->is_commit_only)
|
||||||
{
|
{
|
||||||
g_hash_table_iter_init (&hash_iter, requested_refs_to_fetch);
|
g_hash_table_iter_init (&hash_iter, requested_refs_to_fetch);
|
||||||
while (g_hash_table_iter_next (&hash_iter, &key, &value))
|
while (g_hash_table_iter_next (&hash_iter, &key, &value))
|
||||||
|
|
@ -3021,7 +3108,8 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||||
else
|
else
|
||||||
g_clear_error (&pull_data->cached_async_error);
|
g_clear_error (&pull_data->cached_async_error);
|
||||||
|
|
||||||
ostree_repo_abort_transaction (pull_data->repo, cancellable, NULL);
|
if (!inherit_transaction)
|
||||||
|
ostree_repo_abort_transaction (pull_data->repo, cancellable, NULL);
|
||||||
g_main_context_unref (pull_data->main_context);
|
g_main_context_unref (pull_data->main_context);
|
||||||
if (update_timeout)
|
if (update_timeout)
|
||||||
g_source_destroy (update_timeout);
|
g_source_destroy (update_timeout);
|
||||||
|
|
|
||||||
|
|
@ -2011,8 +2011,6 @@ allocate_deployserial (OstreeSysroot *self,
|
||||||
{
|
{
|
||||||
OstreeDeployment *deployment = tmp_current_deployments->pdata[i];
|
OstreeDeployment *deployment = tmp_current_deployments->pdata[i];
|
||||||
|
|
||||||
if (strcmp (ostree_deployment_get_osname (deployment), osname) != 0)
|
|
||||||
continue;
|
|
||||||
if (strcmp (ostree_deployment_get_csum (deployment), revision) != 0)
|
if (strcmp (ostree_deployment_get_csum (deployment), revision) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ static gboolean opt_dry_run;
|
||||||
static gboolean opt_disable_static_deltas;
|
static gboolean opt_disable_static_deltas;
|
||||||
static gboolean opt_require_static_deltas;
|
static gboolean opt_require_static_deltas;
|
||||||
static gboolean opt_untrusted;
|
static gboolean opt_untrusted;
|
||||||
static char* opt_subpath;
|
static char** opt_subpaths;
|
||||||
static char* opt_cache_dir;
|
static char* opt_cache_dir;
|
||||||
static int opt_depth = 0;
|
static int opt_depth = 0;
|
||||||
static char* opt_url;
|
static char* opt_url;
|
||||||
|
|
@ -46,7 +46,7 @@ static GOptionEntry options[] = {
|
||||||
{ "disable-static-deltas", 0, 0, G_OPTION_ARG_NONE, &opt_disable_static_deltas, "Do not use static deltas", NULL },
|
{ "disable-static-deltas", 0, 0, G_OPTION_ARG_NONE, &opt_disable_static_deltas, "Do not use static deltas", NULL },
|
||||||
{ "require-static-deltas", 0, 0, G_OPTION_ARG_NONE, &opt_require_static_deltas, "Require static deltas", NULL },
|
{ "require-static-deltas", 0, 0, G_OPTION_ARG_NONE, &opt_require_static_deltas, "Require static deltas", NULL },
|
||||||
{ "mirror", 0, 0, G_OPTION_ARG_NONE, &opt_mirror, "Write refs suitable for a mirror", NULL },
|
{ "mirror", 0, 0, G_OPTION_ARG_NONE, &opt_mirror, "Write refs suitable for a mirror", NULL },
|
||||||
{ "subpath", 0, 0, G_OPTION_ARG_STRING, &opt_subpath, "Only pull the provided subpath", NULL },
|
{ "subpath", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_subpaths, "Only pull the provided subpath(s)", NULL },
|
||||||
{ "untrusted", 0, 0, G_OPTION_ARG_NONE, &opt_untrusted, "Do not trust (local) sources", NULL },
|
{ "untrusted", 0, 0, G_OPTION_ARG_NONE, &opt_untrusted, "Do not trust (local) sources", NULL },
|
||||||
{ "dry-run", 0, 0, G_OPTION_ARG_NONE, &opt_dry_run, "Only print information on what will be downloaded (requires static deltas)", NULL },
|
{ "dry-run", 0, 0, G_OPTION_ARG_NONE, &opt_dry_run, "Only print information on what will be downloaded (requires static deltas)", NULL },
|
||||||
{ "depth", 0, 0, G_OPTION_ARG_INT, &opt_depth, "Traverse DEPTH parents (-1=infinite) (default: 0)", "DEPTH" },
|
{ "depth", 0, 0, G_OPTION_ARG_INT, &opt_depth, "Traverse DEPTH parents (-1=infinite) (default: 0)", "DEPTH" },
|
||||||
|
|
@ -216,9 +216,17 @@ ostree_builtin_pull (int argc, char **argv, GCancellable *cancellable, GError **
|
||||||
if (opt_url)
|
if (opt_url)
|
||||||
g_variant_builder_add (&builder, "{s@v}", "override-url",
|
g_variant_builder_add (&builder, "{s@v}", "override-url",
|
||||||
g_variant_new_variant (g_variant_new_string (opt_url)));
|
g_variant_new_variant (g_variant_new_string (opt_url)));
|
||||||
if (opt_subpath)
|
if (opt_subpaths && opt_subpaths[0] != NULL)
|
||||||
g_variant_builder_add (&builder, "{s@v}", "subdir",
|
{
|
||||||
g_variant_new_variant (g_variant_new_string (opt_subpath)));
|
/* Special case the one-element case so that we excercise this
|
||||||
|
old single-argument version in the tests */
|
||||||
|
if (opt_subpaths[1] == NULL)
|
||||||
|
g_variant_builder_add (&builder, "{s@v}", "subdir",
|
||||||
|
g_variant_new_variant (g_variant_new_string (opt_subpaths[0])));
|
||||||
|
else
|
||||||
|
g_variant_builder_add (&builder, "{s@v}", "subdirs",
|
||||||
|
g_variant_new_variant (g_variant_new_strv ((const char *const*) opt_subpaths, -1)));
|
||||||
|
}
|
||||||
g_variant_builder_add (&builder, "{s@v}", "flags",
|
g_variant_builder_add (&builder, "{s@v}", "flags",
|
||||||
g_variant_new_variant (g_variant_new_int32 (pullflags)));
|
g_variant_new_variant (g_variant_new_int32 (pullflags)));
|
||||||
if (refs_to_fetch)
|
if (refs_to_fetch)
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,10 @@ mkdir repo
|
||||||
${CMD_PREFIX} ostree --repo=repo init
|
${CMD_PREFIX} ostree --repo=repo init
|
||||||
${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin ${remoteurl}
|
${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin ${remoteurl}
|
||||||
|
|
||||||
${CMD_PREFIX} ostree --repo=repo pull --subpath=/baz origin main
|
${CMD_PREFIX} ostree --repo=repo pull --subpath=/baz/deeper --subpath=/baz/another origin main
|
||||||
|
|
||||||
${CMD_PREFIX} ostree --repo=repo ls origin:main /baz
|
${CMD_PREFIX} ostree --repo=repo ls origin:main /baz/deeper
|
||||||
|
${CMD_PREFIX} ostree --repo=repo ls origin:main /baz/another
|
||||||
if ${CMD_PREFIX} ostree --repo=repo ls origin:main /firstfile 2>err.txt; then
|
if ${CMD_PREFIX} ostree --repo=repo ls origin:main /firstfile 2>err.txt; then
|
||||||
assert_not_reached
|
assert_not_reached
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue