Merge tag 'upstream/2016.12' into debian/master

Upstream version 2016.12
This commit is contained in:
Simon McVittie 2016-10-25 22:29:03 +01:00
commit bc870baa58
11 changed files with 271 additions and 97 deletions

View File

@ -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>

20
configure vendored
View File

@ -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\\"

View File

@ -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])

View File

@ -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.

View File

@ -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,

View File

@ -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

View File

@ -2035,8 +2035,9 @@ ostree_repo_read_commit_detached_metadata (OstreeRepo *self,
g_autoptr(GVariant) ret_metadata = NULL; g_autoptr(GVariant) ret_metadata = NULL;
_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))
{ {

View File

@ -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))
@ -3020,8 +3107,9 @@ ostree_repo_pull_with_options (OstreeRepo *self,
g_propagate_error (error, pull_data->cached_async_error); g_propagate_error (error, pull_data->cached_async_error);
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);

View File

@ -2002,7 +2002,7 @@ allocate_deployserial (OstreeSysroot *self,
g_ptr_array_new_with_free_func (g_object_unref); g_ptr_array_new_with_free_func (g_object_unref);
osdir = ot_gfile_get_child_build_path (self->path, "ostree/deploy", osname, NULL); osdir = ot_gfile_get_child_build_path (self->path, "ostree/deploy", osname, NULL);
if (!_ostree_sysroot_list_deployment_dirs_for_os (osdir, tmp_current_deployments, if (!_ostree_sysroot_list_deployment_dirs_for_os (osdir, tmp_current_deployments,
cancellable, error)) cancellable, error))
goto out; goto out;
@ -2010,9 +2010,7 @@ allocate_deployserial (OstreeSysroot *self,
for (i = 0; i < tmp_current_deployments->len; i++) for (i = 0; i < tmp_current_deployments->len; i++)
{ {
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;

View File

@ -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)

View File

@ -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