pull: Use all available commits for delta sources
The previous logic for static deltas was to use as a FROM revision the current branch tip. However, we want to support deltas between branches in an automatic fashion. If a summary file is available, we already have an enumerated list of deltas - so the logic introduced here is to search it, and find the newest commit we have locally that matches the TO revision target. This builds on some thoughts from https://github.com/ostreedev/ostree/pull/151#issuecomment-232390232 Closes: https://github.com/ostreedev/ostree/pull/151 Closes: #710 Approved by: giuseppe
This commit is contained in:
parent
b41f150a72
commit
a787e0c072
|
|
@ -1866,6 +1866,87 @@ process_one_static_delta (OtPullData *pull_data,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Loop over the static delta data we got from the summary,
|
||||||
|
* and find the newest commit for @out_from_revision that
|
||||||
|
* goes to @to_revision.
|
||||||
|
*/
|
||||||
|
static gboolean
|
||||||
|
get_best_static_delta_start_for (OtPullData *pull_data,
|
||||||
|
const char *to_revision,
|
||||||
|
char **out_from_revision,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GHashTableIter hiter;
|
||||||
|
gpointer hkey, hvalue;
|
||||||
|
/* Array<char*> of possible from checksums */
|
||||||
|
g_autoptr(GPtrArray) candidates = g_ptr_array_new_with_free_func (g_free);
|
||||||
|
const char *newest_candidate = NULL;
|
||||||
|
guint64 newest_candidate_timestamp;
|
||||||
|
|
||||||
|
g_assert (pull_data->summary_deltas_checksums != NULL);
|
||||||
|
g_hash_table_iter_init (&hiter, pull_data->summary_deltas_checksums);
|
||||||
|
|
||||||
|
/* Loop over all deltas known from the summary file,
|
||||||
|
* finding ones which go to to_revision */
|
||||||
|
while (g_hash_table_iter_next (&hiter, &hkey, &hvalue))
|
||||||
|
{
|
||||||
|
const char *delta_name = hkey;
|
||||||
|
g_autofree char *cur_from_rev = NULL;
|
||||||
|
g_autofree char *cur_to_rev = NULL;
|
||||||
|
|
||||||
|
/* Gracefully handle corrupted (or malicious) summary files */
|
||||||
|
if (!_ostree_parse_delta_name (delta_name, &cur_from_rev, &cur_to_rev, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Is this the checksum we want? */
|
||||||
|
if (strcmp (cur_to_rev, to_revision) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (cur_from_rev)
|
||||||
|
g_ptr_array_add (candidates, g_steal_pointer (&cur_from_rev));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loop over our candidates, find the newest one */
|
||||||
|
for (guint i = 0; i < candidates->len; i++)
|
||||||
|
{
|
||||||
|
const char *candidate = candidates->pdata[i];
|
||||||
|
guint64 candidate_ts;
|
||||||
|
g_autoptr(GVariant) commit = NULL;
|
||||||
|
OstreeRepoCommitState state;
|
||||||
|
gboolean have_candidate;
|
||||||
|
|
||||||
|
/* Do we have this commit at all? If not, skip it */
|
||||||
|
if (!ostree_repo_has_object (pull_data->repo, OSTREE_OBJECT_TYPE_COMMIT,
|
||||||
|
candidate, &have_candidate,
|
||||||
|
NULL, error))
|
||||||
|
return FALSE;
|
||||||
|
if (!have_candidate)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Load it */
|
||||||
|
if (!ostree_repo_load_commit (pull_data->repo, candidate,
|
||||||
|
&commit, &state, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Ignore partial commits, we can't use them */
|
||||||
|
if (state & OSTREE_REPO_COMMIT_STATE_PARTIAL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Is it newer? */
|
||||||
|
candidate_ts = ostree_commit_get_timestamp (commit);
|
||||||
|
if (newest_candidate == NULL ||
|
||||||
|
candidate_ts > newest_candidate_timestamp)
|
||||||
|
{
|
||||||
|
newest_candidate = candidate;
|
||||||
|
newest_candidate_timestamp = candidate_ts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_from_revision = g_strdup (newest_candidate);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
OtPullData *pull_data;
|
OtPullData *pull_data;
|
||||||
char *from_revision;
|
char *from_revision;
|
||||||
|
|
@ -3159,9 +3240,21 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
||||||
const char *ref = key;
|
const char *ref = key;
|
||||||
const char *to_revision = value;
|
const char *to_revision = value;
|
||||||
|
|
||||||
if (!ostree_repo_resolve_rev (pull_data->repo, ref, TRUE,
|
/* If we have a summary, find the latest local commit we have
|
||||||
&from_revision, error))
|
* to use as a from revision for static deltas.
|
||||||
goto out;
|
*/
|
||||||
|
if (pull_data->summary)
|
||||||
|
{
|
||||||
|
if (!get_best_static_delta_start_for (pull_data, to_revision, &from_revision,
|
||||||
|
cancellable, error))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!ostree_repo_resolve_rev (pull_data->repo, ref, TRUE,
|
||||||
|
&from_revision, error))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (!disable_static_deltas &&
|
if (!disable_static_deltas &&
|
||||||
(from_revision == NULL || g_strcmp0 (from_revision, to_revision) != 0))
|
(from_revision == NULL || g_strcmp0 (from_revision, to_revision) != 0))
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ skip_without_user_xattrs
|
||||||
bindatafiles="bash true ostree"
|
bindatafiles="bash true ostree"
|
||||||
morebindatafiles="false ls"
|
morebindatafiles="false ls"
|
||||||
|
|
||||||
echo '1..11'
|
echo '1..12'
|
||||||
|
|
||||||
mkdir repo
|
mkdir repo
|
||||||
${CMD_PREFIX} ostree --repo=repo init --mode=archive-z2
|
${CMD_PREFIX} ostree --repo=repo init --mode=archive-z2
|
||||||
|
|
@ -244,6 +244,17 @@ ${CMD_PREFIX} ostree --repo=repo2 ls ${samerev} >/dev/null
|
||||||
|
|
||||||
echo 'ok pull empty delta part'
|
echo 'ok pull empty delta part'
|
||||||
|
|
||||||
|
# Make a new branch to test "rebase deltas"
|
||||||
|
echo otherbranch-content > files/otherbranch-content
|
||||||
|
${CMD_PREFIX} ostree --repo=repo commit -b otherbranch --tree=dir=files
|
||||||
|
samerev=$(${CMD_PREFIX} ostree --repo=repo rev-parse test)
|
||||||
|
${CMD_PREFIX} ostree --repo=repo static-delta generate --from=test --to=otherbranch
|
||||||
|
${CMD_PREFIX} ostree --repo=repo summary -u
|
||||||
|
${CMD_PREFIX} ostree --repo=repo2 pull-local --require-static-deltas repo otherbranch
|
||||||
|
|
||||||
|
echo 'ok rebase deltas'
|
||||||
|
|
||||||
|
${CMD_PREFIX} ostree --repo=repo summary -u
|
||||||
if ${CMD_PREFIX} ostree --repo=repo static-delta show GARBAGE 2> err.txt; then
|
if ${CMD_PREFIX} ostree --repo=repo static-delta show GARBAGE 2> err.txt; then
|
||||||
assert_not_reached "static-delta show GARBAGE unexpectedly succeeded"
|
assert_not_reached "static-delta show GARBAGE unexpectedly succeeded"
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue