New upstream version 2018.4

This commit is contained in:
Simon McVittie 2018-03-24 18:19:31 +00:00
commit de3c1878b1
85 changed files with 1520 additions and 1199 deletions

View File

@ -26,6 +26,7 @@ ostree-admin-config-diff.1 ostree-admin-deploy.1 \
ostree-admin-init-fs.1 ostree-admin-instutil.1 ostree-admin-os-init.1 \ ostree-admin-init-fs.1 ostree-admin-instutil.1 ostree-admin-os-init.1 \
ostree-admin-status.1 ostree-admin-set-origin.1 ostree-admin-switch.1 \ ostree-admin-status.1 ostree-admin-set-origin.1 ostree-admin-switch.1 \
ostree-admin-undeploy.1 ostree-admin-upgrade.1 ostree-admin-unlock.1 \ ostree-admin-undeploy.1 ostree-admin-upgrade.1 ostree-admin-unlock.1 \
ostree-admin-pin.1 \
ostree-admin.1 ostree-cat.1 ostree-checkout.1 ostree-checksum.1 \ ostree-admin.1 ostree-cat.1 ostree-checkout.1 ostree-checksum.1 \
ostree-commit.1 ostree-export.1 ostree-gpg-sign.1 ostree-config.1 \ ostree-commit.1 ostree-export.1 ostree-gpg-sign.1 ostree-config.1 \
ostree-diff.1 ostree-fsck.1 ostree-init.1 ostree-log.1 ostree-ls.1 \ ostree-diff.1 ostree-fsck.1 ostree-init.1 ostree-log.1 ostree-ls.1 \

View File

@ -74,6 +74,7 @@ ostree_SOURCES += \
src/ostree/ot-admin-builtin-set-origin.c \ src/ostree/ot-admin-builtin-set-origin.c \
src/ostree/ot-admin-builtin-status.c \ src/ostree/ot-admin-builtin-status.c \
src/ostree/ot-admin-builtin-switch.c \ src/ostree/ot-admin-builtin-switch.c \
src/ostree/ot-admin-builtin-pin.c \
src/ostree/ot-admin-builtin-upgrade.c \ src/ostree/ot-admin-builtin-upgrade.c \
src/ostree/ot-admin-builtin-unlock.c \ src/ostree/ot-admin-builtin-unlock.c \
src/ostree/ot-admin-builtins.h \ src/ostree/ot-admin-builtins.h \

View File

@ -1007,6 +1007,7 @@ am__ostree_SOURCES_DIST = src/ostree/main.c \
src/ostree/ot-admin-builtin-set-origin.c \ src/ostree/ot-admin-builtin-set-origin.c \
src/ostree/ot-admin-builtin-status.c \ src/ostree/ot-admin-builtin-status.c \
src/ostree/ot-admin-builtin-switch.c \ src/ostree/ot-admin-builtin-switch.c \
src/ostree/ot-admin-builtin-pin.c \
src/ostree/ot-admin-builtin-upgrade.c \ src/ostree/ot-admin-builtin-upgrade.c \
src/ostree/ot-admin-builtin-unlock.c \ src/ostree/ot-admin-builtin-unlock.c \
src/ostree/ot-admin-builtins.h \ src/ostree/ot-admin-builtins.h \
@ -1079,6 +1080,7 @@ am_ostree_OBJECTS = src/ostree/ostree-main.$(OBJEXT) \
src/ostree/ostree-ot-admin-builtin-set-origin.$(OBJEXT) \ src/ostree/ostree-ot-admin-builtin-set-origin.$(OBJEXT) \
src/ostree/ostree-ot-admin-builtin-status.$(OBJEXT) \ src/ostree/ostree-ot-admin-builtin-status.$(OBJEXT) \
src/ostree/ostree-ot-admin-builtin-switch.$(OBJEXT) \ src/ostree/ostree-ot-admin-builtin-switch.$(OBJEXT) \
src/ostree/ostree-ot-admin-builtin-pin.$(OBJEXT) \
src/ostree/ostree-ot-admin-builtin-upgrade.$(OBJEXT) \ src/ostree/ostree-ot-admin-builtin-upgrade.$(OBJEXT) \
src/ostree/ostree-ot-admin-builtin-unlock.$(OBJEXT) \ src/ostree/ostree-ot-admin-builtin-unlock.$(OBJEXT) \
src/ostree/ostree-ot-admin-instutil-builtin-selinux-ensure-labeled.$(OBJEXT) \ src/ostree/ostree-ot-admin-instutil-builtin-selinux-ensure-labeled.$(OBJEXT) \
@ -2469,6 +2471,7 @@ ostree_SOURCES = src/ostree/main.c src/ostree/ot-builtin-admin.c \
src/ostree/ot-admin-builtin-set-origin.c \ src/ostree/ot-admin-builtin-set-origin.c \
src/ostree/ot-admin-builtin-status.c \ src/ostree/ot-admin-builtin-status.c \
src/ostree/ot-admin-builtin-switch.c \ src/ostree/ot-admin-builtin-switch.c \
src/ostree/ot-admin-builtin-pin.c \
src/ostree/ot-admin-builtin-upgrade.c \ src/ostree/ot-admin-builtin-upgrade.c \
src/ostree/ot-admin-builtin-unlock.c \ src/ostree/ot-admin-builtin-unlock.c \
src/ostree/ot-admin-builtins.h \ src/ostree/ot-admin-builtins.h \
@ -2773,7 +2776,8 @@ tests_test_gpg_verify_result_LDADD = $(TESTS_LDADD) $(OT_INTERNAL_GPGME_LIBS)
@ENABLE_MAN_TRUE@ ostree-admin-set-origin.1 \ @ENABLE_MAN_TRUE@ ostree-admin-set-origin.1 \
@ENABLE_MAN_TRUE@ ostree-admin-switch.1 ostree-admin-undeploy.1 \ @ENABLE_MAN_TRUE@ ostree-admin-switch.1 ostree-admin-undeploy.1 \
@ENABLE_MAN_TRUE@ ostree-admin-upgrade.1 ostree-admin-unlock.1 \ @ENABLE_MAN_TRUE@ ostree-admin-upgrade.1 ostree-admin-unlock.1 \
@ENABLE_MAN_TRUE@ ostree-admin.1 ostree-cat.1 ostree-checkout.1 \ @ENABLE_MAN_TRUE@ ostree-admin-pin.1 ostree-admin.1 \
@ENABLE_MAN_TRUE@ ostree-cat.1 ostree-checkout.1 \
@ENABLE_MAN_TRUE@ ostree-checksum.1 ostree-commit.1 \ @ENABLE_MAN_TRUE@ ostree-checksum.1 ostree-commit.1 \
@ENABLE_MAN_TRUE@ ostree-export.1 ostree-gpg-sign.1 \ @ENABLE_MAN_TRUE@ ostree-export.1 ostree-gpg-sign.1 \
@ENABLE_MAN_TRUE@ ostree-config.1 ostree-diff.1 ostree-fsck.1 \ @ENABLE_MAN_TRUE@ ostree-config.1 ostree-diff.1 ostree-fsck.1 \
@ -3768,6 +3772,9 @@ src/ostree/ostree-ot-admin-builtin-status.$(OBJEXT): \
src/ostree/ostree-ot-admin-builtin-switch.$(OBJEXT): \ src/ostree/ostree-ot-admin-builtin-switch.$(OBJEXT): \
src/ostree/$(am__dirstamp) \ src/ostree/$(am__dirstamp) \
src/ostree/$(DEPDIR)/$(am__dirstamp) src/ostree/$(DEPDIR)/$(am__dirstamp)
src/ostree/ostree-ot-admin-builtin-pin.$(OBJEXT): \
src/ostree/$(am__dirstamp) \
src/ostree/$(DEPDIR)/$(am__dirstamp)
src/ostree/ostree-ot-admin-builtin-upgrade.$(OBJEXT): \ src/ostree/ostree-ot-admin-builtin-upgrade.$(OBJEXT): \
src/ostree/$(am__dirstamp) \ src/ostree/$(am__dirstamp) \
src/ostree/$(DEPDIR)/$(am__dirstamp) src/ostree/$(DEPDIR)/$(am__dirstamp)
@ -4419,6 +4426,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-init-fs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-init-fs.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-instutil.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-instutil.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-os-init.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-os-init.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-pin.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-set-origin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-set-origin.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-status.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-status.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-switch.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-switch.Po@am__quote@
@ -5681,6 +5689,20 @@ src/ostree/ostree-ot-admin-builtin-switch.obj: src/ostree/ot-admin-builtin-switc
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -c -o src/ostree/ostree-ot-admin-builtin-switch.obj `if test -f 'src/ostree/ot-admin-builtin-switch.c'; then $(CYGPATH_W) 'src/ostree/ot-admin-builtin-switch.c'; else $(CYGPATH_W) '$(srcdir)/src/ostree/ot-admin-builtin-switch.c'; fi` @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -c -o src/ostree/ostree-ot-admin-builtin-switch.obj `if test -f 'src/ostree/ot-admin-builtin-switch.c'; then $(CYGPATH_W) 'src/ostree/ot-admin-builtin-switch.c'; else $(CYGPATH_W) '$(srcdir)/src/ostree/ot-admin-builtin-switch.c'; fi`
src/ostree/ostree-ot-admin-builtin-pin.o: src/ostree/ot-admin-builtin-pin.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -MT src/ostree/ostree-ot-admin-builtin-pin.o -MD -MP -MF src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-pin.Tpo -c -o src/ostree/ostree-ot-admin-builtin-pin.o `test -f 'src/ostree/ot-admin-builtin-pin.c' || echo '$(srcdir)/'`src/ostree/ot-admin-builtin-pin.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-pin.Tpo src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-pin.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/ostree/ot-admin-builtin-pin.c' object='src/ostree/ostree-ot-admin-builtin-pin.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -c -o src/ostree/ostree-ot-admin-builtin-pin.o `test -f 'src/ostree/ot-admin-builtin-pin.c' || echo '$(srcdir)/'`src/ostree/ot-admin-builtin-pin.c
src/ostree/ostree-ot-admin-builtin-pin.obj: src/ostree/ot-admin-builtin-pin.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -MT src/ostree/ostree-ot-admin-builtin-pin.obj -MD -MP -MF src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-pin.Tpo -c -o src/ostree/ostree-ot-admin-builtin-pin.obj `if test -f 'src/ostree/ot-admin-builtin-pin.c'; then $(CYGPATH_W) 'src/ostree/ot-admin-builtin-pin.c'; else $(CYGPATH_W) '$(srcdir)/src/ostree/ot-admin-builtin-pin.c'; fi`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-pin.Tpo src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-pin.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/ostree/ot-admin-builtin-pin.c' object='src/ostree/ostree-ot-admin-builtin-pin.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -c -o src/ostree/ostree-ot-admin-builtin-pin.obj `if test -f 'src/ostree/ot-admin-builtin-pin.c'; then $(CYGPATH_W) 'src/ostree/ot-admin-builtin-pin.c'; else $(CYGPATH_W) '$(srcdir)/src/ostree/ot-admin-builtin-pin.c'; fi`
src/ostree/ostree-ot-admin-builtin-upgrade.o: src/ostree/ot-admin-builtin-upgrade.c src/ostree/ostree-ot-admin-builtin-upgrade.o: src/ostree/ot-admin-builtin-upgrade.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -MT src/ostree/ostree-ot-admin-builtin-upgrade.o -MD -MP -MF src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-upgrade.Tpo -c -o src/ostree/ostree-ot-admin-builtin-upgrade.o `test -f 'src/ostree/ot-admin-builtin-upgrade.c' || echo '$(srcdir)/'`src/ostree/ot-admin-builtin-upgrade.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -MT src/ostree/ostree-ot-admin-builtin-upgrade.o -MD -MP -MF src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-upgrade.Tpo -c -o src/ostree/ostree-ot-admin-builtin-upgrade.o `test -f 'src/ostree/ot-admin-builtin-upgrade.c' || echo '$(srcdir)/'`src/ostree/ot-admin-builtin-upgrade.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-upgrade.Tpo src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-upgrade.Po @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-upgrade.Tpo src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-upgrade.Po

View File

@ -14,7 +14,7 @@
<div class="titlepage"> <div class="titlepage">
<div> <div>
<div><table class="navigation" id="top" width="100%" cellpadding="2" cellspacing="0"><tr><th valign="middle"><p class="title">OSTree API references</p></th></tr></table></div> <div><table class="navigation" id="top" width="100%" cellpadding="2" cellspacing="0"><tr><th valign="middle"><p class="title">OSTree API references</p></th></tr></table></div>
<div><p class="releaseinfo">for OSTree 2018.2</p></div> <div><p class="releaseinfo">for OSTree 2018.4</p></div>
</div> </div>
<hr> <hr>
</div> </div>

View File

@ -2488,6 +2488,13 @@ content, the other types are metadata.</p>
</td> </td>
<td class="enum_member_annotations"> </td> <td class="enum_member_annotations"> </td>
</tr> </tr>
<tr>
<td class="enum_member_name"><p><a name="OSTREE-OBJECT-TYPE-PAYLOAD-LINK:CAPS"></a>OSTREE_OBJECT_TYPE_PAYLOAD_LINK</p></td>
<td class="enum_member_description">
<p>Symlink to a .file given its checksum on the payload only.</p>
</td>
<td class="enum_member_annotations"> </td>
</tr>
</tbody> </tbody>
</table></div> </table></div>
</div> </div>
@ -2495,7 +2502,7 @@ content, the other types are metadata.</p>
<hr> <hr>
<div class="refsect2"> <div class="refsect2">
<a name="OSTREE-OBJECT-TYPE-LAST:CAPS"></a><h3>OSTREE_OBJECT_TYPE_LAST</h3> <a name="OSTREE-OBJECT-TYPE-LAST:CAPS"></a><h3>OSTREE_OBJECT_TYPE_LAST</h3>
<pre class="programlisting">#define OSTREE_OBJECT_TYPE_LAST OSTREE_OBJECT_TYPE_COMMIT_META <pre class="programlisting">#define OSTREE_OBJECT_TYPE_LAST OSTREE_OBJECT_TYPE_PAYLOAD_LINK
</pre> </pre>
<p>Last valid object type; use this to validate ranges.</p> <p>Last valid object type; use this to validate ranges.</p>
</div> </div>

View File

@ -2285,6 +2285,7 @@ The following are currently defined:</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem"><p>override-url (s): Fetch summary from this URL if remote specifies no metalink in options</p></li> <li class="listitem"><p>override-url (s): Fetch summary from this URL if remote specifies no metalink in options</p></li>
<li class="listitem"><p>http-headers (a(ss)): Additional headers to add to all HTTP requests</p></li> <li class="listitem"><p>http-headers (a(ss)): Additional headers to add to all HTTP requests</p></li>
<li class="listitem"><p>append-user-agent (s): Additional string to append to the user agent</p></li>
</ul></div> </ul></div>
<div class="refsect3"> <div class="refsect3">
<a name="ostree-repo-remote-fetch-summary-with-options.parameters"></a><h4>Parameters</h4> <a name="ostree-repo-remote-fetch-summary-with-options.parameters"></a><h4>Parameters</h4>
@ -6934,6 +6935,7 @@ string to pull the latest commit for that ref</p></li>
<li class="listitem"><p>http-headers (a(ss)): Additional headers to add to all HTTP requests</p></li> <li class="listitem"><p>http-headers (a(ss)): Additional headers to add to all HTTP requests</p></li>
<li class="listitem"><p>update-frequency (u): Frequency to call the async progress callback in milliseconds, if any; only values higher than 0 are valid</p></li> <li class="listitem"><p>update-frequency (u): Frequency to call the async progress callback in milliseconds, if any; only values higher than 0 are valid</p></li>
<li class="listitem"><p>localcache-repos (as): File paths for local repos to use as caches when doing remote fetches</p></li> <li class="listitem"><p>localcache-repos (as): File paths for local repos to use as caches when doing remote fetches</p></li>
<li class="listitem"><p>append-user-agent (s): Additional string to append to the user agent</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>

View File

@ -268,6 +268,14 @@
<span class="returnvalue">gboolean</span> <span class="returnvalue">gboolean</span>
</td> </td>
<td class="function_name"> <td class="function_name">
<a class="link" href="ostree-Root-partition-mount-point.html#ostree-sysroot-deployment-set-pinned" title="ostree_sysroot_deployment_set_pinned ()">ostree_sysroot_deployment_set_pinned</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">
<span class="returnvalue">gboolean</span>
</td>
<td class="function_name">
<a class="link" href="ostree-Root-partition-mount-point.html#ostree-sysroot-write-deployments" title="ostree_sysroot_write_deployments ()">ostree_sysroot_write_deployments</a> <span class="c_punctuation">()</span> <a class="link" href="ostree-Root-partition-mount-point.html#ostree-sysroot-write-deployments" title="ostree_sysroot_write_deployments ()">ostree_sysroot_write_deployments</a> <span class="c_punctuation">()</span>
</td> </td>
</tr> </tr>
@ -1253,6 +1261,56 @@ across reboots.</p>
</div> </div>
<hr> <hr>
<div class="refsect2"> <div class="refsect2">
<a name="ostree-sysroot-deployment-set-pinned"></a><h3>ostree_sysroot_deployment_set_pinned ()</h3>
<pre class="programlisting"><span class="returnvalue">gboolean</span>
ostree_sysroot_deployment_set_pinned (<em class="parameter"><code><a class="link" href="ostree-Root-partition-mount-point.html#OstreeSysroot" title="OstreeSysroot"><span class="type">OstreeSysroot</span></a> *self</code></em>,
<em class="parameter"><code><a class="link" href="ostree-ostree-deployment.html#OstreeDeployment" title="OstreeDeployment"><span class="type">OstreeDeployment</span></a> *deployment</code></em>,
<em class="parameter"><code><span class="type">gboolean</span> is_pinned</code></em>,
<em class="parameter"><code><span class="type">GError</span> **error</code></em>);</pre>
<p>By default, deployments may be subject to garbage collection. Typical uses of
libostree only retain at most 2 deployments. If <em class="parameter"><code>is_pinned</code></em>
is <code class="literal">TRUE</code>, a
metadata bit will be set causing libostree to avoid automatic GC of the
deployment. However, this is really an "advisory" note; it's still possible
for e.g. older versions of libostree unaware of pinning to GC the deployment.</p>
<p>This function does nothing and returns successfully if the deployment
is already in the desired pinning state.</p>
<div class="refsect3">
<a name="ostree-sysroot-deployment-set-pinned.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody>
<tr>
<td class="parameter_name"><p>self</p></td>
<td class="parameter_description"><p>Sysroot</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>deployment</p></td>
<td class="parameter_description"><p>A deployment</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>is_pinned</p></td>
<td class="parameter_description"><p>Whether or not deployment will be automatically GC'd</p></td>
<td class="parameter_annotations"> </td>
</tr>
<tr>
<td class="parameter_name"><p>error</p></td>
<td class="parameter_description"><p>Error</p></td>
<td class="parameter_annotations"> </td>
</tr>
</tbody>
</table></div>
</div>
<p class="since">Since: 2018.3</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-sysroot-write-deployments"></a><h3>ostree_sysroot_write_deployments ()</h3> <a name="ostree-sysroot-write-deployments"></a><h3>ostree_sysroot_write_deployments ()</h3>
<pre class="programlisting"><span class="returnvalue">gboolean</span> <pre class="programlisting"><span class="returnvalue">gboolean</span>
ostree_sysroot_write_deployments (<em class="parameter"><code><a class="link" href="ostree-Root-partition-mount-point.html#OstreeSysroot" title="OstreeSysroot"><span class="type">OstreeSysroot</span></a> *self</code></em>, ostree_sysroot_write_deployments (<em class="parameter"><code><a class="link" href="ostree-Root-partition-mount-point.html#OstreeSysroot" title="OstreeSysroot"><span class="type">OstreeSysroot</span></a> *self</code></em>,

View File

@ -142,6 +142,14 @@
</tr> </tr>
<tr> <tr>
<td class="function_type"> <td class="function_type">
<span class="returnvalue">gboolean</span>
</td>
<td class="function_name">
<a class="link" href="ostree-ostree-deployment.html#ostree-deployment-is-pinned" title="ostree_deployment_is_pinned ()">ostree_deployment_is_pinned</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">
<span class="returnvalue">void</span> <span class="returnvalue">void</span>
</td> </td>
<td class="function_name"> <td class="function_name">
@ -174,6 +182,14 @@
</tr> </tr>
<tr> <tr>
<td class="function_type"> <td class="function_type">
<span class="returnvalue">void</span>
</td>
<td class="function_name">
<a class="link" href="ostree-ostree-deployment.html#ostree-deployment-origin-remove-transient-state" title="ostree_deployment_origin_remove_transient_state ()">ostree_deployment_origin_remove_transient_state</a> <span class="c_punctuation">()</span>
</td>
</tr>
<tr>
<td class="function_type">
<a class="link" href="ostree-ostree-deployment.html#OstreeDeployment" title="OstreeDeployment"><span class="returnvalue">OstreeDeployment</span></a> * <a class="link" href="ostree-ostree-deployment.html#OstreeDeployment" title="OstreeDeployment"><span class="returnvalue">OstreeDeployment</span></a> *
</td> </td>
<td class="function_name"> <td class="function_name">
@ -382,6 +398,33 @@ ostree_deployment_get_unlocked (<em class="parameter"><code><a class="link" href
</div> </div>
<hr> <hr>
<div class="refsect2"> <div class="refsect2">
<a name="ostree-deployment-is-pinned"></a><h3>ostree_deployment_is_pinned ()</h3>
<pre class="programlisting"><span class="returnvalue">gboolean</span>
ostree_deployment_is_pinned (<em class="parameter"><code><a class="link" href="ostree-ostree-deployment.html#OstreeDeployment" title="OstreeDeployment"><span class="type">OstreeDeployment</span></a> *self</code></em>);</pre>
<p>See <a class="link" href="ostree-Root-partition-mount-point.html#ostree-sysroot-deployment-set-pinned" title="ostree_sysroot_deployment_set_pinned ()"><code class="function">ostree_sysroot_deployment_set_pinned()</code></a>.</p>
<div class="refsect3">
<a name="ostree-deployment-is-pinned.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody><tr>
<td class="parameter_name"><p>self</p></td>
<td class="parameter_description"><p>Deployment</p></td>
<td class="parameter_annotations"> </td>
</tr></tbody>
</table></div>
</div>
<div class="refsect3">
<a name="ostree-deployment-is-pinned.returns"></a><h4>Returns</h4>
<p> <code class="literal">TRUE</code> if deployment will not be subject to GC</p>
</div>
<p class="since">Since: 2018.3</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-deployment-set-index"></a><h3>ostree_deployment_set_index ()</h3> <a name="ostree-deployment-set-index"></a><h3>ostree_deployment_set_index ()</h3>
<pre class="programlisting"><span class="returnvalue">void</span> <pre class="programlisting"><span class="returnvalue">void</span>
ostree_deployment_set_index (<em class="parameter"><code><a class="link" href="ostree-ostree-deployment.html#OstreeDeployment" title="OstreeDeployment"><span class="type">OstreeDeployment</span></a> *self</code></em>, ostree_deployment_set_index (<em class="parameter"><code><a class="link" href="ostree-ostree-deployment.html#OstreeDeployment" title="OstreeDeployment"><span class="type">OstreeDeployment</span></a> *self</code></em>,
@ -410,6 +453,41 @@ ostree_deployment_set_origin (<em class="parameter"><code><a class="link" href="
</div> </div>
<hr> <hr>
<div class="refsect2"> <div class="refsect2">
<a name="ostree-deployment-origin-remove-transient-state"></a><h3>ostree_deployment_origin_remove_transient_state ()</h3>
<pre class="programlisting"><span class="returnvalue">void</span>
ostree_deployment_origin_remove_transient_state
(<em class="parameter"><code><span class="type">GKeyFile</span> *origin</code></em>);</pre>
<p>The intention of an origin file is primarily describe the "inputs" that
resulted in a deployment, and it's commonly used to derive the new state. For
example, a key value (in pure libostree mode) is the "refspec". However,
libostree (or other applications) may want to store "transient" state that
should not be carried across upgrades.</p>
<p>This function just removes all members of the <code class="literal">libostree-transient</code> group.
The name of that group is available to all libostree users; best practice
would be to prefix values underneath there with a short identifier for your
software.</p>
<p>Additionally, this function will remove the <code class="literal">origin/unlocked</code> and
<code class="literal">origin/override-commit</code> members; these should be considered transient state
that should have been under an explicit group.</p>
<div class="refsect3">
<a name="ostree-deployment-origin-remove-transient-state.parameters"></a><h4>Parameters</h4>
<div class="informaltable"><table class="informaltable" width="100%" border="0">
<colgroup>
<col width="150px" class="parameters_name">
<col class="parameters_description">
<col width="200px" class="parameters_annotations">
</colgroup>
<tbody><tr>
<td class="parameter_name"><p>origin</p></td>
<td class="parameter_description"><p>An origin</p></td>
<td class="parameter_annotations"> </td>
</tr></tbody>
</table></div>
</div>
<p class="since">Since: 2018.3</p>
</div>
<hr>
<div class="refsect2">
<a name="ostree-deployment-clone"></a><h3>ostree_deployment_clone ()</h3> <a name="ostree-deployment-clone"></a><h3>ostree_deployment_clone ()</h3>
<pre class="programlisting"><a class="link" href="ostree-ostree-deployment.html#OstreeDeployment" title="OstreeDeployment"><span class="returnvalue">OstreeDeployment</span></a> * <pre class="programlisting"><a class="link" href="ostree-ostree-deployment.html#OstreeDeployment" title="OstreeDeployment"><span class="returnvalue">OstreeDeployment</span></a> *
ostree_deployment_clone (<em class="parameter"><code><a class="link" href="ostree-ostree-deployment.html#OstreeDeployment" title="OstreeDeployment"><span class="type">OstreeDeployment</span></a> *self</code></em>);</pre> ostree_deployment_clone (<em class="parameter"><code><a class="link" href="ostree-ostree-deployment.html#OstreeDeployment" title="OstreeDeployment"><span class="type">OstreeDeployment</span></a> *self</code></em>);</pre>

View File

@ -275,6 +275,7 @@
<keyword type="function" name="ostree_sysroot_deployment_set_kargs ()" link="ostree-Root-partition-mount-point.html#ostree-sysroot-deployment-set-kargs"/> <keyword type="function" name="ostree_sysroot_deployment_set_kargs ()" link="ostree-Root-partition-mount-point.html#ostree-sysroot-deployment-set-kargs"/>
<keyword type="function" name="ostree_sysroot_deployment_set_mutable ()" link="ostree-Root-partition-mount-point.html#ostree-sysroot-deployment-set-mutable"/> <keyword type="function" name="ostree_sysroot_deployment_set_mutable ()" link="ostree-Root-partition-mount-point.html#ostree-sysroot-deployment-set-mutable"/>
<keyword type="function" name="ostree_sysroot_deployment_unlock ()" link="ostree-Root-partition-mount-point.html#ostree-sysroot-deployment-unlock"/> <keyword type="function" name="ostree_sysroot_deployment_unlock ()" link="ostree-Root-partition-mount-point.html#ostree-sysroot-deployment-unlock"/>
<keyword type="function" name="ostree_sysroot_deployment_set_pinned ()" link="ostree-Root-partition-mount-point.html#ostree-sysroot-deployment-set-pinned" since="2018.3"/>
<keyword type="function" name="ostree_sysroot_write_deployments ()" link="ostree-Root-partition-mount-point.html#ostree-sysroot-write-deployments"/> <keyword type="function" name="ostree_sysroot_write_deployments ()" link="ostree-Root-partition-mount-point.html#ostree-sysroot-write-deployments"/>
<keyword type="function" name="ostree_sysroot_write_deployments_with_options ()" link="ostree-Root-partition-mount-point.html#ostree-sysroot-write-deployments-with-options"/> <keyword type="function" name="ostree_sysroot_write_deployments_with_options ()" link="ostree-Root-partition-mount-point.html#ostree-sysroot-write-deployments-with-options"/>
<keyword type="function" name="ostree_sysroot_write_origin_file ()" link="ostree-Root-partition-mount-point.html#ostree-sysroot-write-origin-file"/> <keyword type="function" name="ostree_sysroot_write_origin_file ()" link="ostree-Root-partition-mount-point.html#ostree-sysroot-write-origin-file"/>
@ -362,10 +363,12 @@
<keyword type="function" name="ostree_deployment_get_origin ()" link="ostree-ostree-deployment.html#ostree-deployment-get-origin"/> <keyword type="function" name="ostree_deployment_get_origin ()" link="ostree-ostree-deployment.html#ostree-deployment-get-origin"/>
<keyword type="function" name="ostree_deployment_get_origin_relpath ()" link="ostree-ostree-deployment.html#ostree-deployment-get-origin-relpath"/> <keyword type="function" name="ostree_deployment_get_origin_relpath ()" link="ostree-ostree-deployment.html#ostree-deployment-get-origin-relpath"/>
<keyword type="function" name="ostree_deployment_get_unlocked ()" link="ostree-ostree-deployment.html#ostree-deployment-get-unlocked"/> <keyword type="function" name="ostree_deployment_get_unlocked ()" link="ostree-ostree-deployment.html#ostree-deployment-get-unlocked"/>
<keyword type="function" name="ostree_deployment_is_pinned ()" link="ostree-ostree-deployment.html#ostree-deployment-is-pinned" since="2018.3"/>
<keyword type="function" name="ostree_deployment_set_index ()" link="ostree-ostree-deployment.html#ostree-deployment-set-index"/> <keyword type="function" name="ostree_deployment_set_index ()" link="ostree-ostree-deployment.html#ostree-deployment-set-index"/>
<keyword type="function" name="ostree_deployment_set_bootserial ()" link="ostree-ostree-deployment.html#ostree-deployment-set-bootserial"/> <keyword type="function" name="ostree_deployment_set_bootserial ()" link="ostree-ostree-deployment.html#ostree-deployment-set-bootserial"/>
<keyword type="function" name="ostree_deployment_set_bootconfig ()" link="ostree-ostree-deployment.html#ostree-deployment-set-bootconfig"/> <keyword type="function" name="ostree_deployment_set_bootconfig ()" link="ostree-ostree-deployment.html#ostree-deployment-set-bootconfig"/>
<keyword type="function" name="ostree_deployment_set_origin ()" link="ostree-ostree-deployment.html#ostree-deployment-set-origin"/> <keyword type="function" name="ostree_deployment_set_origin ()" link="ostree-ostree-deployment.html#ostree-deployment-set-origin"/>
<keyword type="function" name="ostree_deployment_origin_remove_transient_state ()" link="ostree-ostree-deployment.html#ostree-deployment-origin-remove-transient-state" since="2018.3"/>
<keyword type="function" name="ostree_deployment_clone ()" link="ostree-ostree-deployment.html#ostree-deployment-clone"/> <keyword type="function" name="ostree_deployment_clone ()" link="ostree-ostree-deployment.html#ostree-deployment-clone"/>
<keyword type="function" name="ostree_deployment_unlocked_state_to_string ()" link="ostree-ostree-deployment.html#ostree-deployment-unlocked-state-to-string"/> <keyword type="function" name="ostree_deployment_unlocked_state_to_string ()" link="ostree-ostree-deployment.html#ostree-deployment-unlocked-state-to-string"/>
<keyword type="struct" name="OstreeDeployment" link="ostree-ostree-deployment.html#OstreeDeployment"/> <keyword type="struct" name="OstreeDeployment" link="ostree-ostree-deployment.html#OstreeDeployment"/>
@ -395,6 +398,7 @@
<keyword type="constant" name="OSTREE_OBJECT_TYPE_COMMIT" link="ostree-Core-repository-independent-functions.html#OSTREE-OBJECT-TYPE-COMMIT:CAPS"/> <keyword type="constant" name="OSTREE_OBJECT_TYPE_COMMIT" link="ostree-Core-repository-independent-functions.html#OSTREE-OBJECT-TYPE-COMMIT:CAPS"/>
<keyword type="constant" name="OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT" link="ostree-Core-repository-independent-functions.html#OSTREE-OBJECT-TYPE-TOMBSTONE-COMMIT:CAPS"/> <keyword type="constant" name="OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT" link="ostree-Core-repository-independent-functions.html#OSTREE-OBJECT-TYPE-TOMBSTONE-COMMIT:CAPS"/>
<keyword type="constant" name="OSTREE_OBJECT_TYPE_COMMIT_META" link="ostree-Core-repository-independent-functions.html#OSTREE-OBJECT-TYPE-COMMIT-META:CAPS"/> <keyword type="constant" name="OSTREE_OBJECT_TYPE_COMMIT_META" link="ostree-Core-repository-independent-functions.html#OSTREE-OBJECT-TYPE-COMMIT-META:CAPS"/>
<keyword type="constant" name="OSTREE_OBJECT_TYPE_PAYLOAD_LINK" link="ostree-Core-repository-independent-functions.html#OSTREE-OBJECT-TYPE-PAYLOAD-LINK:CAPS"/>
<keyword type="constant" name="OSTREE_REPO_MODE_BARE" link="ostree-OstreeRepo.html#OSTREE-REPO-MODE-BARE:CAPS"/> <keyword type="constant" name="OSTREE_REPO_MODE_BARE" link="ostree-OstreeRepo.html#OSTREE-REPO-MODE-BARE:CAPS"/>
<keyword type="constant" name="OSTREE_REPO_MODE_ARCHIVE" link="ostree-OstreeRepo.html#OSTREE-REPO-MODE-ARCHIVE:CAPS"/> <keyword type="constant" name="OSTREE_REPO_MODE_ARCHIVE" link="ostree-OstreeRepo.html#OSTREE-REPO-MODE-ARCHIVE:CAPS"/>
<keyword type="constant" name="OSTREE_REPO_MODE_ARCHIVE_Z2" link="ostree-OstreeRepo.html#OSTREE-REPO-MODE-ARCHIVE-Z2:CAPS"/> <keyword type="constant" name="OSTREE_REPO_MODE_ARCHIVE_Z2" link="ostree-OstreeRepo.html#OSTREE-REPO-MODE-ARCHIVE-Z2:CAPS"/>

View File

@ -359,10 +359,18 @@ OSTREE_CHECK_VERSION, macro in ostree-version
</dt> </dt>
<dd></dd> <dd></dd>
<dt> <dt>
<a class="link" href="ostree-ostree-deployment.html#ostree-deployment-is-pinned" title="ostree_deployment_is_pinned ()">ostree_deployment_is_pinned</a>, function in <a class="link" href="ostree-ostree-deployment.html" title="ostree-deployment">ostree-deployment</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-ostree-deployment.html#ostree-deployment-new" title="ostree_deployment_new ()">ostree_deployment_new</a>, function in <a class="link" href="ostree-ostree-deployment.html" title="ostree-deployment">ostree-deployment</a> <a class="link" href="ostree-ostree-deployment.html#ostree-deployment-new" title="ostree_deployment_new ()">ostree_deployment_new</a>, function in <a class="link" href="ostree-ostree-deployment.html" title="ostree-deployment">ostree-deployment</a>
</dt> </dt>
<dd></dd> <dd></dd>
<dt> <dt>
<a class="link" href="ostree-ostree-deployment.html#ostree-deployment-origin-remove-transient-state" title="ostree_deployment_origin_remove_transient_state ()">ostree_deployment_origin_remove_transient_state</a>, function in <a class="link" href="ostree-ostree-deployment.html" title="ostree-deployment">ostree-deployment</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-ostree-deployment.html#ostree-deployment-set-bootconfig" title="ostree_deployment_set_bootconfig ()">ostree_deployment_set_bootconfig</a>, function in <a class="link" href="ostree-ostree-deployment.html" title="ostree-deployment">ostree-deployment</a> <a class="link" href="ostree-ostree-deployment.html#ostree-deployment-set-bootconfig" title="ostree_deployment_set_bootconfig ()">ostree_deployment_set_bootconfig</a>, function in <a class="link" href="ostree-ostree-deployment.html" title="ostree-deployment">ostree-deployment</a>
</dt> </dt>
<dd></dd> <dd></dd>
@ -1343,6 +1351,10 @@ OSTREE_RELEASE_VERSION, macro in ostree-version
</dt> </dt>
<dd></dd> <dd></dd>
<dt> <dt>
<a class="link" href="ostree-Root-partition-mount-point.html#ostree-sysroot-deployment-set-pinned" title="ostree_sysroot_deployment_set_pinned ()">ostree_sysroot_deployment_set_pinned</a>, function in <a class="link" href="ostree-Root-partition-mount-point.html" title="Root partition mount point">Root partition mount point</a>
</dt>
<dd></dd>
<dt>
<a class="link" href="ostree-Root-partition-mount-point.html#ostree-sysroot-deployment-unlock" title="ostree_sysroot_deployment_unlock ()">ostree_sysroot_deployment_unlock</a>, function in <a class="link" href="ostree-Root-partition-mount-point.html" title="Root partition mount point">Root partition mount point</a> <a class="link" href="ostree-Root-partition-mount-point.html#ostree-sysroot-deployment-unlock" title="ostree_sysroot_deployment_unlock ()">ostree_sysroot_deployment_unlock</a>, function in <a class="link" href="ostree-Root-partition-mount-point.html" title="Root partition mount point">Root partition mount point</a>
</dt> </dt>
<dd></dd> <dd></dd>

View File

@ -169,10 +169,12 @@ ostree_deployment_get_bootconfig
ostree_deployment_get_origin ostree_deployment_get_origin
ostree_deployment_get_origin_relpath ostree_deployment_get_origin_relpath
ostree_deployment_get_unlocked ostree_deployment_get_unlocked
ostree_deployment_is_pinned
ostree_deployment_set_index ostree_deployment_set_index
ostree_deployment_set_bootserial ostree_deployment_set_bootserial
ostree_deployment_set_bootconfig ostree_deployment_set_bootconfig
ostree_deployment_set_origin ostree_deployment_set_origin
ostree_deployment_origin_remove_transient_state
ostree_deployment_clone ostree_deployment_clone
ostree_deployment_unlocked_state_to_string ostree_deployment_unlocked_state_to_string
<SUBSECTION Standard> <SUBSECTION Standard>
@ -508,6 +510,7 @@ ostree_sysroot_init_osname
ostree_sysroot_deployment_set_kargs ostree_sysroot_deployment_set_kargs
ostree_sysroot_deployment_set_mutable ostree_sysroot_deployment_set_mutable
ostree_sysroot_deployment_unlock ostree_sysroot_deployment_unlock
ostree_sysroot_deployment_set_pinned
ostree_sysroot_write_deployments ostree_sysroot_write_deployments
ostree_sysroot_write_deployments_with_options ostree_sysroot_write_deployments_with_options
ostree_sysroot_write_origin_file ostree_sysroot_write_origin_file

View File

@ -1 +1 @@
2018.2 2018.4

View File

@ -180,472 +180,6 @@ _ostree_ostree() {
return 0 return 0
} }
_ostree_admin_cleanup() {
local boolean_options="
$main_boolean_options
"
local options_with_args="
--sysroot
"
local options_with_args_glob=$( __ostree_to_extglob "$options_with_args" )
case "$prev" in
--sysroot)
__ostree_compreply_dirs_only
return 0
;;
$options_with_args_glob )
return 0
;;
esac
case "$cur" in
-*)
local all_options="$boolean_options $options_with_args"
__ostree_compreply_all_options
;;
esac
return 0
}
_ostree_admin_config_diff() {
local boolean_options="
$main_boolean_options
"
local options_with_args="
--os
--sysroot
"
local options_with_args_glob=$( __ostree_to_extglob "$options_with_args" )
case "$prev" in
--os)
__ostree_compreply_oses
return 0
;;
--sysroot)
__ostree_compreply_dirs_only
return 0
;;
$options_with_args_glob )
return 0
;;
esac
case "$cur" in
-*)
local all_options="$boolean_options $options_with_args"
__ostree_compreply_all_options
;;
esac
return 0
}
_ostree_admin_deploy() {
local boolean_options="
$main_boolean_options
--retain
--retain-pending
--retain-rollback
--not-as-default
--karg-proc-cmdline
"
local options_with_args="
--karg
--karg-append
--origin-file
--os
--sysroot
"
local options_with_args_glob=$( __ostree_to_extglob "$options_with_args" )
case "$prev" in
--origin-file)
__ostree_compreply_all_files
return 0
;;
--os)
__ostree_compreply_oses
return 0
;;
--sysroot)
__ostree_compreply_dirs_only
return 0
;;
$options_with_args_glob )
return 0
;;
esac
case "$cur" in
-*)
local all_options="$boolean_options $options_with_args"
__ostree_compreply_all_options
;;
esac
return 0
}
_ostree_admin_init_fs() {
local boolean_options="
$main_boolean_options
"
local options_with_args="
--sysroot
"
local options_with_args_glob=$( __ostree_to_extglob "$options_with_args" )
case "$prev" in
--sysroot)
__ostree_compreply_dirs_only
return 0
;;
$options_with_args_glob )
return 0
;;
esac
case "$cur" in
-*)
local all_options="$boolean_options $options_with_args"
__ostree_compreply_all_options
;;
esac
return 0
}
_ostree_admin_instutil() {
local boolean_options="
$main_boolean_options
"
local options_with_args="
--sysroot
"
local options_with_args_glob=$( __ostree_to_extglob "$options_with_args" )
case "$prev" in
--sysroot)
__ostree_compreply_dirs_only
return 0
;;
$options_with_args_glob )
return 0
;;
esac
case "$cur" in
-*)
local all_options="$boolean_options $options_with_args"
__ostree_compreply_all_options
;;
*)
local argpos=$( __ostree_pos_first_nonflag $( __ostree_to_alternatives "$options_with_args" ) )
if [ $cword -eq $argpos ]; then
local instutil_commands="
grub2-generate
selinux-ensure-labeled
set-kargs
"
COMPREPLY=( $( compgen -W "$instutil_commands" -- "$cur" ) )
fi
;;
esac
return 0
}
_ostree_admin_os_init() {
local boolean_options="
$main_boolean_options
"
local options_with_args="
--sysroot
"
local options_with_args_glob=$( __ostree_to_extglob "$options_with_args" )
case "$prev" in
--sysroot)
__ostree_compreply_dirs_only
return 0
;;
$options_with_args_glob )
return 0
;;
esac
case "$cur" in
-*)
local all_options="$boolean_options $options_with_args"
__ostree_compreply_all_options
;;
esac
return 0
}
_ostree_admin_set_origin() {
local boolean_options="
$main_boolean_options
"
local options_with_args="
--index
--set -s
--sysroot
"
local options_with_args_glob=$( __ostree_to_extglob "$options_with_args" )
case "$prev" in
--sysroot)
__ostree_compreply_dirs_only
return 0
;;
$options_with_args_glob )
return 0
;;
esac
case "$cur" in
-*)
local all_options="$boolean_options $options_with_args"
__ostree_compreply_all_options
;;
*)
local argpos=$( __ostree_pos_first_nonflag $( __ostree_to_alternatives "$options_with_args" ) )
if [ $cword -eq $argpos ]; then
__ostree_compreply_remotes
fi
;;
esac
return 0
}
_ostree_admin_status() {
local boolean_options="
$main_boolean_options
"
local options_with_args="
--sysroot
"
local options_with_args_glob=$( __ostree_to_extglob "$options_with_args" )
case "$prev" in
--sysroot)
__ostree_compreply_dirs_only
return 0
;;
$options_with_args_glob )
return 0
;;
esac
case "$cur" in
-*)
local all_options="$boolean_options $options_with_args"
__ostree_compreply_all_options
;;
esac
return 0
}
_ostree_admin_switch() {
local boolean_options="
$main_boolean_options
"
local options_with_args="
--os
--reboot -r
--sysroot
"
local options_with_args_glob=$( __ostree_to_extglob "$options_with_args" )
case "$prev" in
--os)
__ostree_compreply_oses
return 0
;;
--sysroot)
__ostree_compreply_dirs_only
return 0
;;
$options_with_args_glob )
return 0
;;
esac
case "$cur" in
-*)
local all_options="$boolean_options $options_with_args"
__ostree_compreply_all_options
;;
*)
local argpos=$( __ostree_pos_first_nonflag $( __ostree_to_alternatives "$options_with_args" ) )
if [ $cword -eq $argpos ]; then
__ostree_compreply_refs
fi
esac
return 0
}
_ostree_admin_undeploy() {
local boolean_options="
$main_boolean_options
"
local options_with_args="
--sysroot
"
local options_with_args_glob=$( __ostree_to_extglob "$options_with_args" )
case "$prev" in
--sysroot)
__ostree_compreply_dirs_only
return 0
;;
$options_with_args_glob )
return 0
;;
esac
case "$cur" in
-*)
local all_options="$boolean_options $options_with_args"
__ostree_compreply_all_options
;;
esac
return 0
}
_ostree_admin_unlock() {
local boolean_options="
$main_boolean_options
--hotfix
"
local options_with_args="
--sysroot
"
local options_with_args_glob=$( __ostree_to_extglob "$options_with_args" )
case "$prev" in
--sysroot)
__ostree_compreply_dirs_only
return 0
;;
$options_with_args_glob )
return 0
;;
esac
case "$cur" in
-*)
local all_options="$boolean_options $options_with_args"
__ostree_compreply_all_options
;;
esac
return 0
}
_ostree_admin_upgrade() {
local boolean_options="
$main_boolean_options
--allow-downgrade
--deploy-only
--pull-only
--reboot -r
"
local options_with_args="
--os
--override-commit
--sysroot
"
local options_with_args_glob=$( __ostree_to_extglob "$options_with_args" )
case "$prev" in
--override-commit)
__ostree_compreply_commits
return 0
;;
--sysroot)
__ostree_compreply_dirs_only
return 0
;;
$options_with_args_glob )
return 0
;;
esac
case "$cur" in
-*)
local all_options="$boolean_options $options_with_args"
__ostree_compreply_all_options
;;
esac
return 0
}
_ostree_admin() {
local subcommands="
cleanup
config-diff
deploy
init-fs
instutil
os-init
set-origin
status
switch
undeploy
unlock
upgrade
"
__ostree_subcommands "$subcommands" && return 0
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "$main_boolean_options" -- "$cur" ) )
;;
*)
COMPREPLY=( $( compgen -W "$subcommands" -- "$cur" ) )
;;
esac
return 0
}
_ostree_cat() { _ostree_cat() {
local boolean_options=" local boolean_options="
$main_boolean_options $main_boolean_options

View File

@ -12,6 +12,7 @@ AC_CHECK_DECLS([
#include <sched.h> #include <sched.h>
#include <linux/loop.h> #include <linux/loop.h>
#include <linux/random.h> #include <linux/random.h>
#include <sys/mman.h>
]]) ]])
AC_ARG_ENABLE(otmpfile, AC_ARG_ENABLE(otmpfile,

View File

@ -79,7 +79,7 @@
/* Define if we have libsoup client certs */ /* Define if we have libsoup client certs */
#undef HAVE_LIBSOUP_CLIENT_CERTS #undef HAVE_LIBSOUP_CLIENT_CERTS
/* Define if we have libsystemd */ /* Define if we have libsystemd.pc */
#undef HAVE_LIBSYSTEMD #undef HAVE_LIBSYSTEMD
/* Define to 1 if you have the <memory.h> header file. */ /* Define to 1 if you have the <memory.h> header file. */

108
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 libostree 2018.2. # Generated by GNU Autoconf 2.69 for libostree 2018.4.
# #
# 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='libostree' PACKAGE_NAME='libostree'
PACKAGE_TARNAME='libostree' PACKAGE_TARNAME='libostree'
PACKAGE_VERSION='2018.2' PACKAGE_VERSION='2018.4'
PACKAGE_STRING='libostree 2018.2' PACKAGE_STRING='libostree 2018.4'
PACKAGE_BUGREPORT='walters@verbum.org' PACKAGE_BUGREPORT='walters@verbum.org'
PACKAGE_URL='' PACKAGE_URL=''
@ -948,6 +948,7 @@ with_libmount
enable_rofiles_fuse enable_rofiles_fuse
with_dracut with_dracut
with_mkinitcpio with_mkinitcpio
with_libsystemd
with_systemdsystemunitdir with_systemdsystemunitdir
with_systemdsystemgeneratordir with_systemdsystemgeneratordir
with_builtin_grub2_mkconfig with_builtin_grub2_mkconfig
@ -1541,7 +1542,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 libostree 2018.2 to adapt to many kinds of systems. \`configure' configures libostree 2018.4 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1611,7 +1612,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 libostree 2018.2:";; short | recursive ) echo "Configuration of libostree 2018.4:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@ -1689,6 +1690,7 @@ Optional Packages:
--without-libmount Do not use libmount --without-libmount Do not use libmount
--with-dracut Install dracut module (default: no) --with-dracut Install dracut module (default: no)
--with-mkinitcpio Install mkinitcpio module (default: no) --with-mkinitcpio Install mkinitcpio module (default: no)
--without-libsystemd Do not use libsystemd
--with-systemdsystemunitdir=DIR --with-systemdsystemunitdir=DIR
Directory for systemd service files Directory for systemd service files
--with-systemdsystemgeneratordir=DIR --with-systemdsystemgeneratordir=DIR
@ -1853,7 +1855,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
libostree configure 2018.2 libostree configure 2018.4
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.
@ -2325,7 +2327,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 libostree $as_me 2018.2, which was It was created by libostree $as_me 2018.4, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@ $ $0 $@
@ -3193,7 +3195,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE='libostree' PACKAGE='libostree'
VERSION='2018.2' VERSION='2018.4'
# Some tools Automake needs. # Some tools Automake needs.
@ -5927,9 +5929,9 @@ test -n "$YACC" || YACC="yacc"
YEAR_VERSION=2018 YEAR_VERSION=2018
RELEASE_VERSION=2 RELEASE_VERSION=4
PACKAGE_VERSION=2018.2 PACKAGE_VERSION=2018.4
if echo "$CFLAGS" | grep -q -E -e '-Werror($| )'; then : if echo "$CFLAGS" | grep -q -E -e '-Werror($| )'; then :
@ -13781,6 +13783,7 @@ ac_fn_c_check_decl "$LINENO" "renameat2" "ac_cv_have_decl_renameat2" "
#include <sched.h> #include <sched.h>
#include <linux/loop.h> #include <linux/loop.h>
#include <linux/random.h> #include <linux/random.h>
#include <sys/mman.h>
" "
if test "x$ac_cv_have_decl_renameat2" = xyes; then : if test "x$ac_cv_have_decl_renameat2" = xyes; then :
@ -13800,6 +13803,7 @@ ac_fn_c_check_decl "$LINENO" "memfd_create" "ac_cv_have_decl_memfd_create" "
#include <sched.h> #include <sched.h>
#include <linux/loop.h> #include <linux/loop.h>
#include <linux/random.h> #include <linux/random.h>
#include <sys/mman.h>
" "
if test "x$ac_cv_have_decl_memfd_create" = xyes; then : if test "x$ac_cv_have_decl_memfd_create" = xyes; then :
@ -13819,6 +13823,7 @@ ac_fn_c_check_decl "$LINENO" "copy_file_range" "ac_cv_have_decl_copy_file_range"
#include <sched.h> #include <sched.h>
#include <linux/loop.h> #include <linux/loop.h>
#include <linux/random.h> #include <linux/random.h>
#include <sys/mman.h>
" "
if test "x$ac_cv_have_decl_copy_file_range" = xyes; then : if test "x$ac_cv_have_decl_copy_file_range" = xyes; then :
@ -17335,6 +17340,41 @@ fi
# Check whether --with-libsystemd was given.
if test "${with_libsystemd+set}" = set; then :
withval=$with_libsystemd; :
else
with_libsystemd=maybe
fi
if test x$with_libsystemd != xno ; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libsystemd" >&5
$as_echo_n "checking for libsystemd... " >&6; }
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsystemd\""; } >&5
($PKG_CONFIG --exists --print-errors "libsystemd") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
have_libsystemd=yes
else
have_libsystemd=no
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_libsystemd" >&5
$as_echo "$have_libsystemd" >&6; }
if test x$have_libsystemd = xno && test x$with_libsystemd != xmaybe ; then :
as_fn_error $? "libsystemd is enabled but could not be found" "$LINENO" 5
fi
if test x$have_libsystemd = xyes; then :
$as_echo "#define HAVE_LIBSYSTEMD 1" >>confdefs.h
pkg_failed=no pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSYSTEMD" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSYSTEMD" >&5
$as_echo_n "checking for LIBSYSTEMD... " >&6; } $as_echo_n "checking for LIBSYSTEMD... " >&6; }
@ -17393,19 +17433,50 @@ fi
# Put the nasty error message in config.log where it belongs # Put the nasty error message in config.log where it belongs
echo "$LIBSYSTEMD_PKG_ERRORS" >&5 echo "$LIBSYSTEMD_PKG_ERRORS" >&5
have_libsystemd=no as_fn_error $? "Package requirements (libsystemd) were not met:
$LIBSYSTEMD_PKG_ERRORS
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
Alternatively, you may set the environment variables LIBSYSTEMD_CFLAGS
and LIBSYSTEMD_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details." "$LINENO" 5
elif test $pkg_failed = untried; then elif test $pkg_failed = untried; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; } $as_echo "no" >&6; }
have_libsystemd=no { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.
Alternatively, you may set the environment variables LIBSYSTEMD_CFLAGS
and LIBSYSTEMD_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
To get pkg-config, see <http://pkg-config.freedesktop.org/>.
See \`config.log' for more details" "$LINENO" 5; }
else else
LIBSYSTEMD_CFLAGS=$pkg_cv_LIBSYSTEMD_CFLAGS LIBSYSTEMD_CFLAGS=$pkg_cv_LIBSYSTEMD_CFLAGS
LIBSYSTEMD_LIBS=$pkg_cv_LIBSYSTEMD_LIBS LIBSYSTEMD_LIBS=$pkg_cv_LIBSYSTEMD_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; } $as_echo "yes" >&6; }
have_libsystemd=yes
fi fi
if test x$have_libsystemd = xyes; then with_libsystemd=yes
else
with_libsystemd=no
fi
else
with_libsystemd=no
fi
if test $with_libsystemd != no; then
BUILDOPT_LIBSYSTEMD_TRUE= BUILDOPT_LIBSYSTEMD_TRUE=
BUILDOPT_LIBSYSTEMD_FALSE='#' BUILDOPT_LIBSYSTEMD_FALSE='#'
else else
@ -17413,11 +17484,6 @@ else
BUILDOPT_LIBSYSTEMD_FALSE= BUILDOPT_LIBSYSTEMD_FALSE=
fi fi
if test -z "$BUILDOPT_LIBSYSTEMD_TRUE"; then :
$as_echo "#define HAVE_LIBSYSTEMD 1" >>confdefs.h
fi
if test "x$have_libsystemd" = "xyes"; then : if test "x$have_libsystemd" = "xyes"; then :
@ -18381,7 +18447,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 libostree $as_me 2018.2, which was This file was extended by libostree $as_me 2018.4, 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
@ -18447,7 +18513,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="\\
libostree config.status 2018.2 libostree config.status 2018.4
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

@ -4,7 +4,7 @@ dnl update libostree-released.sym from libostree-devel.sym, and update the check
dnl in test-symbols.sh, and also set is_release_build=yes below. Then make dnl in test-symbols.sh, and also set is_release_build=yes below. Then make
dnl another post-release commit to bump the version, and set is_release_build=no. dnl another post-release commit to bump the version, and set is_release_build=no.
m4_define([year_version], [2018]) m4_define([year_version], [2018])
m4_define([release_version], [2]) m4_define([release_version], [4])
m4_define([package_version], [year_version.release_version]) m4_define([package_version], [year_version.release_version])
AC_INIT([libostree], [package_version], [walters@verbum.org]) AC_INIT([libostree], [package_version], [walters@verbum.org])
is_release_build=yes is_release_build=yes
@ -469,10 +469,26 @@ AC_ARG_WITH(mkinitcpio,
AM_CONDITIONAL(BUILDOPT_MKINITCPIO, test x$with_mkinitcpio = xyes) AM_CONDITIONAL(BUILDOPT_MKINITCPIO, test x$with_mkinitcpio = xyes)
dnl We have separate checks for libsystemd and the unit dir for historical reasons dnl We have separate checks for libsystemd and the unit dir for historical reasons
PKG_CHECK_MODULES([LIBSYSTEMD], [libsystemd], [have_libsystemd=yes], [have_libsystemd=no]) AC_ARG_WITH(libsystemd,
AM_CONDITIONAL(BUILDOPT_LIBSYSTEMD, test x$have_libsystemd = xyes) AS_HELP_STRING([--without-libsystemd], [Do not use libsystemd]),
AM_COND_IF(BUILDOPT_LIBSYSTEMD, :, with_libsystemd=maybe)
AC_DEFINE([HAVE_LIBSYSTEMD], 1, [Define if we have libsystemd]))
AS_IF([ test x$with_libsystemd != xno ], [
AC_MSG_CHECKING([for libsystemd])
PKG_CHECK_EXISTS(libsystemd, have_libsystemd=yes, have_libsystemd=no)
AC_MSG_RESULT([$have_libsystemd])
AS_IF([ test x$have_libsystemd = xno && test x$with_libsystemd != xmaybe ], [
AC_MSG_ERROR([libsystemd is enabled but could not be found])
])
AS_IF([ test x$have_libsystemd = xyes], [
AC_DEFINE([HAVE_LIBSYSTEMD], 1, [Define if we have libsystemd.pc])
PKG_CHECK_MODULES([LIBSYSTEMD], [libsystemd])
with_libsystemd=yes
], [
with_libsystemd=no
])
], [ with_libsystemd=no ])
AM_CONDITIONAL(BUILDOPT_LIBSYSTEMD, test $with_libsystemd != no)
AS_IF([test "x$have_libsystemd" = "xyes"], [ AS_IF([test "x$have_libsystemd" = "xyes"], [
with_systemd=yes with_systemd=yes

View File

@ -46,8 +46,8 @@
static gboolean locked; static gboolean locked;
static guint64 last_update_ms; /* monotonic time in millis we last updated */ static guint64 last_update_ms; /* monotonic time in millis we last updated */
static gboolean gboolean
stdout_is_tty (void) glnx_stdout_is_tty (void)
{ {
static gsize initialized = 0; static gsize initialized = 0;
static gboolean stdout_is_tty_v; static gboolean stdout_is_tty_v;
@ -156,7 +156,7 @@ glnx_console_lock (GLnxConsoleRef *console)
g_return_if_fail (!locked); g_return_if_fail (!locked);
g_return_if_fail (!console->locked); g_return_if_fail (!console->locked);
console->is_tty = stdout_is_tty (); console->is_tty = glnx_stdout_is_tty ();
locked = console->locked = TRUE; locked = console->locked = TRUE;
@ -199,7 +199,7 @@ text_percent_internal (const char *text,
if (percentage != 100) if (percentage != 100)
{ {
const guint64 diff_ms = current_ms - last_update_ms; const guint64 diff_ms = current_ms - last_update_ms;
if (stdout_is_tty ()) if (glnx_stdout_is_tty ())
{ {
if (diff_ms < (1000/MAX_TTY_UPDATE_HZ)) if (diff_ms < (1000/MAX_TTY_UPDATE_HZ))
return; return;
@ -224,7 +224,7 @@ text_percent_internal (const char *text,
const guint input_textlen = text ? strlen (text) : 0; const guint input_textlen = text ? strlen (text) : 0;
if (!stdout_is_tty ()) if (!glnx_stdout_is_tty ())
{ {
if (text) if (text)
fprintf (stdout, "%s", text); fprintf (stdout, "%s", text);

View File

@ -31,6 +31,8 @@ struct GLnxConsoleRef {
typedef struct GLnxConsoleRef GLnxConsoleRef; typedef struct GLnxConsoleRef GLnxConsoleRef;
gboolean glnx_stdout_is_tty (void);
void glnx_console_lock (GLnxConsoleRef *ref); void glnx_console_lock (GLnxConsoleRef *ref);
void glnx_console_text (const char *text); void glnx_console_text (const char *text);

View File

@ -12,6 +12,7 @@ AC_CHECK_DECLS([
#include <sched.h> #include <sched.h>
#include <linux/loop.h> #include <linux/loop.h>
#include <linux/random.h> #include <linux/random.h>
#include <sys/mman.h>
]]) ]])
AC_ARG_ENABLE(otmpfile, AC_ARG_ENABLE(otmpfile,

82
man/ostree-admin-pin.xml Normal file
View File

@ -0,0 +1,82 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
Copyright 2018 Red Hat
SPDX-License-Identifier: LGPL-2.0+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
-->
<refentry id="ostree">
<refentryinfo>
<title>ostree admin pin</title>
<productname>OSTree</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Colin</firstname>
<surname>Walters</surname>
<email>walters@verbum.org</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>ostree admin pin</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>ostree-admin-pin</refname>
<refpurpose>Explicitly retain deployment at a given index</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>ostree admin pin</command> <arg choice="req">INDEX</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
Ensures the deployment at <literal>INDEX</literal>, will not be garbage
collected by default. This is termed "pinning". If the
<literal>-u</literal> option is provided, undoes a pinning operation.
</para>
</refsect1>
<refsect1>
<title>Options</title>
<variablelist>
<varlistentry>
<term><option>--unpin</option>,<option>-u</option></term>
<listitem><para>
Undoes a pinning operation.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
</refentry>

View File

@ -1,133 +0,0 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
Copyright 2018 Matthew Leeds <matthew.leeds@endlessm.com>
SPDX-License-Identifier: LGPL-2.0+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
-->
<refentry id="ostree">
<refentryinfo>
<title>ostree find-remotes</title>
<productname>OSTree</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Matthew</firstname>
<surname>Leeds</surname>
<email>matthew.leeds@endlessm.com</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>ostree find-remotes</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>ostree-find-remotes</refname>
<refpurpose>Find remotes to serve the given refs</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>ostree find-remotes</command> <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="req">COLLECTION-ID</arg> <arg choice="req">REF</arg> <arg choice="opt" rep="repeat">COLLECTION-ID REF</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<!-- FIXME: Reword this when no longer in experimental -->
<para>
OSTree has the ability do pulls not just from configured remote
servers but also from peer computers on the LAN and from mounted
filesystems such as USB drives. Currently this requires compiling
OSTree with experimental API enabled, and it requires the use of
collection IDs and GPG verification.
</para>
<para>
The <command>find-remotes</command> command searches for remotes
which claim to provide one or more of the given COLLECTION-ID REF
pairs and prints information about them, with remotes sorted by
latency (Mounts > LAN > Internet). By default, OSTree searches for
remotes in configuration files, on mounted filesystems (in a
well-known location), and on the LAN using Avahi. Searching for LAN
remotes requires OSTree to have been compiled with Avahi support,
and it requires an Avahi daemon to be running. You can override the
default set of finders (sources for remotes) using the
<option>--finders</option> option documented below.
</para>
</refsect1>
<refsect1>
<title>Options</title>
<variablelist>
<varlistentry>
<term><option>--disable-fsync</option></term>
<listitem><para>
Do not invoke fsync().
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--finders</option>=FINDERS</term>
<listitem><para>
Use the specified comma separated list of finders rather than
the default set. Possible values: <literal>config</literal>,
<literal>lan</literal>, and <literal>mount</literal> (or any
combination thereof).
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--pull</option></term>
<listitem><para>
Pull the most recent commit found for each ref.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Example</title>
<para><command>$ ostree find-remotes --finders=mount,lan com.exampleos.Os exampleos/x86_64/standard</command></para>
<programlisting>
Result 0: http://10.0.64.202:43381/0
- Finder: OstreeRepoFinderAvahi
- Keyring: exampleos.trustedkeys.gpg
- Priority: 60
- Summary last modified: 2018-01-12T19:00:28Z
- Refs:
- (com.exampleos.Os, exampleos/x86_64/standard) = c91acd964b3fda561b87bfb7f7c80e36220d76b567f0ce90c0e60742ef33c360
1/1 refs were found.
</programlisting>
</refsect1>
</refentry>

View File

@ -114,8 +114,12 @@ Boston, MA 02111-1307, USA.
<term><option>--static-deltas-only</option>=DEPTH</term> <term><option>--static-deltas-only</option>=DEPTH</term>
<listitem><para> <listitem><para>
Change the behaviour of --keep-younger-than and --delete-commit to prune only This option may currently <emphasis>only</emphasis> be used in combination with
the static deltas files. <option>--delete-commit</option>. Previous versions of ostree silently accepted
the option without that, and ignored it. However, there are desired use
cases for pruning just static deltas (while retaining the commits), and it's
likely at some point this option will be supported for use cases outside of just
<option>--delete-commit</option>.
</para></listitem> </para></listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>

View File

@ -145,6 +145,13 @@ Boston, MA 02111-1307, USA.
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>payload-link-threshold</varname></term>
<listitem><para>An integer value that specifies a minimum file size for creating
a payload link. By default it is disabled.
</para></listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect1> </refsect1>

View File

@ -18,6 +18,8 @@
***/ ***/
/* Add new symbols here. Release commits should copy this section into -released.sym. */ /* Add new symbols here. Release commits should copy this section into -released.sym. */
LIBOSTREE_2018.5 {
} LIBOSTREE_2018.3;
/* Stub section for the stable release *after* this development one; don't /* Stub section for the stable release *after* this development one; don't
* edit this other than to update the last number. This is just a copy/paste * edit this other than to update the last number. This is just a copy/paste

View File

@ -458,6 +458,12 @@ LIBOSTREE_2018.2 {
ostree_commit_get_content_checksum; ostree_commit_get_content_checksum;
} LIBOSTREE_2018.1; } LIBOSTREE_2018.1;
LIBOSTREE_2018.3 {
ostree_deployment_origin_remove_transient_state;
ostree_sysroot_deployment_set_pinned;
ostree_deployment_is_pinned;
} LIBOSTREE_2018.2;
/* NOTE: Only add more content here in release commits! See the /* NOTE: Only add more content here in release commits! See the
* comments at the top of this file. * comments at the top of this file.
*/ */

View File

@ -1239,6 +1239,8 @@ ostree_object_type_to_string (OstreeObjectType objtype)
return "tombstone-commit"; return "tombstone-commit";
case OSTREE_OBJECT_TYPE_COMMIT_META: case OSTREE_OBJECT_TYPE_COMMIT_META:
return "commitmeta"; return "commitmeta";
case OSTREE_OBJECT_TYPE_PAYLOAD_LINK:
return "payload-link";
default: default:
g_assert_not_reached (); g_assert_not_reached ();
return NULL; return NULL;
@ -1266,6 +1268,8 @@ ostree_object_type_from_string (const char *str)
return OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT; return OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT;
else if (!strcmp (str, "commitmeta")) else if (!strcmp (str, "commitmeta"))
return OSTREE_OBJECT_TYPE_COMMIT_META; return OSTREE_OBJECT_TYPE_COMMIT_META;
else if (!strcmp (str, "payload-link"))
return OSTREE_OBJECT_TYPE_PAYLOAD_LINK;
g_assert_not_reached (); g_assert_not_reached ();
return 0; return 0;
} }
@ -2122,6 +2126,7 @@ _ostree_validate_structureof_metadata (OstreeObjectType objtype,
break; break;
case OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT: case OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT:
case OSTREE_OBJECT_TYPE_COMMIT_META: case OSTREE_OBJECT_TYPE_COMMIT_META:
case OSTREE_OBJECT_TYPE_PAYLOAD_LINK:
/* TODO */ /* TODO */
break; break;
case OSTREE_OBJECT_TYPE_FILE: case OSTREE_OBJECT_TYPE_FILE:

View File

@ -68,6 +68,7 @@ G_BEGIN_DECLS
* @OSTREE_OBJECT_TYPE_COMMIT: Toplevel object, refers to tree and dirmeta for root * @OSTREE_OBJECT_TYPE_COMMIT: Toplevel object, refers to tree and dirmeta for root
* @OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT: Toplevel object, refers to a deleted commit * @OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT: Toplevel object, refers to a deleted commit
* @OSTREE_OBJECT_TYPE_COMMIT_META: Detached metadata for a commit * @OSTREE_OBJECT_TYPE_COMMIT_META: Detached metadata for a commit
* @OSTREE_OBJECT_TYPE_PAYLOAD_LINK: Symlink to a .file given its checksum on the payload only.
* *
* Enumeration for core object types; %OSTREE_OBJECT_TYPE_FILE is for * Enumeration for core object types; %OSTREE_OBJECT_TYPE_FILE is for
* content, the other types are metadata. * content, the other types are metadata.
@ -79,6 +80,7 @@ typedef enum {
OSTREE_OBJECT_TYPE_COMMIT = 4, /* .commit */ OSTREE_OBJECT_TYPE_COMMIT = 4, /* .commit */
OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT = 5, /* .commit-tombstone */ OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT = 5, /* .commit-tombstone */
OSTREE_OBJECT_TYPE_COMMIT_META = 6, /* .commitmeta */ OSTREE_OBJECT_TYPE_COMMIT_META = 6, /* .commitmeta */
OSTREE_OBJECT_TYPE_PAYLOAD_LINK = 7, /* .payload-link */
} OstreeObjectType; } OstreeObjectType;
/** /**
@ -94,7 +96,7 @@ typedef enum {
* *
* Last valid object type; use this to validate ranges. * Last valid object type; use this to validate ranges.
*/ */
#define OSTREE_OBJECT_TYPE_LAST OSTREE_OBJECT_TYPE_COMMIT_META #define OSTREE_OBJECT_TYPE_LAST OSTREE_OBJECT_TYPE_PAYLOAD_LINK
/** /**
* OSTREE_DIRMETA_GVARIANT_FORMAT: * OSTREE_DIRMETA_GVARIANT_FORMAT:

View File

@ -121,6 +121,35 @@ ostree_deployment_set_origin (OstreeDeployment *self, GKeyFile *origin)
self->origin = g_key_file_ref (origin); self->origin = g_key_file_ref (origin);
} }
/**
* ostree_deployment_origin_remove_transient_state:
* @origin: An origin
*
* The intention of an origin file is primarily describe the "inputs" that
* resulted in a deployment, and it's commonly used to derive the new state. For
* example, a key value (in pure libostree mode) is the "refspec". However,
* libostree (or other applications) may want to store "transient" state that
* should not be carried across upgrades.
*
* This function just removes all members of the `libostree-transient` group.
* The name of that group is available to all libostree users; best practice
* would be to prefix values underneath there with a short identifier for your
* software.
*
* Additionally, this function will remove the `origin/unlocked` and
* `origin/override-commit` members; these should be considered transient state
* that should have been under an explicit group.
*
* Since: 2018.3
*/
void
ostree_deployment_origin_remove_transient_state (GKeyFile *origin)
{
g_key_file_remove_group (origin, OSTREE_ORIGIN_TRANSIENT_GROUP, NULL);
g_key_file_remove_key (origin, "origin", "override-commit", NULL);
g_key_file_remove_key (origin, "origin", "unlocked", NULL);
}
void void
_ostree_deployment_set_bootcsum (OstreeDeployment *self, _ostree_deployment_set_bootcsum (OstreeDeployment *self,
const char *bootcsum) const char *bootcsum)
@ -293,3 +322,20 @@ ostree_deployment_get_unlocked (OstreeDeployment *self)
{ {
return self->unlocked; return self->unlocked;
} }
/**
* ostree_deployment_is_pinned:
* @self: Deployment
*
* See ostree_sysroot_deployment_set_pinned().
*
* Returns: `TRUE` if deployment will not be subject to GC
* Since: 2018.3
*/
gboolean
ostree_deployment_is_pinned (OstreeDeployment *self)
{
if (!self->origin)
return FALSE;
return g_key_file_get_boolean (self->origin, OSTREE_ORIGIN_TRANSIENT_GROUP, "pinned", NULL);
}

View File

@ -27,6 +27,17 @@ G_BEGIN_DECLS
#define OSTREE_DEPLOYMENT(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), OSTREE_TYPE_DEPLOYMENT, OstreeDeployment)) #define OSTREE_DEPLOYMENT(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), OSTREE_TYPE_DEPLOYMENT, OstreeDeployment))
#define OSTREE_IS_DEPLOYMENT(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), OSTREE_TYPE_DEPLOYMENT)) #define OSTREE_IS_DEPLOYMENT(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), OSTREE_TYPE_DEPLOYMENT))
/**
* OSTREE_ORIGIN_TRANSIENT_GROUP:
*
* The name of a `GKeyFile` group for data that should not
* be carried across upgrades. For more information,
* see ostree_deployment_origin_remove_transient_state().
*
* Since: 2018.3
*/
#define OSTREE_ORIGIN_TRANSIENT_GROUP "libostree-transient"
typedef struct _OstreeDeployment OstreeDeployment; typedef struct _OstreeDeployment OstreeDeployment;
_OSTREE_PUBLIC _OSTREE_PUBLIC
@ -62,6 +73,10 @@ OstreeBootconfigParser *ostree_deployment_get_bootconfig (OstreeDeployment *self
_OSTREE_PUBLIC _OSTREE_PUBLIC
GKeyFile *ostree_deployment_get_origin (OstreeDeployment *self); GKeyFile *ostree_deployment_get_origin (OstreeDeployment *self);
_OSTREE_PUBLIC
gboolean ostree_deployment_is_pinned (OstreeDeployment *self);
_OSTREE_PUBLIC _OSTREE_PUBLIC
void ostree_deployment_set_index (OstreeDeployment *self, int index); void ostree_deployment_set_index (OstreeDeployment *self, int index);
_OSTREE_PUBLIC _OSTREE_PUBLIC
@ -71,6 +86,9 @@ void ostree_deployment_set_bootconfig (OstreeDeployment *self, OstreeBootconfigP
_OSTREE_PUBLIC _OSTREE_PUBLIC
void ostree_deployment_set_origin (OstreeDeployment *self, GKeyFile *origin); void ostree_deployment_set_origin (OstreeDeployment *self, GKeyFile *origin);
_OSTREE_PUBLIC
void ostree_deployment_origin_remove_transient_state (GKeyFile *origin);
_OSTREE_PUBLIC _OSTREE_PUBLIC
OstreeDeployment *ostree_deployment_clone (OstreeDeployment *self); OstreeDeployment *ostree_deployment_clone (OstreeDeployment *self);

View File

@ -77,6 +77,7 @@ struct OstreeFetcher
char *proxy; char *proxy;
struct curl_slist *extra_headers; struct curl_slist *extra_headers;
int tmpdir_dfd; int tmpdir_dfd;
char *custom_user_agent;
GMainContext *mainctx; GMainContext *mainctx;
CURLM *multi; CURLM *multi;
@ -180,6 +181,7 @@ _ostree_fetcher_finalize (GObject *object)
g_clear_pointer (&self->timer_event, (GDestroyNotify)destroy_and_unref_source); g_clear_pointer (&self->timer_event, (GDestroyNotify)destroy_and_unref_source);
if (self->mainctx) if (self->mainctx)
g_main_context_unref (self->mainctx); g_main_context_unref (self->mainctx);
g_clear_pointer (&self->custom_user_agent, (GDestroyNotify)g_free);
G_OBJECT_CLASS (_ostree_fetcher_parent_class)->finalize (object); G_OBJECT_CLASS (_ostree_fetcher_parent_class)->finalize (object);
} }
@ -676,6 +678,18 @@ _ostree_fetcher_set_extra_headers (OstreeFetcher *self,
} }
} }
void
_ostree_fetcher_set_extra_user_agent (OstreeFetcher *self,
const char *extra_user_agent)
{
g_clear_pointer (&self->custom_user_agent, (GDestroyNotify)g_free);
if (extra_user_agent)
{
self->custom_user_agent =
g_strdup_printf ("%s %s", OSTREE_FETCHER_USERAGENT_STRING, extra_user_agent);
}
}
/* Re-bind all of the outstanding curl items to our new main context */ /* Re-bind all of the outstanding curl items to our new main context */
static void static void
adopt_steal_mainctx (OstreeFetcher *self, adopt_steal_mainctx (OstreeFetcher *self,
@ -716,7 +730,8 @@ initiate_next_curl_request (FetcherRequest *req,
curl_easy_setopt (req->easy, CURLOPT_URL, uri); curl_easy_setopt (req->easy, CURLOPT_URL, uri);
} }
curl_easy_setopt (req->easy, CURLOPT_USERAGENT, OSTREE_FETCHER_USERAGENT_STRING); curl_easy_setopt (req->easy, CURLOPT_USERAGENT,
self->custom_user_agent ?: OSTREE_FETCHER_USERAGENT_STRING);
if (self->extra_headers) if (self->extra_headers)
curl_easy_setopt (req->easy, CURLOPT_HTTPHEADER, self->extra_headers); curl_easy_setopt (req->easy, CURLOPT_HTTPHEADER, self->extra_headers);

View File

@ -374,6 +374,24 @@ session_thread_set_tls_database_cb (ThreadClosure *thread_closure,
} }
} }
static void
session_thread_set_extra_user_agent_cb (ThreadClosure *thread_closure,
gpointer data)
{
const char *extra_user_agent = data;
if (extra_user_agent != NULL)
{
g_autofree char *ua =
g_strdup_printf ("%s %s", OSTREE_FETCHER_USERAGENT_STRING, extra_user_agent);
g_object_set (thread_closure->session, SOUP_SESSION_USER_AGENT, ua, NULL);
}
else
{
g_object_set (thread_closure->session, SOUP_SESSION_USER_AGENT,
OSTREE_FETCHER_USERAGENT_STRING, NULL);
}
}
static void static void
on_request_sent (GObject *object, GAsyncResult *result, gpointer user_data); on_request_sent (GObject *object, GAsyncResult *result, gpointer user_data);
@ -774,6 +792,16 @@ _ostree_fetcher_set_extra_headers (OstreeFetcher *self,
(GDestroyNotify) g_variant_unref); (GDestroyNotify) g_variant_unref);
} }
void
_ostree_fetcher_set_extra_user_agent (OstreeFetcher *self,
const char *extra_user_agent)
{
session_thread_idle_add (self->thread_closure,
session_thread_set_extra_user_agent_cb,
g_strdup (extra_user_agent),
(GDestroyNotify) g_free);
}
static gboolean static gboolean
finish_stream (OstreeFetcherPendingURI *pending, finish_stream (OstreeFetcherPendingURI *pending,
GCancellable *cancellable, GCancellable *cancellable,

View File

@ -114,6 +114,9 @@ void _ostree_fetcher_set_tls_database (OstreeFetcher *self,
void _ostree_fetcher_set_extra_headers (OstreeFetcher *self, void _ostree_fetcher_set_extra_headers (OstreeFetcher *self,
GVariant *extra_headers); GVariant *extra_headers);
void _ostree_fetcher_set_extra_user_agent (OstreeFetcher *self,
const char *extra_user_agent);
guint64 _ostree_fetcher_bytes_transferred (OstreeFetcher *self); guint64 _ostree_fetcher_bytes_transferred (OstreeFetcher *self);
void _ostree_fetcher_request_to_tmpfile (OstreeFetcher *self, void _ostree_fetcher_request_to_tmpfile (OstreeFetcher *self,

View File

@ -149,6 +149,7 @@ ostree_remote_unref (OstreeRemote *remote)
if (g_atomic_int_dec_and_test (&remote->ref_count)) if (g_atomic_int_dec_and_test (&remote->ref_count))
{ {
g_clear_pointer (&remote->name, g_free); g_clear_pointer (&remote->name, g_free);
g_clear_pointer (&remote->refspec_name, g_free);
g_clear_pointer (&remote->group, g_free); g_clear_pointer (&remote->group, g_free);
g_clear_pointer (&remote->keyring, g_free); g_clear_pointer (&remote->keyring, g_free);
g_clear_object (&remote->file); g_clear_object (&remote->file);

View File

@ -30,6 +30,8 @@
#include <gio/gunixoutputstream.h> #include <gio/gunixoutputstream.h>
#include <sys/xattr.h> #include <sys/xattr.h>
#include <glib/gprintf.h> #include <glib/gprintf.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include "otutil.h" #include "otutil.h"
#include "ostree.h" #include "ostree.h"
@ -40,6 +42,12 @@
#include "ostree-checksum-input-stream.h" #include "ostree-checksum-input-stream.h"
#include "ostree-varint.h" #include "ostree-varint.h"
/* The standardized version of BTRFS_IOC_CLONE */
#ifndef FICLONE
#define FICLONE _IOW(0x94, 9, int)
#endif
/* If fsync is enabled and we're in a txn, we write into a staging dir for /* If fsync is enabled and we're in a txn, we write into a staging dir for
* commit, but we also allow direct writes into objects/ for e.g. hardlink * commit, but we also allow direct writes into objects/ for e.g. hardlink
* imports. * imports.
@ -589,6 +597,192 @@ create_regular_tmpfile_linkable_with_content (OstreeRepo *self,
return TRUE; return TRUE;
} }
static gboolean
_check_support_reflink (OstreeRepo *self, gboolean *supported, GError **error)
{
/* We have not checked yet if the file system supports reflinks, do it here */
if (g_atomic_int_get (&self->fs_support_reflink) == 0)
{
g_auto(GLnxTmpfile) src_tmpf = { 0, };
g_auto(GLnxTmpfile) dest_tmpf = { 0, };
if (!glnx_open_tmpfile_linkable_at (commit_tmp_dfd (self), ".", O_RDWR|O_CLOEXEC,
&src_tmpf, error))
return FALSE;
if (!glnx_open_tmpfile_linkable_at (commit_tmp_dfd (self), ".", O_WRONLY|O_CLOEXEC,
&dest_tmpf, error))
return FALSE;
if (ioctl (dest_tmpf.fd, FICLONE, src_tmpf.fd) == 0)
g_atomic_int_set (&self->fs_support_reflink, 1);
else if (errno == EOPNOTSUPP) /* Ignore other kind of errors as they might be temporary failures */
g_atomic_int_set (&self->fs_support_reflink, -1);
}
*supported = g_atomic_int_get (&self->fs_support_reflink) >= 0;
return TRUE;
}
static gboolean
_create_payload_link (OstreeRepo *self,
const char *checksum,
const char *payload_checksum,
GFileInfo *file_info,
GCancellable *cancellable,
GError **error)
{
gboolean reflinks_supported = FALSE;
if (!_check_support_reflink (self, &reflinks_supported, error))
return FALSE;
if (!reflinks_supported)
return TRUE;
if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_REGULAR
|| !G_IN_SET(self->mode, OSTREE_REPO_MODE_BARE, OSTREE_REPO_MODE_BARE_USER, OSTREE_REPO_MODE_BARE_USER_ONLY))
return TRUE;
if (payload_checksum == NULL || g_file_info_get_size (file_info) < self->payload_link_threshold)
return TRUE;
char target_buf[_OSTREE_LOOSE_PATH_MAX + _OSTREE_PAYLOAD_LINK_PREFIX_LEN];
strcpy (target_buf, _OSTREE_PAYLOAD_LINK_PREFIX);
_ostree_loose_path (target_buf + _OSTREE_PAYLOAD_LINK_PREFIX_LEN, checksum, OSTREE_OBJECT_TYPE_FILE, self->mode);
if (symlinkat (target_buf, commit_tmp_dfd (self), payload_checksum) < 0)
{
if (errno != EEXIST)
return glnx_throw_errno_prefix (error, "symlinkat");
}
else
{
g_auto(OtCleanupUnlinkat) tmp_unlinker = { commit_tmp_dfd (self), g_strdup (payload_checksum) };
if (!commit_path_final (self, payload_checksum, OSTREE_OBJECT_TYPE_PAYLOAD_LINK, &tmp_unlinker, cancellable, error))
return FALSE;
}
return TRUE;
}
static gboolean
_import_payload_link (OstreeRepo *self,
OstreeRepo *source,
const char *checksum,
GCancellable *cancellable,
GError **error)
{
gboolean reflinks_supported = FALSE;
g_autofree char *payload_checksum = NULL;
g_autoptr(GInputStream) is = NULL;
glnx_unref_object OtChecksumInstream *checksum_payload = NULL;
g_autoptr(GFileInfo) file_info = NULL;
if (!_check_support_reflink (self, &reflinks_supported, error))
return FALSE;
if (!reflinks_supported)
return TRUE;
if (!G_IN_SET(self->mode, OSTREE_REPO_MODE_BARE, OSTREE_REPO_MODE_BARE_USER, OSTREE_REPO_MODE_BARE_USER_ONLY))
return TRUE;
if (!ostree_repo_load_file (source, checksum, &is, &file_info, NULL, cancellable, error))
return FALSE;
if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_REGULAR
|| g_file_info_get_size (file_info) < self->payload_link_threshold)
return TRUE;
checksum_payload = ot_checksum_instream_new (is, G_CHECKSUM_SHA256);
guint64 remaining = g_file_info_get_size (file_info);
while (remaining)
{
char buf[8192];
gssize ret = g_input_stream_read ((GInputStream *) checksum_payload, buf,
MIN (sizeof (buf), remaining), cancellable, error);
if (ret < 0)
return FALSE;
remaining -= ret;
}
payload_checksum = ot_checksum_instream_get_string (checksum_payload);
return _create_payload_link (self, checksum, payload_checksum, file_info, cancellable, error);
}
static gboolean
_try_clone_from_payload_link (OstreeRepo *self,
const char *payload_checksum,
GFileInfo *file_info,
GLnxTmpfile *tmpf,
GCancellable *cancellable,
GError **error)
{
gboolean reflinks_supported = FALSE;
int dfd_searches[] = { -1, self->objects_dir_fd };
if (self->commit_stagedir.initialized)
dfd_searches[0] = self->commit_stagedir.fd;
if (!_check_support_reflink (self, &reflinks_supported, error))
return FALSE;
if (!reflinks_supported)
return TRUE;
for (guint i = 0; i < G_N_ELEMENTS (dfd_searches); i++)
{
glnx_autofd int fdf = -1;
char loose_path_buf[_OSTREE_LOOSE_PATH_MAX];
char loose_path_target_buf[_OSTREE_LOOSE_PATH_MAX];
char target_buf[_OSTREE_LOOSE_PATH_MAX + _OSTREE_PAYLOAD_LINK_PREFIX_LEN];
char target_checksum[OSTREE_SHA256_STRING_LEN+1];
int dfd = dfd_searches[i];
ssize_t size;
if (dfd == -1)
continue;
_ostree_loose_path (loose_path_buf, payload_checksum, OSTREE_OBJECT_TYPE_PAYLOAD_LINK, self->mode);
size = TEMP_FAILURE_RETRY (readlinkat (dfd, loose_path_buf, target_buf, sizeof (target_buf)));
if (size < 0)
{
if (errno == ENOENT)
continue;
return glnx_throw_errno_prefix (error, "readlinkat");
}
if (size < OSTREE_SHA256_STRING_LEN + _OSTREE_PAYLOAD_LINK_PREFIX_LEN)
return glnx_throw (error, "invalid data size for %s", loose_path_buf);
sprintf (target_checksum, "%.2s%.62s", target_buf + _OSTREE_PAYLOAD_LINK_PREFIX_LEN, target_buf + _OSTREE_PAYLOAD_LINK_PREFIX_LEN + 3);
_ostree_loose_path (loose_path_target_buf, target_checksum, OSTREE_OBJECT_TYPE_FILE, self->mode);
if (!ot_openat_ignore_enoent (dfd, loose_path_target_buf, &fdf, error))
return FALSE;
if (fdf < 0)
{
/* If the link is referring to an object that doesn't exist anymore in the repository, just unlink it. */
if (!glnx_unlinkat (dfd, loose_path_buf, 0, error))
return FALSE;
}
else
{
/* This undoes all of the previous writes; we want to generate reflinked data. */
if (ftruncate (tmpf->fd, 0) < 0)
return glnx_throw_errno_prefix (error, "ftruncate");
if (glnx_regfile_copy_bytes (fdf, tmpf->fd, -1) < 0)
return glnx_throw_errno_prefix (error, "regfile copy");
return TRUE;
}
}
if (self->parent_repo)
return _try_clone_from_payload_link (self->parent_repo, payload_checksum, file_info, tmpf, cancellable, error);
return TRUE;
}
/* The main driver for writing a content (regfile or symlink) object. /* The main driver for writing a content (regfile or symlink) object.
* There are a variety of tricky cases here; for example, bare-user * There are a variety of tricky cases here; for example, bare-user
* repos store symlinks as regular files. Computing checksums * repos store symlinks as regular files. Computing checksums
@ -616,6 +810,8 @@ write_content_object (OstreeRepo *self,
GInputStream *file_input; /* Unowned alias */ GInputStream *file_input; /* Unowned alias */
g_autoptr(GInputStream) file_input_owned = NULL; /* We need a temporary for bare-user symlinks */ g_autoptr(GInputStream) file_input_owned = NULL; /* We need a temporary for bare-user symlinks */
glnx_unref_object OtChecksumInstream *checksum_input = NULL; glnx_unref_object OtChecksumInstream *checksum_input = NULL;
glnx_unref_object OtChecksumInstream *checksum_payload_input = NULL;
const GFileType object_file_type = g_file_info_get_file_type (file_info);
if (out_csum) if (out_csum)
{ {
/* Previously we checksummed the input verbatim; now /* Previously we checksummed the input verbatim; now
@ -624,6 +820,7 @@ write_content_object (OstreeRepo *self,
* it's not that's not a serious problem because we're still computing a * it's not that's not a serious problem because we're still computing a
* checksum over the data we actually use. * checksum over the data we actually use.
*/ */
gboolean reflinks_supported = FALSE;
g_autoptr(GBytes) header = _ostree_file_header_new (file_info, xattrs); g_autoptr(GBytes) header = _ostree_file_header_new (file_info, xattrs);
size_t len; size_t len;
const guint8 *buf = g_bytes_get_data (header, &len); const guint8 *buf = g_bytes_get_data (header, &len);
@ -633,13 +830,26 @@ write_content_object (OstreeRepo *self,
null_input = input = g_memory_input_stream_new_from_data ("", 0, NULL); null_input = input = g_memory_input_stream_new_from_data ("", 0, NULL);
checksum_input = ot_checksum_instream_new_with_start (input, G_CHECKSUM_SHA256, checksum_input = ot_checksum_instream_new_with_start (input, G_CHECKSUM_SHA256,
buf, len); buf, len);
file_input = (GInputStream*)checksum_input;
if (!_check_support_reflink (self, &reflinks_supported, error))
return FALSE;
if (xattrs == NULL || !G_IN_SET(self->mode, OSTREE_REPO_MODE_BARE, OSTREE_REPO_MODE_BARE_USER, OSTREE_REPO_MODE_BARE_USER_ONLY) || object_file_type != G_FILE_TYPE_REGULAR ||
!reflinks_supported)
file_input = (GInputStream*)checksum_input;
else
{
/* The payload checksum-input reads from the full object checksum-input; this
* means it skips the header.
*/
checksum_payload_input = ot_checksum_instream_new ((GInputStream*)checksum_input, G_CHECKSUM_SHA256);
file_input = (GInputStream*)checksum_payload_input;
}
} }
else else
file_input = input; file_input = input;
gboolean phys_object_is_symlink = FALSE; gboolean phys_object_is_symlink = FALSE;
const GFileType object_file_type = g_file_info_get_file_type (file_info);
switch (object_file_type) switch (object_file_type)
{ {
case G_FILE_TYPE_REGULAR: case G_FILE_TYPE_REGULAR:
@ -765,6 +975,7 @@ write_content_object (OstreeRepo *self,
} }
const char *actual_checksum = NULL; const char *actual_checksum = NULL;
g_autofree char *actual_payload_checksum = NULL;
g_autofree char *actual_checksum_owned = NULL; g_autofree char *actual_checksum_owned = NULL;
if (!checksum_input) if (!checksum_input)
actual_checksum = expected_checksum; actual_checksum = expected_checksum;
@ -777,6 +988,9 @@ write_content_object (OstreeRepo *self,
error)) error))
return FALSE; return FALSE;
} }
if (checksum_payload_input)
actual_payload_checksum = ot_checksum_instream_get_string (checksum_payload_input);
} }
g_assert (actual_checksum != NULL); /* Pacify static analysis */ g_assert (actual_checksum != NULL); /* Pacify static analysis */
@ -794,6 +1008,10 @@ write_content_object (OstreeRepo *self,
g_mutex_lock (&self->txn_lock); g_mutex_lock (&self->txn_lock);
self->txn.stats.content_objects_total++; self->txn.stats.content_objects_total++;
g_mutex_unlock (&self->txn_lock); g_mutex_unlock (&self->txn_lock);
if (!_create_payload_link (self, actual_checksum, actual_payload_checksum, file_info, cancellable, error))
return FALSE;
if (out_csum) if (out_csum)
*out_csum = ostree_checksum_to_bytes (actual_checksum); *out_csum = ostree_checksum_to_bytes (actual_checksum);
/* Note early return */ /* Note early return */
@ -853,12 +1071,20 @@ write_content_object (OstreeRepo *self,
repo_store_size_entry (self, actual_checksum, unpacked_size, stbuf.st_size); repo_store_size_entry (self, actual_checksum, unpacked_size, stbuf.st_size);
} }
/* Check if a file with the same payload is present in the repository,
and in case try to reflink it */
if (actual_payload_checksum && !_try_clone_from_payload_link (self, actual_payload_checksum, file_info, &tmpf, cancellable, error))
return FALSE;
/* This path is for regular files */ /* This path is for regular files */
if (!commit_loose_regfile_object (self, actual_checksum, &tmpf, if (!commit_loose_regfile_object (self, actual_checksum, &tmpf,
uid, gid, mode, uid, gid, mode,
xattrs, xattrs,
cancellable, error)) cancellable, error))
return FALSE; return FALSE;
if (!_create_payload_link (self, actual_checksum, actual_payload_checksum, file_info, cancellable, error))
return FALSE;
} }
/* Update statistics */ /* Update statistics */
@ -1927,6 +2153,12 @@ ostree_repo_abort_transaction (OstreeRepo *self,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
/* Always ignore the cancellable to avoid the chance that, if it gets
* canceled, the transaction may not be fully cleaned up.
* See https://github.com/ostreedev/ostree/issues/1491 .
*/
cancellable = NULL;
/* Note early return */ /* Note early return */
if (!self->in_transaction) if (!self->in_transaction)
return TRUE; return TRUE;
@ -3999,7 +4231,11 @@ import_one_object_direct (OstreeRepo *dest_repo,
if (!copy_detached_metadata (dest_repo, src_repo, checksum, cancellable, error)) if (!copy_detached_metadata (dest_repo, src_repo, checksum, cancellable, error))
return FALSE; return FALSE;
} }
else if (objtype == OSTREE_OBJECT_TYPE_FILE)
{
if (!_import_payload_link (dest_repo, src_repo, checksum, cancellable, error))
return FALSE;
}
*out_was_supported = TRUE; *out_was_supported = TRUE;
return TRUE; return TRUE;
} }
@ -4092,7 +4328,14 @@ _ostree_repo_import_object (OstreeRepo *self,
return FALSE; return FALSE;
/* If we have it, we're done */ /* If we have it, we're done */
if (has_object) if (has_object)
return TRUE; {
if (objtype == OSTREE_OBJECT_TYPE_FILE)
{
if (!_import_payload_link (self, source, checksum, cancellable, error))
return FALSE;
}
return TRUE;
}
if (OSTREE_OBJECT_TYPE_IS_META (objtype)) if (OSTREE_OBJECT_TYPE_IS_META (objtype))
{ {

View File

@ -30,6 +30,7 @@
#include <glib-object.h> #include <glib-object.h>
#include <libglnx.h> #include <libglnx.h>
#include "ostree-autocleanups.h"
#include "ostree-remote-private.h" #include "ostree-remote-private.h"
#include "ostree-repo.h" #include "ostree-repo.h"
#include "ostree-repo-private.h" #include "ostree-repo-private.h"
@ -176,7 +177,7 @@ ostree_repo_finder_config_resolve_async (OstreeRepoFinder *find
while (g_hash_table_iter_next (&iter, (gpointer *) &remote_name, (gpointer *) &supported_ref_to_checksum)) while (g_hash_table_iter_next (&iter, (gpointer *) &remote_name, (gpointer *) &supported_ref_to_checksum))
{ {
g_autoptr(GError) local_error = NULL; g_autoptr(GError) local_error = NULL;
OstreeRemote *remote; g_autoptr(OstreeRemote) remote = NULL;
/* We dont know what last-modified timestamp the remote has without /* We dont know what last-modified timestamp the remote has without
* making expensive HTTP queries, so leave that information blank. We * making expensive HTTP queries, so leave that information blank. We

View File

@ -52,7 +52,7 @@
* enumerated, and all OSTree repositories below it will be searched, in lexical * enumerated, and all OSTree repositories below it will be searched, in lexical
* order, for the requested #OstreeCollectionRefs. The names of the directories * order, for the requested #OstreeCollectionRefs. The names of the directories
* below `.ostree/repos.d` are irrelevant, apart from their lexical ordering. * below `.ostree/repos.d` are irrelevant, apart from their lexical ordering.
* The directories `.ostree/repo`, `ostree/repo` and `var/lib/flatpak` * The directories `.ostree/repo`, `ostree/repo` and `var/lib/flatpak/repo`
* will be searched after the others, if they exist. * will be searched after the others, if they exist.
* Non-removable volumes are ignored. * Non-removable volumes are ignored.
* *
@ -295,8 +295,8 @@ scan_and_add_repo (int dfd,
}; };
g_array_append_val (inout_repos_refs, val); g_array_append_val (inout_repos_refs, val);
g_debug ("%s: Adding repo %s (%ssortable)", g_debug ("%s: Adding repo %s on mount %s (%ssortable)",
G_STRFUNC, path, sortable ? "" : "not "); G_STRFUNC, path, mount_name, sortable ? "" : "not ");
} }
} }
@ -439,7 +439,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS
{ {
".ostree/repo", ".ostree/repo",
"ostree/repo", "ostree/repo",
"var/lib/flatpak", "var/lib/flatpak/repo",
}; };
for (i = 0; i < G_N_ELEMENTS (well_known_repos); i++) for (i = 0; i < G_N_ELEMENTS (well_known_repos); i++)

View File

@ -53,6 +53,9 @@ G_BEGIN_DECLS
#define OSTREE_SUMMARY_COLLECTION_ID "ostree.summary.collection-id" #define OSTREE_SUMMARY_COLLECTION_ID "ostree.summary.collection-id"
#define OSTREE_SUMMARY_COLLECTION_MAP "ostree.summary.collection-map" #define OSTREE_SUMMARY_COLLECTION_MAP "ostree.summary.collection-map"
#define _OSTREE_PAYLOAD_LINK_PREFIX "../"
#define _OSTREE_PAYLOAD_LINK_PREFIX_LEN (sizeof (_OSTREE_PAYLOAD_LINK_PREFIX) - 1)
/* Well-known keys for the additional metadata field in a commit in a ref entry /* Well-known keys for the additional metadata field in a commit in a ref entry
* in a summary file. */ * in a summary file. */
#define OSTREE_COMMIT_TIMESTAMP "ostree.commit.timestamp" #define OSTREE_COMMIT_TIMESTAMP "ostree.commit.timestamp"
@ -161,6 +164,8 @@ struct OstreeRepo {
gchar *collection_id; gchar *collection_id;
gboolean add_remotes_config_dir; /* Add new remotes in remotes.d dir */ gboolean add_remotes_config_dir; /* Add new remotes in remotes.d dir */
gint lock_timeout_seconds; gint lock_timeout_seconds;
guint64 payload_link_threshold;
gint fs_support_reflink; /* The underlying filesystem has support for ioctl (FICLONE..) */
OstreeRepo *parent_repo; OstreeRepo *parent_repo;
}; };
@ -237,14 +242,6 @@ _ostree_repo_ensure_loose_objdir_at (int dfd,
GCancellable *cancellable, GCancellable *cancellable,
GError **error); GError **error);
gboolean
_ostree_repo_find_object (OstreeRepo *self,
OstreeObjectType objtype,
const char *checksum,
GFile **out_stored_path,
GCancellable *cancellable,
GError **error);
GFile * GFile *
_ostree_repo_get_commit_metadata_loose_path (OstreeRepo *self, _ostree_repo_get_commit_metadata_loose_path (OstreeRepo *self,
const char *checksum); const char *checksum);

View File

@ -46,40 +46,79 @@ maybe_prune_loose_object (OtPruneData *data,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
gboolean reachable = FALSE;
g_autoptr(GVariant) key = NULL; g_autoptr(GVariant) key = NULL;
key = ostree_object_name_serialize (checksum, objtype); key = ostree_object_name_serialize (checksum, objtype);
if (!g_hash_table_lookup_extended (data->reachable, key, NULL, NULL)) if (g_hash_table_lookup_extended (data->reachable, key, NULL, NULL))
reachable = TRUE;
else
{ {
guint64 storage_size = 0;
g_debug ("Pruning unneeded object %s.%s", checksum, g_debug ("Pruning unneeded object %s.%s", checksum,
ostree_object_type_to_string (objtype)); ostree_object_type_to_string (objtype));
if (!ostree_repo_query_object_storage_size (data->repo, objtype, checksum,
&storage_size, cancellable, error))
return FALSE;
data->freed_bytes += storage_size;
if (!(flags & OSTREE_REPO_PRUNE_FLAGS_NO_PRUNE)) if (!(flags & OSTREE_REPO_PRUNE_FLAGS_NO_PRUNE))
{ {
guint64 storage_size = 0; if (objtype == OSTREE_OBJECT_TYPE_PAYLOAD_LINK)
{
ssize_t size;
char loose_path_buf[_OSTREE_LOOSE_PATH_MAX];
char target_checksum[OSTREE_SHA256_STRING_LEN+1];
char target_buf[_OSTREE_LOOSE_PATH_MAX + _OSTREE_PAYLOAD_LINK_PREFIX_LEN];
if (objtype == OSTREE_OBJECT_TYPE_COMMIT) _ostree_loose_path (loose_path_buf, checksum, OSTREE_OBJECT_TYPE_PAYLOAD_LINK, data->repo->mode);
size = readlinkat (data->repo->objects_dir_fd, loose_path_buf, target_buf, sizeof (target_buf));
if (size < 0)
return glnx_throw_errno_prefix (error, "readlinkat");
if (size < OSTREE_SHA256_STRING_LEN + _OSTREE_PAYLOAD_LINK_PREFIX_LEN)
return glnx_throw (error, "invalid data size for %s", loose_path_buf);
sprintf (target_checksum, "%.2s%.62s", target_buf + _OSTREE_PAYLOAD_LINK_PREFIX_LEN, target_buf + _OSTREE_PAYLOAD_LINK_PREFIX_LEN + 3);
g_autoptr(GVariant) target_key = ostree_object_name_serialize (target_checksum, OSTREE_OBJECT_TYPE_FILE);
if (g_hash_table_lookup_extended (data->reachable, target_key, NULL, NULL))
{
guint64 target_storage_size = 0;
if (!ostree_repo_query_object_storage_size (data->repo, OSTREE_OBJECT_TYPE_FILE, target_checksum,
&target_storage_size, cancellable, error))
return FALSE;
reachable = target_storage_size >= data->repo->payload_link_threshold;
if (reachable)
goto exit;
}
}
else if (objtype == OSTREE_OBJECT_TYPE_COMMIT)
{ {
if (!ostree_repo_mark_commit_partial (data->repo, checksum, FALSE, error)) if (!ostree_repo_mark_commit_partial (data->repo, checksum, FALSE, error))
return FALSE; return FALSE;
} }
if (!ostree_repo_query_object_storage_size (data->repo, objtype, checksum,
&storage_size, cancellable, error))
return FALSE;
if (!ostree_repo_delete_object (data->repo, objtype, checksum, if (!ostree_repo_delete_object (data->repo, objtype, checksum,
cancellable, error)) cancellable, error))
return FALSE; return FALSE;
data->freed_bytes += storage_size;
} }
if (OSTREE_OBJECT_TYPE_IS_META (objtype)) if (OSTREE_OBJECT_TYPE_IS_META (objtype))
data->n_unreachable_meta++; data->n_unreachable_meta++;
else else
data->n_unreachable_content++; data->n_unreachable_content++;
} }
else
exit:
if (reachable)
{ {
g_debug ("Keeping needed object %s.%s", checksum, g_debug ("Keeping needed object %s.%s", checksum,
ostree_object_type_to_string (objtype)); ostree_object_type_to_string (objtype));

View File

@ -87,6 +87,7 @@ typedef struct {
OstreeAsyncProgress *progress; OstreeAsyncProgress *progress;
GVariant *extra_headers; GVariant *extra_headers;
char *append_user_agent;
gboolean dry_run; gboolean dry_run;
gboolean dry_run_emitted_progress; gboolean dry_run_emitted_progress;
@ -2922,11 +2923,13 @@ repo_remote_fetch_summary (OstreeRepo *self,
const char *url_override = NULL; const char *url_override = NULL;
g_autoptr(GVariant) extra_headers = NULL; g_autoptr(GVariant) extra_headers = NULL;
g_autoptr(GPtrArray) mirrorlist = NULL; g_autoptr(GPtrArray) mirrorlist = NULL;
const char *append_user_agent = NULL;
if (options) if (options)
{ {
(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, "http-headers", "@a(ss)", &extra_headers); (void) g_variant_lookup (options, "http-headers", "@a(ss)", &extra_headers);
(void) g_variant_lookup (options, "append-user-agent", "&s", &append_user_agent);
} }
mainctx = g_main_context_new (); mainctx = g_main_context_new ();
@ -2939,6 +2942,9 @@ repo_remote_fetch_summary (OstreeRepo *self,
if (extra_headers) if (extra_headers)
_ostree_fetcher_set_extra_headers (fetcher, extra_headers); _ostree_fetcher_set_extra_headers (fetcher, extra_headers);
if (append_user_agent)
_ostree_fetcher_set_extra_user_agent (fetcher, append_user_agent);
{ {
g_autofree char *url_string = NULL; g_autofree char *url_string = NULL;
if (metalink_url_string) if (metalink_url_string)
@ -3055,6 +3061,9 @@ reinitialize_fetcher (OtPullData *pull_data, const char *remote_name,
if (pull_data->extra_headers) if (pull_data->extra_headers)
_ostree_fetcher_set_extra_headers (pull_data->fetcher, pull_data->extra_headers); _ostree_fetcher_set_extra_headers (pull_data->fetcher, pull_data->extra_headers);
if (pull_data->append_user_agent)
_ostree_fetcher_set_extra_user_agent (pull_data->fetcher, pull_data->append_user_agent);
return TRUE; return TRUE;
} }
@ -3240,6 +3249,7 @@ initiate_request (OtPullData *pull_data,
* * http-headers (a(ss)): Additional headers to add to all HTTP requests * * http-headers (a(ss)): Additional headers to add to all HTTP requests
* * update-frequency (u): Frequency to call the async progress callback in milliseconds, if any; only values higher than 0 are valid * * update-frequency (u): Frequency to call the async progress callback in milliseconds, if any; only values higher than 0 are valid
* * localcache-repos (as): File paths for local repos to use as caches when doing remote fetches * * localcache-repos (as): File paths for local repos to use as caches when doing remote fetches
* * append-user-agent (s): Additional string to append to the user agent
*/ */
gboolean gboolean
ostree_repo_pull_with_options (OstreeRepo *self, ostree_repo_pull_with_options (OstreeRepo *self,
@ -3311,6 +3321,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
(void) g_variant_lookup (options, "update-frequency", "u", &update_frequency); (void) g_variant_lookup (options, "update-frequency", "u", &update_frequency);
(void) g_variant_lookup (options, "localcache-repos", "^a&s", &opt_localcache_repos); (void) g_variant_lookup (options, "localcache-repos", "^a&s", &opt_localcache_repos);
(void) g_variant_lookup (options, "timestamp-check", "b", &pull_data->timestamp_check); (void) g_variant_lookup (options, "timestamp-check", "b", &pull_data->timestamp_check);
(void) g_variant_lookup (options, "append-user-agent", "s", &pull_data->append_user_agent);
if (pull_data->remote_refspec_name != NULL) if (pull_data->remote_refspec_name != NULL)
pull_data->remote_name = g_strdup (pull_data->remote_refspec_name); pull_data->remote_name = g_strdup (pull_data->remote_refspec_name);
@ -3365,7 +3376,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
(GDestroyNotify)g_free); (GDestroyNotify)g_free);
pull_data->ref_original_commits = g_hash_table_new_full (ostree_collection_ref_hash, ostree_collection_ref_equal, pull_data->ref_original_commits = g_hash_table_new_full (ostree_collection_ref_hash, ostree_collection_ref_equal,
(GDestroyNotify)NULL, (GDestroyNotify)NULL,
(GDestroyNotify)g_variant_unref); (GDestroyNotify)g_free);
pull_data->gpg_verified_commits = g_hash_table_new_full (g_str_hash, g_str_equal, pull_data->gpg_verified_commits = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)g_free, NULL); (GDestroyNotify)g_free, NULL);
pull_data->scanned_metadata = g_hash_table_new_full (ostree_hash_object_name, g_variant_equal, pull_data->scanned_metadata = g_hash_table_new_full (ostree_hash_object_name, g_variant_equal,
@ -4323,6 +4334,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
g_clear_pointer (&pull_data->localcache_repos, (GDestroyNotify)g_ptr_array_unref); g_clear_pointer (&pull_data->localcache_repos, (GDestroyNotify)g_ptr_array_unref);
g_clear_object (&pull_data->remote_repo_local); g_clear_object (&pull_data->remote_repo_local);
g_free (pull_data->remote_name); g_free (pull_data->remote_name);
g_free (pull_data->append_user_agent);
g_clear_pointer (&pull_data->meta_mirrorlist, (GDestroyNotify) g_ptr_array_unref); g_clear_pointer (&pull_data->meta_mirrorlist, (GDestroyNotify) g_ptr_array_unref);
g_clear_pointer (&pull_data->content_mirrorlist, (GDestroyNotify) g_ptr_array_unref); g_clear_pointer (&pull_data->content_mirrorlist, (GDestroyNotify) g_ptr_array_unref);
g_clear_pointer (&pull_data->summary_data, (GDestroyNotify) g_bytes_unref); g_clear_pointer (&pull_data->summary_data, (GDestroyNotify) g_bytes_unref);
@ -5502,6 +5514,7 @@ ostree_repo_pull_from_remotes_async (OstreeRepo *self,
copy_option (&options_dict, &local_options_dict, "http-headers", G_VARIANT_TYPE ("a(ss)")); copy_option (&options_dict, &local_options_dict, "http-headers", G_VARIANT_TYPE ("a(ss)"));
copy_option (&options_dict, &local_options_dict, "subdirs", G_VARIANT_TYPE ("as")); copy_option (&options_dict, &local_options_dict, "subdirs", G_VARIANT_TYPE ("as"));
copy_option (&options_dict, &local_options_dict, "update-frequency", G_VARIANT_TYPE ("u")); copy_option (&options_dict, &local_options_dict, "update-frequency", G_VARIANT_TYPE ("u"));
copy_option (&options_dict, &local_options_dict, "append-user-agent", G_VARIANT_TYPE ("s"));
local_options = g_variant_dict_end (&local_options_dict); local_options = g_variant_dict_end (&local_options_dict);
@ -5645,7 +5658,7 @@ ostree_repo_resolve_keyring_for_collection (OstreeRepo *self,
{ {
gsize i; gsize i;
g_auto(GStrv) remotes = NULL; g_auto(GStrv) remotes = NULL;
OstreeRemote *keyring_remote = NULL; g_autoptr(OstreeRemote) keyring_remote = NULL;
g_return_val_if_fail (OSTREE_IS_REPO (self), NULL); g_return_val_if_fail (OSTREE_IS_REPO (self), NULL);
g_return_val_if_fail (ostree_validate_collection_id (collection_id, NULL), NULL); g_return_val_if_fail (ostree_validate_collection_id (collection_id, NULL), NULL);
@ -5680,6 +5693,7 @@ ostree_repo_resolve_keyring_for_collection (OstreeRepo *self,
{ {
g_debug ("%s: Ignoring remote %s as it has no keyring configured.", g_debug ("%s: Ignoring remote %s as it has no keyring configured.",
G_STRFUNC, remotes[i]); G_STRFUNC, remotes[i]);
g_clear_object (&keyring_remote);
continue; continue;
} }
@ -5695,7 +5709,7 @@ ostree_repo_resolve_keyring_for_collection (OstreeRepo *self,
} }
if (keyring_remote != NULL) if (keyring_remote != NULL)
return ostree_remote_ref (keyring_remote); return g_steal_pointer (&keyring_remote);
else else
{ {
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
@ -5724,6 +5738,7 @@ ostree_repo_resolve_keyring_for_collection (OstreeRepo *self,
* *
* - override-url (s): Fetch summary from this URL if remote specifies no metalink in options * - override-url (s): Fetch summary from this URL if remote specifies no metalink in options
* - http-headers (a(ss)): Additional headers to add to all HTTP requests * - http-headers (a(ss)): Additional headers to add to all HTTP requests
* - append-user-agent (s): Additional string to append to the user agent
* *
* Returns: %TRUE on success, %FALSE on failure * Returns: %TRUE on success, %FALSE on failure
*/ */

View File

@ -617,6 +617,8 @@ _ostree_repo_list_refs_internal (OstreeRepo *self,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
GLNX_AUTO_PREFIX_ERROR ("Listing refs", error);
g_autofree char *remote = NULL; g_autofree char *remote = NULL;
g_autofree char *ref_prefix = NULL; g_autofree char *ref_prefix = NULL;
@ -627,8 +629,24 @@ _ostree_repo_list_refs_internal (OstreeRepo *self,
const char *prefix_path; const char *prefix_path;
const char *path; const char *path;
if (!ostree_parse_refspec (refspec_prefix, &remote, &ref_prefix, error)) /* special-case "<remote>:" and "<remote>:.", which ostree_parse_refspec won't like */
return FALSE; if (g_str_has_suffix (refspec_prefix, ":") ||
g_str_has_suffix (refspec_prefix, ":."))
{
const char *colon = strrchr (refspec_prefix, ':');
g_autofree char *r = g_strndup (refspec_prefix, colon - refspec_prefix);
if (ostree_validate_remote_name (r, NULL))
{
remote = g_steal_pointer (&r);
ref_prefix = g_strdup (".");
}
}
if (!ref_prefix)
{
if (!ostree_parse_refspec (refspec_prefix, &remote, &ref_prefix, error))
return FALSE;
}
if (!(flags & OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES) && remote) if (!(flags & OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES) && remote)
{ {
@ -1029,10 +1047,7 @@ _ostree_repo_write_ref (OstreeRepo *self,
{ {
if (!glnx_opendirat (self->repo_dir_fd, "refs/heads", TRUE, if (!glnx_opendirat (self->repo_dir_fd, "refs/heads", TRUE,
&dfd, error)) &dfd, error))
{ return FALSE;
g_prefix_error (error, "Opening %s: ", "refs/heads");
return FALSE;
}
} }
else if (remote == NULL && ref->collection_id != NULL) else if (remote == NULL && ref->collection_id != NULL)
{ {
@ -1041,10 +1056,7 @@ _ostree_repo_write_ref (OstreeRepo *self,
/* refs/mirrors might not exist in older repositories, so create it. */ /* refs/mirrors might not exist in older repositories, so create it. */
if (!glnx_shutil_mkdir_p_at_open (self->repo_dir_fd, "refs/mirrors", 0777, if (!glnx_shutil_mkdir_p_at_open (self->repo_dir_fd, "refs/mirrors", 0777,
&refs_mirrors_dfd, cancellable, error)) &refs_mirrors_dfd, cancellable, error))
{ return FALSE;
g_prefix_error (error, "Opening %s: ", "refs/mirrors");
return FALSE;
}
if (rev != NULL) if (rev != NULL)
{ {
@ -1063,10 +1075,7 @@ _ostree_repo_write_ref (OstreeRepo *self,
if (!glnx_opendirat (self->repo_dir_fd, "refs/remotes", TRUE, if (!glnx_opendirat (self->repo_dir_fd, "refs/remotes", TRUE,
&refs_remotes_dfd, error)) &refs_remotes_dfd, error))
{ return FALSE;
g_prefix_error (error, "Opening %s: ", "refs/remotes");
return FALSE;
}
if (rev != NULL) if (rev != NULL)
{ {
@ -1207,6 +1216,8 @@ ostree_repo_list_collection_refs (OstreeRepo *self,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
GLNX_AUTO_PREFIX_ERROR ("Listing refs", error);
g_return_val_if_fail (OSTREE_IS_REPO (self), FALSE); g_return_val_if_fail (OSTREE_IS_REPO (self), FALSE);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE); g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

View File

@ -241,14 +241,8 @@ finish_part (OstreeStaticDeltaBuilder *builder, GError **error)
g_variant_builder_add_value (&xattr_builder, part_builder->xattrs->pdata[j]); g_variant_builder_add_value (&xattr_builder, part_builder->xattrs->pdata[j]);
{ {
g_autoptr(GBytes) payload_b; g_autoptr(GBytes) payload_b = g_string_free_to_bytes (g_steal_pointer (&part_builder->payload));
g_autoptr(GBytes) operations_b; g_autoptr(GBytes) operations_b = g_string_free_to_bytes (g_steal_pointer (&part_builder->operations));
payload_b = g_string_free_to_bytes (part_builder->payload);
part_builder->payload = NULL;
operations_b = g_string_free_to_bytes (part_builder->operations);
part_builder->operations = NULL;
delta_part_content = g_variant_new ("(a(uuu)aa(ayay)@ay@ay)", delta_part_content = g_variant_new ("(a(uuu)aa(ayay)@ay@ay)",
&mode_builder, &xattr_builder, &mode_builder, &xattr_builder,

View File

@ -38,10 +38,8 @@ _ostree_static_delta_parse_checksum_array (GVariant *array,
guint *out_n_checksums, guint *out_n_checksums,
GError **error) GError **error)
{ {
gsize n = g_variant_n_children (array); const gsize n = g_variant_n_children (array);
guint n_checksums; const guint n_checksums = n / OSTREE_STATIC_DELTA_OBJTYPE_CSUM_LEN;
n_checksums = n / OSTREE_STATIC_DELTA_OBJTYPE_CSUM_LEN;
if (G_UNLIKELY(n > (G_MAXUINT32/OSTREE_STATIC_DELTA_OBJTYPE_CSUM_LEN) || if (G_UNLIKELY(n > (G_MAXUINT32/OSTREE_STATIC_DELTA_OBJTYPE_CSUM_LEN) ||
(n_checksums * OSTREE_STATIC_DELTA_OBJTYPE_CSUM_LEN) != n)) (n_checksums * OSTREE_STATIC_DELTA_OBJTYPE_CSUM_LEN) != n))
@ -166,8 +164,8 @@ _ostree_repo_static_delta_part_have_all_objects (OstreeRepo *repo,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
guint8 *checksums_data; guint8 *checksums_data = NULL;
guint n_checksums; guint n_checksums = 0;
gboolean have_object = TRUE; gboolean have_object = TRUE;
if (!_ostree_static_delta_parse_checksum_array (checksum_array, if (!_ostree_static_delta_parse_checksum_array (checksum_array,

View File

@ -2827,6 +2827,15 @@ reload_core_config (OstreeRepo *self,
return FALSE; return FALSE;
} }
{ g_autofree char *payload_threshold = NULL;
if (!ot_keyfile_get_value_with_default (self->config, "core", "payload-link-threshold", "-1",
&payload_threshold, error))
return FALSE;
self->payload_link_threshold = g_ascii_strtoull (payload_threshold, NULL, 10);
}
return TRUE; return TRUE;
} }
@ -3278,6 +3287,8 @@ list_loose_objects_at (OstreeRepo *self,
objtype = OSTREE_OBJECT_TYPE_DIR_META; objtype = OSTREE_OBJECT_TYPE_DIR_META;
else if (strcmp (dot, ".commit") == 0) else if (strcmp (dot, ".commit") == 0)
objtype = OSTREE_OBJECT_TYPE_COMMIT; objtype = OSTREE_OBJECT_TYPE_COMMIT;
else if (strcmp (dot, ".payload-link") == 0)
objtype = OSTREE_OBJECT_TYPE_PAYLOAD_LINK;
else else
continue; continue;
@ -4800,17 +4811,16 @@ ostree_repo_add_gpg_signature_summary (OstreeRepo *self,
/* Note that fd is reused below */ /* Note that fd is reused below */
glnx_close_fd (&fd); glnx_close_fd (&fd);
g_autoptr(GVariant) existing_signatures = NULL; g_autoptr(GVariant) metadata = NULL;
if (!ot_openat_ignore_enoent (self->repo_dir_fd, "summary.sig", &fd, error)) if (!ot_openat_ignore_enoent (self->repo_dir_fd, "summary.sig", &fd, error))
return FALSE; return FALSE;
if (fd != -1) if (fd != -1)
{ {
if (!ot_variant_read_fd (fd, 0, G_VARIANT_TYPE (OSTREE_SUMMARY_SIG_GVARIANT_STRING), if (!ot_variant_read_fd (fd, 0, G_VARIANT_TYPE (OSTREE_SUMMARY_SIG_GVARIANT_STRING),
FALSE, &existing_signatures, error)) FALSE, &metadata, error))
return FALSE; return FALSE;
} }
g_autoptr(GVariant) new_metadata = NULL;
for (guint i = 0; key_id[i]; i++) for (guint i = 0; key_id[i]; i++)
{ {
g_autoptr(GBytes) signature_data = NULL; g_autoptr(GBytes) signature_data = NULL;
@ -4819,10 +4829,11 @@ ostree_repo_add_gpg_signature_summary (OstreeRepo *self,
cancellable, error)) cancellable, error))
return FALSE; return FALSE;
new_metadata = _ostree_detached_metadata_append_gpg_sig (existing_signatures, signature_data); g_autoptr(GVariant) old_metadata = g_steal_pointer (&metadata);
metadata = _ostree_detached_metadata_append_gpg_sig (old_metadata, signature_data);
} }
g_autoptr(GVariant) normalized = g_variant_get_normal_form (new_metadata); g_autoptr(GVariant) normalized = g_variant_get_normal_form (metadata);
if (!_ostree_repo_file_replace_contents (self, if (!_ostree_repo_file_replace_contents (self,
self->repo_dir_fd, self->repo_dir_fd,
@ -4914,7 +4925,7 @@ _ostree_repo_gpg_verify_data_internal (OstreeRepo *self,
g_autofree char *gpgkeypath = NULL; g_autofree char *gpgkeypath = NULL;
/* Add the remote's keyring file if it exists. */ /* Add the remote's keyring file if it exists. */
OstreeRemote *remote; g_autoptr(OstreeRemote) remote = NULL;
remote = _ostree_repo_get_remote_inherited (self, remote_name, error); remote = _ostree_repo_get_remote_inherited (self, remote_name, error);
if (remote == NULL) if (remote == NULL)
@ -4936,8 +4947,6 @@ _ostree_repo_gpg_verify_data_internal (OstreeRepo *self,
if (gpgkeypath) if (gpgkeypath)
_ostree_gpg_verifier_add_key_ascii_file (verifier, gpgkeypath); _ostree_gpg_verifier_add_key_ascii_file (verifier, gpgkeypath);
ostree_remote_unref (remote);
} }
if (add_global_keyring_dir) if (add_global_keyring_dir)

View File

@ -523,38 +523,33 @@ checkout_deployment_tree (OstreeSysroot *sysroot,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
gboolean ret = FALSE; GLNX_AUTO_PREFIX_ERROR ("Checking out deployment tree", error);
OstreeRepoCheckoutAtOptions checkout_opts = { 0, }; /* Find the directory with deployments for this stateroot */
const char *csum = ostree_deployment_get_csum (deployment); g_autofree char *osdeploy_path =
g_autofree char *checkout_target_name = NULL; g_strconcat ("ostree/deploy/", ostree_deployment_get_osname (deployment), "/deploy", NULL);
g_autofree char *osdeploy_path = NULL;
glnx_autofd int osdeploy_dfd = -1;
int ret_fd;
osdeploy_path = g_strconcat ("ostree/deploy/", ostree_deployment_get_osname (deployment), "/deploy", NULL);
checkout_target_name = g_strdup_printf ("%s.%d", csum, ostree_deployment_get_deployserial (deployment));
if (!glnx_shutil_mkdir_p_at (sysroot->sysroot_fd, osdeploy_path, 0775, cancellable, error)) if (!glnx_shutil_mkdir_p_at (sysroot->sysroot_fd, osdeploy_path, 0775, cancellable, error))
goto out; return FALSE;
glnx_autofd int osdeploy_dfd = -1;
if (!glnx_opendirat (sysroot->sysroot_fd, osdeploy_path, TRUE, &osdeploy_dfd, error)) if (!glnx_opendirat (sysroot->sysroot_fd, osdeploy_path, TRUE, &osdeploy_dfd, error))
goto out; return FALSE;
/* Clean up anything that was there before, from e.g. an interrupted checkout */
const char *csum = ostree_deployment_get_csum (deployment);
g_autofree char *checkout_target_name =
g_strdup_printf ("%s.%d", csum, ostree_deployment_get_deployserial (deployment));
if (!glnx_shutil_rm_rf_at (osdeploy_dfd, checkout_target_name, cancellable, error)) if (!glnx_shutil_rm_rf_at (osdeploy_dfd, checkout_target_name, cancellable, error))
goto out; return FALSE;
/* Generate hardlink farm, then opendir it */
OstreeRepoCheckoutAtOptions checkout_opts = { 0, };
if (!ostree_repo_checkout_at (repo, &checkout_opts, osdeploy_dfd, if (!ostree_repo_checkout_at (repo, &checkout_opts, osdeploy_dfd,
checkout_target_name, csum, checkout_target_name, csum,
cancellable, error)) cancellable, error))
goto out; return FALSE;
if (!glnx_opendirat (osdeploy_dfd, checkout_target_name, TRUE, &ret_fd, error)) return glnx_opendirat (osdeploy_dfd, checkout_target_name, TRUE, out_deployment_dfd,
goto out; error);
ret = TRUE;
*out_deployment_dfd = ret_fd;
out:
return ret;
} }
static char * static char *
@ -672,27 +667,21 @@ selinux_relabel_dir (OstreeSysroot *sysroot,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
gboolean ret = FALSE;
g_autoptr(GPtrArray) path_parts = g_ptr_array_new ();
g_autoptr(GFileInfo) root_info = NULL;
root_info = g_file_query_info (dir, OSTREE_GIO_FAST_QUERYINFO, g_autoptr(GFileInfo) root_info =
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, g_file_query_info (dir, OSTREE_GIO_FAST_QUERYINFO,
cancellable, error); G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
cancellable, error);
if (!root_info) if (!root_info)
goto out; return FALSE;
g_autoptr(GPtrArray) path_parts = g_ptr_array_new ();
g_ptr_array_add (path_parts, (char*)prefix); g_ptr_array_add (path_parts, (char*)prefix);
if (!relabel_recursively (sysroot, sepolicy, dir, root_info, path_parts, if (!relabel_recursively (sysroot, sepolicy, dir, root_info, path_parts,
cancellable, error)) cancellable, error))
{ return glnx_prefix_error (error, "Relabeling /%s", prefix);
g_prefix_error (error, "Relabeling /%s: ", prefix);
goto out;
}
ret = TRUE; return TRUE;
out:
return ret;
} }
/* Handles SELinux labeling for /var; this is slated to be deleted. See /* Handles SELinux labeling for /var; this is slated to be deleted. See
@ -767,16 +756,12 @@ merge_configuration (OstreeSysroot *sysroot,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
GLNX_AUTO_PREFIX_ERROR ("During /etc merge", error);
g_autoptr(OstreeSePolicy) sepolicy = NULL; g_autoptr(OstreeSePolicy) sepolicy = NULL;
if (previous_deployment) if (previous_deployment)
{ {
g_autoptr(GFile) previous_path = NULL; OstreeBootconfigParser *previous_bootconfig = ostree_deployment_get_bootconfig (previous_deployment);
OstreeBootconfigParser *previous_bootconfig;
previous_path = ostree_sysroot_get_deployment_directory (sysroot, previous_deployment);
previous_bootconfig = ostree_deployment_get_bootconfig (previous_deployment);
if (previous_bootconfig) if (previous_bootconfig)
{ {
const char *previous_options = ostree_bootconfig_parser_get (previous_bootconfig, "options"); const char *previous_options = ostree_bootconfig_parser_get (previous_bootconfig, "options");
@ -847,30 +832,39 @@ merge_configuration (OstreeSysroot *sysroot,
return TRUE; return TRUE;
} }
/* Write the origin file for a deployment. */ /* Write the origin file for a deployment; this does not bump the mtime, under
* the assumption the caller may be writing multiple.
*/
static gboolean static gboolean
write_origin_file_internal (OstreeSysroot *sysroot, write_origin_file_internal (OstreeSysroot *sysroot,
OstreeSePolicy *sepolicy,
OstreeDeployment *deployment, OstreeDeployment *deployment,
GKeyFile *new_origin, GKeyFile *new_origin,
GLnxFileReplaceFlags flags, GLnxFileReplaceFlags flags,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
GLNX_AUTO_PREFIX_ERROR ("Writing out origin file", error);
GKeyFile *origin = GKeyFile *origin =
new_origin ? new_origin : ostree_deployment_get_origin (deployment); new_origin ? new_origin : ostree_deployment_get_origin (deployment);
if (origin) if (origin)
{ {
g_autofree char *origin_path = NULL; g_auto(OstreeSepolicyFsCreatecon) con = { 0, };
g_autofree char *contents = NULL; if (!_ostree_sepolicy_preparefscreatecon (&con, sepolicy,
"/etc/ostree/remotes.d/dummy.conf",
0644, error))
return FALSE;
g_autofree char *origin_path =
g_strdup_printf ("ostree/deploy/%s/deploy/%s.%d.origin",
ostree_deployment_get_osname (deployment),
ostree_deployment_get_csum (deployment),
ostree_deployment_get_deployserial (deployment));
gsize len; gsize len;
g_autofree char *contents = g_key_file_to_data (origin, &len, error);
origin_path = g_strdup_printf ("ostree/deploy/%s/deploy/%s.%d.origin",
ostree_deployment_get_osname (deployment),
ostree_deployment_get_csum (deployment),
ostree_deployment_get_deployserial (deployment));
contents = g_key_file_to_data (origin, &len, error);
if (!contents) if (!contents)
return FALSE; return FALSE;
@ -903,9 +897,20 @@ ostree_sysroot_write_origin_file (OstreeSysroot *sysroot,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
return write_origin_file_internal (sysroot, deployment, new_origin, g_autoptr(GFile) rootfs = g_file_new_for_path ("/");
GLNX_FILE_REPLACE_DATASYNC_NEW, g_autoptr(OstreeSePolicy) sepolicy = ostree_sepolicy_new (rootfs, cancellable, error);
cancellable, error); if (!sepolicy)
return FALSE;
if (!write_origin_file_internal (sysroot, sepolicy, deployment, new_origin,
GLNX_FILE_REPLACE_DATASYNC_NEW,
cancellable, error))
return FALSE;
if (!_ostree_sysroot_bump_mtime (sysroot, error))
return FALSE;
return TRUE;
} }
typedef struct { typedef struct {
@ -1497,6 +1502,7 @@ create_new_bootlinks (OstreeSysroot *self,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
GLNX_AUTO_PREFIX_ERROR ("Creating new current bootlinks", error);
glnx_autofd int ostree_dfd = -1; glnx_autofd int ostree_dfd = -1;
if (!glnx_opendirat (self->sysroot_fd, "ostree", TRUE, &ostree_dfd, error)) if (!glnx_opendirat (self->sysroot_fd, "ostree", TRUE, &ostree_dfd, error))
return FALSE; return FALSE;
@ -1559,6 +1565,7 @@ swap_bootlinks (OstreeSysroot *self,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
GLNX_AUTO_PREFIX_ERROR ("Swapping new version bootlinks", error);
glnx_autofd int ostree_dfd = -1; glnx_autofd int ostree_dfd = -1;
if (!glnx_opendirat (self->sysroot_fd, "ostree", TRUE, &ostree_dfd, error)) if (!glnx_opendirat (self->sysroot_fd, "ostree", TRUE, &ostree_dfd, error))
return FALSE; return FALSE;
@ -1628,6 +1635,7 @@ install_deployment_kernel (OstreeSysroot *sysroot,
GError **error) GError **error)
{ {
GLNX_AUTO_PREFIX_ERROR ("Installing kernel", error);
OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (deployment); OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (deployment);
g_autofree char *deployment_dirpath = ostree_sysroot_get_deployment_dirpath (sysroot, deployment); g_autofree char *deployment_dirpath = ostree_sysroot_get_deployment_dirpath (sysroot, deployment);
glnx_autofd int deployment_dfd = -1; glnx_autofd int deployment_dfd = -1;
@ -1936,23 +1944,18 @@ deployment_bootconfigs_equal (OstreeDeployment *a,
return FALSE; return FALSE;
{ {
OstreeBootconfigParser *a_bootconfig = ostree_deployment_get_bootconfig (a);
OstreeBootconfigParser *b_bootconfig = ostree_deployment_get_bootconfig (b);
const char *a_boot_options = ostree_bootconfig_parser_get (a_bootconfig, "options");
const char *b_boot_options = ostree_bootconfig_parser_get (b_bootconfig, "options");
g_autoptr(OstreeKernelArgs) a_kargs = NULL;
g_autoptr(OstreeKernelArgs) b_kargs = NULL;
g_autofree char *a_boot_options_without_ostree = NULL;
g_autofree char *b_boot_options_without_ostree = NULL;
/* We checksum the kernel arguments *except* ostree= */ /* We checksum the kernel arguments *except* ostree= */
a_kargs = _ostree_kernel_args_from_string (a_boot_options); OstreeBootconfigParser *a_bootconfig = ostree_deployment_get_bootconfig (a);
const char *a_boot_options = ostree_bootconfig_parser_get (a_bootconfig, "options");
g_autoptr(OstreeKernelArgs) a_kargs = _ostree_kernel_args_from_string (a_boot_options);
_ostree_kernel_args_replace (a_kargs, "ostree"); _ostree_kernel_args_replace (a_kargs, "ostree");
a_boot_options_without_ostree = _ostree_kernel_args_to_string (a_kargs); g_autofree char *a_boot_options_without_ostree = _ostree_kernel_args_to_string (a_kargs);
b_kargs = _ostree_kernel_args_from_string (b_boot_options); OstreeBootconfigParser *b_bootconfig = ostree_deployment_get_bootconfig (b);
const char *b_boot_options = ostree_bootconfig_parser_get (b_bootconfig, "options");
g_autoptr(OstreeKernelArgs) b_kargs = _ostree_kernel_args_from_string (b_boot_options);
_ostree_kernel_args_replace (b_kargs, "ostree"); _ostree_kernel_args_replace (b_kargs, "ostree");
b_boot_options_without_ostree = _ostree_kernel_args_to_string (b_kargs); g_autofree char *b_boot_options_without_ostree = _ostree_kernel_args_to_string (b_kargs);
if (strcmp (a_boot_options_without_ostree, b_boot_options_without_ostree) != 0) if (strcmp (a_boot_options_without_ostree, b_boot_options_without_ostree) != 0)
return FALSE; return FALSE;
@ -2083,12 +2086,7 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self,
GError **error) GError **error)
{ {
gboolean ret = FALSE; gboolean ret = FALSE;
guint i;
gboolean requires_new_bootversion = FALSE;
gboolean found_booted_deployment = FALSE;
gboolean bootloader_is_atomic = FALSE;
gboolean boot_was_ro_mount = FALSE; gboolean boot_was_ro_mount = FALSE;
SyncStats syncstats = { 0, };
g_autoptr(OstreeBootloader) bootloader = NULL; g_autoptr(OstreeBootloader) bootloader = NULL;
g_assert (self->loaded); g_assert (self->loaded);
@ -2102,11 +2100,12 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self,
* matching bootloader configuration, then we can just swap the * matching bootloader configuration, then we can just swap the
* subbootversion bootlinks. * subbootversion bootlinks.
*/ */
gboolean requires_new_bootversion = FALSE;
if (new_deployments->len != self->deployments->len) if (new_deployments->len != self->deployments->len)
requires_new_bootversion = TRUE; requires_new_bootversion = TRUE;
else else
{ {
for (i = 0; i < new_deployments->len; i++) for (guint i = 0; i < new_deployments->len; i++)
{ {
if (!deployment_bootconfigs_equal (new_deployments->pdata[i], if (!deployment_bootconfigs_equal (new_deployments->pdata[i],
self->deployments->pdata[i])) self->deployments->pdata[i]))
@ -2117,7 +2116,8 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self,
} }
} }
for (i = 0; i < new_deployments->len; i++) gboolean found_booted_deployment = FALSE;
for (guint i = 0; i < new_deployments->len; i++)
{ {
OstreeDeployment *deployment = new_deployments->pdata[i]; OstreeDeployment *deployment = new_deployments->pdata[i];
g_autoptr(GFile) deployment_root = NULL; g_autoptr(GFile) deployment_root = NULL;
@ -2143,15 +2143,14 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self,
goto out; goto out;
} }
gboolean bootloader_is_atomic = FALSE;
SyncStats syncstats = { 0, };
if (!requires_new_bootversion) if (!requires_new_bootversion)
{ {
if (!create_new_bootlinks (self, self->bootversion, if (!create_new_bootlinks (self, self->bootversion,
new_deployments, new_deployments,
cancellable, error)) cancellable, error))
{ goto out;
g_prefix_error (error, "Creating new current bootlinks: ");
goto out;
}
if (!full_system_sync (self, &syncstats, cancellable, error)) if (!full_system_sync (self, &syncstats, cancellable, error))
{ {
@ -2162,10 +2161,7 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self,
if (!swap_bootlinks (self, self->bootversion, if (!swap_bootlinks (self, self->bootversion,
new_deployments, new_deployments,
cancellable, error)) cancellable, error))
{ goto out;
g_prefix_error (error, "Swapping current bootlinks: ");
goto out;
}
bootloader_is_atomic = TRUE; bootloader_is_atomic = TRUE;
} }
@ -2208,13 +2204,10 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self,
/* Only show the osname in bootloader titles if there are multiple /* Only show the osname in bootloader titles if there are multiple
* osname's among the new deployments. Check for that here. */ * osname's among the new deployments. Check for that here. */
for (i = 1; i < new_deployments->len; i++) for (guint i = 1; i < new_deployments->len; i++)
{ {
const gchar *osname_0, *osname_i; const char *osname_0 = ostree_deployment_get_osname (new_deployments->pdata[0]);
const char *osname_i = ostree_deployment_get_osname (new_deployments->pdata[i]);
osname_0 = ostree_deployment_get_osname (new_deployments->pdata[0]);
osname_i = ostree_deployment_get_osname (new_deployments->pdata[i]);
if (!g_str_equal (osname_0, osname_i)) if (!g_str_equal (osname_0, osname_i))
{ {
show_osname = TRUE; show_osname = TRUE;
@ -2222,32 +2215,23 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self,
} }
} }
for (i = 0; i < new_deployments->len; i++) for (guint i = 0; i < new_deployments->len; i++)
{ {
OstreeDeployment *deployment = new_deployments->pdata[i]; OstreeDeployment *deployment = new_deployments->pdata[i];
if (!install_deployment_kernel (self, repo, new_bootversion, if (!install_deployment_kernel (self, repo, new_bootversion,
deployment, new_deployments->len, deployment, new_deployments->len,
show_osname, cancellable, error)) show_osname, cancellable, error))
{ goto out;
g_prefix_error (error, "Installing kernel: ");
goto out;
}
} }
/* Create and swap bootlinks for *new* version */ /* Create and swap bootlinks for *new* version */
if (!create_new_bootlinks (self, new_bootversion, if (!create_new_bootlinks (self, new_bootversion,
new_deployments, new_deployments,
cancellable, error)) cancellable, error))
{ goto out;
g_prefix_error (error, "Creating new version bootlinks: ");
goto out;
}
if (!swap_bootlinks (self, new_bootversion, new_deployments, if (!swap_bootlinks (self, new_bootversion, new_deployments,
cancellable, error)) cancellable, error))
{ goto out;
g_prefix_error (error, "Swapping new version bootlinks: ");
goto out;
}
g_debug ("Using bootloader: %s", bootloader ? g_debug ("Using bootloader: %s", bootloader ?
g_type_name (G_TYPE_FROM_INSTANCE (bootloader)) : "(none)"); g_type_name (G_TYPE_FROM_INSTANCE (bootloader)) : "(none)");
@ -2438,10 +2422,7 @@ ostree_sysroot_deploy_tree (OstreeSysroot *self,
glnx_autofd int deployment_dfd = -1; glnx_autofd int deployment_dfd = -1;
if (!checkout_deployment_tree (self, repo, new_deployment, &deployment_dfd, if (!checkout_deployment_tree (self, repo, new_deployment, &deployment_dfd,
cancellable, error)) cancellable, error))
{ return FALSE;
g_prefix_error (error, "Checking out tree: ");
return FALSE;
}
g_autoptr(OstreeKernelLayout) kernel_layout = NULL; g_autoptr(OstreeKernelLayout) kernel_layout = NULL;
if (!get_kernel_from_tree (deployment_dfd, &kernel_layout, if (!get_kernel_from_tree (deployment_dfd, &kernel_layout,
@ -2461,10 +2442,7 @@ ostree_sysroot_deploy_tree (OstreeSysroot *self,
deployment_dfd, deployment_dfd,
&sepolicy, &sepolicy,
cancellable, error)) cancellable, error))
{ return FALSE;
g_prefix_error (error, "During /etc merge: ");
return FALSE;
}
if (!selinux_relabel_var_if_needed (self, sepolicy, os_deploy_dfd, if (!selinux_relabel_var_if_needed (self, sepolicy, os_deploy_dfd,
cancellable, error)) cancellable, error))
@ -2477,24 +2455,13 @@ ostree_sysroot_deploy_tree (OstreeSysroot *self,
return FALSE; return FALSE;
} }
{ g_auto(OstreeSepolicyFsCreatecon) con = { 0, }; /* Don't fsync here, as we assume that's all done in
* ostree_sysroot_write_deployments().
if (!_ostree_sepolicy_preparefscreatecon (&con, sepolicy, */
"/etc/ostree/remotes.d/dummy.conf", if (!write_origin_file_internal (self, sepolicy, new_deployment, NULL,
0644, error)) GLNX_FILE_REPLACE_NODATASYNC,
return FALSE; cancellable, error))
return FALSE;
/* Don't fsync here, as we assume that's all done in
* ostree_sysroot_write_deployments().
*/
if (!write_origin_file_internal (self, new_deployment, NULL,
GLNX_FILE_REPLACE_NODATASYNC,
cancellable, error))
{
g_prefix_error (error, "Writing out origin file: ");
return FALSE;
}
}
/* After this, install_deployment_kernel() will set the other boot /* After this, install_deployment_kernel() will set the other boot
* options and write it out to disk. * options and write it out to disk.

View File

@ -50,6 +50,11 @@ struct OstreeSysroot {
GLnxLockFile lock; GLnxLockFile lock;
gboolean loaded; gboolean loaded;
gboolean ostree_booted;
gboolean root_is_sysroot; /* TRUE if sysroot_fd is pointed to rootfs "/" */
/* The device/inode for /, used to detect booted deployment */
dev_t root_device;
ino_t root_inode;
gboolean is_physical; /* TRUE if we're pointed at physical storage root and not a deployment */ gboolean is_physical; /* TRUE if we're pointed at physical storage root and not a deployment */
GPtrArray *deployments; GPtrArray *deployments;

View File

@ -37,13 +37,6 @@
#include "ostree-bootloader-syslinux.h" #include "ostree-bootloader-syslinux.h"
#include "ostree-bootloader-grub2.h" #include "ostree-bootloader-grub2.h"
static gboolean
find_booted_deployment (OstreeSysroot *self,
GPtrArray *deployments,
OstreeDeployment **out_deployment,
GCancellable *cancellable,
GError **error);
/** /**
* SECTION:ostree-sysroot * SECTION:ostree-sysroot
* @title: Root partition mount point * @title: Root partition mount point
@ -642,6 +635,24 @@ parse_deployment (OstreeSysroot *self,
&deployment_dfd, error)) &deployment_dfd, error))
return FALSE; return FALSE;
/* See if this is the booted deployment */
const gboolean looking_for_booted_deployment =
(self->ostree_booted && self->root_is_sysroot &&
!self->booted_deployment);
gboolean is_booted_deployment = FALSE;
if (looking_for_booted_deployment)
{
struct stat stbuf;
if (!glnx_fstat (deployment_dfd, &stbuf, error))
return FALSE;
/* A bit ugly, we're assigning to a sysroot-owned variable from deep in
* this parsing code. But eh, if something fails the sysroot state can't
* be relied on anyways.
*/
is_booted_deployment = (stbuf.st_dev == self->root_device &&
stbuf.st_ino == self->root_inode);
}
g_autoptr(GKeyFile) origin = NULL; g_autoptr(GKeyFile) origin = NULL;
if (!parse_origin (self, deployment_dfd, deploy_basename, &origin, if (!parse_origin (self, deployment_dfd, deploy_basename, &origin,
cancellable, error)) cancellable, error))
@ -672,35 +683,32 @@ parse_deployment (OstreeSysroot *self,
g_debug ("Deployment %s.%d unlocked=%d", treecsum, deployserial, ret_deployment->unlocked); g_debug ("Deployment %s.%d unlocked=%d", treecsum, deployserial, ret_deployment->unlocked);
if (is_booted_deployment)
self->booted_deployment = g_object_ref (ret_deployment);
if (out_deployment) if (out_deployment)
*out_deployment = g_steal_pointer (&ret_deployment); *out_deployment = g_steal_pointer (&ret_deployment);
return TRUE; return TRUE;
} }
/* Given a bootloader config, return the value part of the ostree= kernel
* argument.
*/
static char * static char *
get_ostree_kernel_arg_from_config (OstreeBootconfigParser *config) get_ostree_kernel_arg_from_config (OstreeBootconfigParser *config)
{ {
const char *options; const char *options = ostree_bootconfig_parser_get (config, "options");
char *ret = NULL;
char **opts, **iter;
options = ostree_bootconfig_parser_get (config, "options");
if (!options) if (!options)
return NULL; return NULL;
opts = g_strsplit (options, " ", -1); g_auto(GStrv) opts = g_strsplit (options, " ", -1);
for (iter = opts; *iter; iter++) for (char **iter = opts; *iter; iter++)
{ {
const char *opt = *iter; const char *opt = *iter;
if (g_str_has_prefix (opt, "ostree=")) if (g_str_has_prefix (opt, "ostree="))
{ return g_strdup (opt + strlen ("ostree="));
ret = g_strdup (opt + strlen ("ostree="));
break;
}
} }
g_strfreev (opts);
return ret; return NULL;
} }
static gboolean static gboolean
@ -797,6 +805,32 @@ ostree_sysroot_load_if_changed (OstreeSysroot *self,
if (!ensure_repo (self, error)) if (!ensure_repo (self, error))
return FALSE; return FALSE;
/* Gather some global state; first if we have the global ostree-booted flag;
* we'll use it to sanity check that we found a booted deployment for example.
* Second, we also find out whether sysroot == /.
*/
if (!self->loaded)
{
if (!glnx_fstatat_allow_noent (AT_FDCWD, "/run/ostree-booted", NULL, 0, error))
return FALSE;
self->ostree_booted = (errno == 0);
{ struct stat root_stbuf;
if (!glnx_fstatat (AT_FDCWD, "/", &root_stbuf, 0, error))
return FALSE;
self->root_device = root_stbuf.st_dev;
self->root_inode = root_stbuf.st_ino;
}
struct stat self_stbuf;
if (!glnx_fstat (self->sysroot_fd, &self_stbuf, error))
return FALSE;
self->root_is_sysroot =
(self->root_device == self_stbuf.st_dev &&
self->root_inode == self_stbuf.st_ino);
}
int bootversion = 0; int bootversion = 0;
if (!read_current_bootversion (self, &bootversion, cancellable, error)) if (!read_current_bootversion (self, &bootversion, cancellable, error))
return FALSE; return FALSE;
@ -837,11 +871,19 @@ ostree_sysroot_load_if_changed (OstreeSysroot *self,
{ {
OstreeBootconfigParser *config = boot_loader_configs->pdata[i]; OstreeBootconfigParser *config = boot_loader_configs->pdata[i];
/* Note this also sets self->booted_deployment */
if (!list_deployments_process_one_boot_entry (self, config, deployments, if (!list_deployments_process_one_boot_entry (self, config, deployments,
cancellable, error)) cancellable, error))
return FALSE; {
g_clear_object (&self->booted_deployment);
return FALSE;
}
} }
if (self->ostree_booted && self->root_is_sysroot
&& !self->booted_deployment)
return glnx_throw (error, "Unexpected state: /run/ostree-booted found and in / sysroot but not in a booted deployment");
g_ptr_array_sort (deployments, compare_deployments_by_boot_loader_version_reversed); g_ptr_array_sort (deployments, compare_deployments_by_boot_loader_version_reversed);
for (guint i = 0; i < deployments->len; i++) for (guint i = 0; i < deployments->len; i++)
{ {
@ -849,10 +891,6 @@ ostree_sysroot_load_if_changed (OstreeSysroot *self,
ostree_deployment_set_index (deployment, i); ostree_deployment_set_index (deployment, i);
} }
if (!find_booted_deployment (self, deployments, &self->booted_deployment,
cancellable, error))
return FALSE;
/* Determine whether we're "physical" or not, the first time we initialize */ /* Determine whether we're "physical" or not, the first time we initialize */
if (!self->loaded) if (!self->loaded)
{ {
@ -920,13 +958,10 @@ ostree_sysroot_get_booted_deployment (OstreeSysroot *self)
GPtrArray * GPtrArray *
ostree_sysroot_get_deployments (OstreeSysroot *self) ostree_sysroot_get_deployments (OstreeSysroot *self)
{ {
GPtrArray *copy;
guint i;
g_return_val_if_fail (self->loaded, NULL); g_return_val_if_fail (self->loaded, NULL);
copy = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref); GPtrArray *copy = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref);
for (i = 0; i < self->deployments->len; i++) for (guint i = 0; i < self->deployments->len; i++)
g_ptr_array_add (copy, g_object_ref (self->deployments->pdata[i])); g_ptr_array_add (copy, g_object_ref (self->deployments->pdata[i]));
return copy; return copy;
} }
@ -1071,10 +1106,9 @@ char *
_ostree_sysroot_join_lines (GPtrArray *lines) _ostree_sysroot_join_lines (GPtrArray *lines)
{ {
GString *buf = g_string_new (""); GString *buf = g_string_new ("");
guint i;
gboolean prev_was_empty = FALSE; gboolean prev_was_empty = FALSE;
for (i = 0; i < lines->len; i++) for (guint i = 0; i < lines->len; i++)
{ {
const char *line = lines->pdata[i]; const char *line = lines->pdata[i];
/* Special bit to remove extraneous empty lines */ /* Special bit to remove extraneous empty lines */
@ -1091,84 +1125,6 @@ _ostree_sysroot_join_lines (GPtrArray *lines)
return g_string_free (buf, FALSE); return g_string_free (buf, FALSE);
} }
static gboolean
parse_kernel_commandline (OstreeKernelArgs **out_args,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GFile) proc_cmdline = g_file_new_for_path ("/proc/cmdline");
g_autofree char *contents = NULL;
gsize len;
if (!g_file_load_contents (proc_cmdline, cancellable, &contents, &len, NULL,
error))
return FALSE;
g_strchomp (contents);
*out_args = _ostree_kernel_args_from_string (contents);
return TRUE;
}
static gboolean
find_booted_deployment (OstreeSysroot *self,
GPtrArray *deployments,
OstreeDeployment **out_deployment,
GCancellable *cancellable,
GError **error)
{
struct stat root_stbuf;
struct stat self_stbuf;
g_autoptr(OstreeDeployment) ret_deployment = NULL;
if (stat ("/", &root_stbuf) != 0)
return glnx_throw_errno_prefix (error, "stat /");
if (!ensure_sysroot_fd (self, error))
return FALSE;
if (fstat (self->sysroot_fd, &self_stbuf) != 0)
return glnx_throw_errno_prefix (error, "fstat");
if (root_stbuf.st_dev == self_stbuf.st_dev &&
root_stbuf.st_ino == self_stbuf.st_ino)
{
g_autoptr(OstreeKernelArgs) kernel_args = NULL;
if (!parse_kernel_commandline (&kernel_args, cancellable, error))
return FALSE;
const char *bootlink_arg = _ostree_kernel_args_get_last_value (kernel_args, "ostree");
if (bootlink_arg)
{
for (guint i = 0; i < deployments->len; i++)
{
OstreeDeployment *deployment = deployments->pdata[i];
g_autofree char *deployment_path = ostree_sysroot_get_deployment_dirpath (self, deployment);
struct stat stbuf;
if (fstatat (self->sysroot_fd, deployment_path, &stbuf, 0) != 0)
return glnx_throw_errno_prefix (error, "fstatat");
if (stbuf.st_dev == root_stbuf.st_dev &&
stbuf.st_ino == root_stbuf.st_ino)
{
ret_deployment = g_object_ref (deployment);
break;
}
}
if (ret_deployment == NULL)
return glnx_throw (error, "Unexpected state: ostree= kernel argument found, but / is not a deployment root");
}
else
{
/* Not an ostree system */
}
}
ot_transfer_out_value (out_deployment, &ret_deployment);
return TRUE;
}
/** /**
* ostree_sysroot_query_deployments_for: * ostree_sysroot_query_deployments_for:
* @self: Sysroot * @self: Sysroot
@ -1202,6 +1158,10 @@ ostree_sysroot_query_deployments_for (OstreeSysroot *self,
{ {
OstreeDeployment *deployment = self->deployments->pdata[i]; OstreeDeployment *deployment = self->deployments->pdata[i];
/* Ignore deployments not for this osname */
if (strcmp (ostree_deployment_get_osname (deployment), osname) != 0)
continue;
/* Is this deployment booted? If so, note we're past the booted */ /* Is this deployment booted? If so, note we're past the booted */
if (self->booted_deployment != NULL && if (self->booted_deployment != NULL &&
ostree_deployment_equal (deployment, self->booted_deployment)) ostree_deployment_equal (deployment, self->booted_deployment))
@ -1210,10 +1170,6 @@ ostree_sysroot_query_deployments_for (OstreeSysroot *self,
continue; continue;
} }
/* Ignore deployments not for this osname */
if (strcmp (ostree_deployment_get_osname (deployment), osname) != 0)
continue;
if (!found_booted && !ret_pending) if (!found_booted && !ret_pending)
ret_pending = g_object_ref (deployment); ret_pending = g_object_ref (deployment);
else if (found_booted && !ret_rollback) else if (found_booted && !ret_rollback)
@ -1572,12 +1528,14 @@ ostree_sysroot_simple_write_deployment (OstreeSysroot *sysroot,
/* Retain deployment if: /* Retain deployment if:
* - we're explicitly asked to, or * - we're explicitly asked to, or
* - it's pinned
* - the deployment is for another osname, or * - the deployment is for another osname, or
* - we're keeping pending deployments and this is a pending deployment, or * - we're keeping pending deployments and this is a pending deployment, or
* - this is the merge or boot deployment, or * - this is the merge or boot deployment, or
* - we're keeping rollback deployments and this is a rollback deployment * - we're keeping rollback deployments and this is a rollback deployment
*/ */
if (retain if (retain
|| ostree_deployment_is_pinned (deployment)
|| !osname_matches || !osname_matches
|| (retain_pending && !passed_crossover) || (retain_pending && !passed_crossover)
|| (is_booted || is_merge) || (is_booted || is_merge)
@ -1832,3 +1790,45 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self,
return TRUE; return TRUE;
} }
/**
* ostree_sysroot_deployment_set_pinned:
* @self: Sysroot
* @deployment: A deployment
* @is_pinned: Whether or not deployment will be automatically GC'd
* @error: Error
*
* By default, deployments may be subject to garbage collection. Typical uses of
* libostree only retain at most 2 deployments. If @is_pinned is `TRUE`, a
* metadata bit will be set causing libostree to avoid automatic GC of the
* deployment. However, this is really an "advisory" note; it's still possible
* for e.g. older versions of libostree unaware of pinning to GC the deployment.
*
* This function does nothing and returns successfully if the deployment
* is already in the desired pinning state.
*
* Since: 2018.3
*/
gboolean
ostree_sysroot_deployment_set_pinned (OstreeSysroot *self,
OstreeDeployment *deployment,
gboolean is_pinned,
GError **error)
{
const gboolean current_pin = ostree_deployment_is_pinned (deployment);
if (is_pinned == current_pin)
return TRUE;
g_autoptr(OstreeDeployment) deployment_clone = ostree_deployment_clone (deployment);
GKeyFile *origin_clone = ostree_deployment_get_origin (deployment_clone);
if (is_pinned)
g_key_file_set_boolean (origin_clone, OSTREE_ORIGIN_TRANSIENT_GROUP, "pinned", TRUE);
else
g_key_file_remove_key (origin_clone, OSTREE_ORIGIN_TRANSIENT_GROUP, "pinned", NULL);
if (!ostree_sysroot_write_origin_file (self, deployment, origin_clone, NULL, error))
return FALSE;
return TRUE;
}

View File

@ -181,6 +181,12 @@ gboolean ostree_sysroot_deployment_set_mutable (OstreeSysroot *self,
GCancellable *cancellable, GCancellable *cancellable,
GError **error); GError **error);
_OSTREE_PUBLIC
gboolean ostree_sysroot_deployment_set_pinned (OstreeSysroot *self,
OstreeDeployment *deployment,
gboolean is_pinned,
GError **error);
_OSTREE_PUBLIC _OSTREE_PUBLIC
gboolean ostree_sysroot_deployment_unlock (OstreeSysroot *self, gboolean ostree_sysroot_deployment_unlock (OstreeSysroot *self,
OstreeDeployment *deployment, OstreeDeployment *deployment,

View File

@ -43,7 +43,7 @@
* *
* Since: 2017.4 * Since: 2017.4
*/ */
#define OSTREE_RELEASE_VERSION (2) #define OSTREE_RELEASE_VERSION (4)
/** /**
* OSTREE_VERSION * OSTREE_VERSION
@ -52,7 +52,7 @@
* *
* Since: 2017.4 * Since: 2017.4
*/ */
#define OSTREE_VERSION (2018.2) #define OSTREE_VERSION (2018.4)
/** /**
* OSTREE_VERSION_S: * OSTREE_VERSION_S:
@ -62,7 +62,7 @@
* *
* Since: 2017.4 * Since: 2017.4
*/ */
#define OSTREE_VERSION_S "2018.2" #define OSTREE_VERSION_S "2018.4"
#define OSTREE_ENCODE_VERSION(year,release) \ #define OSTREE_ENCODE_VERSION(year,release) \
((year) << 16 | (release)) ((year) << 16 | (release))

View File

@ -141,15 +141,10 @@ main (int argc,
if (error != NULL) if (error != NULL)
{ {
int is_tty = isatty (1); g_printerr ("%s%serror:%s%s %s\n",
const char *prefix = ""; ot_get_red_start (), ot_get_bold_start (),
const char *suffix = ""; ot_get_bold_end (), ot_get_red_end (),
if (is_tty) error->message);
{
prefix = "\x1b[31m\x1b[1m"; /* red, bold */
suffix = "\x1b[22m\x1b[0m"; /* bold off, color reset */
}
g_printerr ("%serror: %s%s\n", prefix, suffix, error->message);
} }
return ret; return ret;

View File

@ -680,15 +680,10 @@ main (int argc,
if (!run (argc, argv, cancellable, &error)) if (!run (argc, argv, cancellable, &error))
{ {
int is_tty = isatty (1); g_printerr ("%s%serror:%s%s %s\n",
const char *prefix = ""; ot_get_red_start (), ot_get_bold_start (),
const char *suffix = ""; ot_get_bold_end (), ot_get_red_end (),
if (is_tty) error->message);
{
prefix = "\x1b[31m\x1b[1m"; /* red, bold */
suffix = "\x1b[22m\x1b[0m"; /* bold off, color reset */
}
g_printerr ("%serror: %s%s\n", prefix, suffix, error->message);
return 1; return 1;
} }

View File

@ -30,11 +30,6 @@
#include <glib/gi18n.h> #include <glib/gi18n.h>
/* ATTENTION:
* Please remember to update the bash-completion script (bash/ostree) and
* man page (man/ostree-admin-cleanup.xml) when changing the option list.
*/
static GOptionEntry options[] = { static GOptionEntry options[] = {
{ NULL } { NULL }
}; };

View File

@ -45,11 +45,6 @@ static char *opt_osname;
static char *opt_origin_path; static char *opt_origin_path;
static gboolean opt_kernel_arg_none; static gboolean opt_kernel_arg_none;
/* ATTENTION:
* Please remember to update the bash-completion script (bash/ostree) and
* man page (man/ostree-admin-deploy.xml) when changing the option list.
*/
static GOptionEntry options[] = { static GOptionEntry options[] = {
{ "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Use a different operating system root than the current one", "OSNAME" }, { "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Use a different operating system root than the current one", "OSNAME" },
{ "origin-file", 0, 0, G_OPTION_ARG_FILENAME, &opt_origin_path, "Specify origin file", "FILENAME" }, { "origin-file", 0, 0, G_OPTION_ARG_FILENAME, &opt_origin_path, "Specify origin file", "FILENAME" },

View File

@ -32,11 +32,6 @@
static char *opt_osname; static char *opt_osname;
/* ATTENTION:
* Please remember to update the bash-completion script (bash/ostree) and
* man page (man/ostree-admin-config-diff.xml) when changing the option list.
*/
static GOptionEntry options[] = { static GOptionEntry options[] = {
{ "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Use a different operating system root than the current one", "OSNAME" }, { "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Use a different operating system root than the current one", "OSNAME" },
{ NULL } { NULL }

View File

@ -30,11 +30,6 @@
#include <glib/gi18n.h> #include <glib/gi18n.h>
/* ATTENTION:
* Please remember to update the bash-completion script (bash/ostree) and
* man page (man/ostree-admin-init-fs.xml) when changing the option list.
*/
static GOptionEntry options[] = { static GOptionEntry options[] = {
{ NULL } { NULL }
}; };

View File

@ -30,11 +30,6 @@
#include <glib/gi18n.h> #include <glib/gi18n.h>
/* ATTENTION:
* Please remember to update the bash-completion script (bash/ostree) and
* man page (man/ostree-admin-os-init.xml) when changing the option list.
*/
static GOptionEntry options[] = { static GOptionEntry options[] = {
{ NULL } { NULL }
}; };

View File

@ -0,0 +1,75 @@
/*
* Copyright (C) 2018 Colin Walters <walters@verbum.org>
*
* SPDX-License-Identifier: LGPL-2.0+
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <stdlib.h>
#include "ot-main.h"
#include "ot-admin-builtins.h"
#include "ot-admin-functions.h"
#include "ostree.h"
#include "otutil.h"
static gboolean opt_unpin;
static GOptionEntry options[] = {
{ "unpin", 'u', 0, G_OPTION_ARG_NONE, &opt_unpin, "Unset pin", NULL },
{ NULL }
};
gboolean
ot_admin_builtin_pin (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = g_option_context_new ("INDEX");
g_autoptr(OstreeSysroot) sysroot = NULL;
if (!ostree_admin_option_context_parse (context, options, &argc, &argv,
OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER,
invocation, &sysroot, cancellable, error))
return FALSE;
if (argc < 2)
{
ot_util_usage_error (context, "INDEX must be specified", error);
return FALSE;
}
const char *deploy_index_str = argv[1];
const int deploy_index = atoi (deploy_index_str);
g_autoptr(OstreeDeployment) target_deployment = ot_admin_get_indexed_deployment (sysroot, deploy_index, error);
if (!target_deployment)
return FALSE;
gboolean current_pin = ostree_deployment_is_pinned (target_deployment);
const gboolean desired_pin = !opt_unpin;
if (current_pin == desired_pin)
g_print ("Deployment is already %s\n", current_pin ? "pinned" : "unpinned");
else
{
if (!ostree_sysroot_deployment_set_pinned (sysroot, target_deployment, desired_pin, error))
return FALSE;
g_print ("Deployment is now %s\n", desired_pin ? "pinned" : "unpinned");
}
return TRUE;
}

View File

@ -35,11 +35,6 @@
static int opt_index = -1; static int opt_index = -1;
static char **opt_set; static char **opt_set;
/* ATTENTION:
* Please remember to update the bash-completion script (bash/ostree) and
* man page (man/ostree-admin-set-origin.xml) when changing the option list.
*/
static GOptionEntry options[] = { static GOptionEntry options[] = {
{ "set", 's', 0, G_OPTION_ARG_STRING_ARRAY, &opt_set, "Set config option KEY=VALUE for remote", "KEY=VALUE" }, { "set", 's', 0, G_OPTION_ARG_STRING_ARRAY, &opt_set, "Set config option KEY=VALUE for remote", "KEY=VALUE" },
{ "index", 0, 0, G_OPTION_ARG_INT, &opt_index, "Operate on the deployment INDEX, starting from zero", "INDEX" }, { "index", 0, 0, G_OPTION_ARG_INT, &opt_index, "Operate on the deployment INDEX, starting from zero", "INDEX" },

View File

@ -27,14 +27,10 @@
#include "ot-admin-builtins.h" #include "ot-admin-builtins.h"
#include "ot-admin-functions.h" #include "ot-admin-functions.h"
#include "ostree.h" #include "ostree.h"
#include "libglnx.h"
#include <glib/gi18n.h> #include <glib/gi18n.h>
/* ATTENTION:
* Please remember to update the bash-completion script (bash/ostree) and
* man page (man/ostree-admin-status.xml) when changing the option list.
*/
static GOptionEntry options[] = { static GOptionEntry options[] = {
{ NULL } { NULL }
}; };
@ -66,13 +62,116 @@ deployment_get_gpg_verify (OstreeDeployment *deployment,
return gpg_verify; return gpg_verify;
} }
static gboolean
deployment_print_status (OstreeSysroot *sysroot,
OstreeRepo *repo,
OstreeDeployment *deployment,
gboolean is_booted,
gboolean is_pending,
gboolean is_rollback,
GCancellable *cancellable,
GError **error)
{
const char *ref = ostree_deployment_get_csum (deployment);
/* Load the backing commit; shouldn't normally fail, but if it does,
* we stumble on.
*/
g_autoptr(GVariant) commit = NULL;
(void)ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, ref,
&commit, NULL);
g_autoptr(GVariant) commit_metadata = NULL;
if (commit)
commit_metadata = g_variant_get_child_value (commit, 0);
const char *version = NULL;
const char *source_title = NULL;
if (commit_metadata)
{
(void) g_variant_lookup (commit_metadata, OSTREE_COMMIT_META_KEY_VERSION, "&s", &version);
(void) g_variant_lookup (commit_metadata, OSTREE_COMMIT_META_KEY_SOURCE_TITLE, "&s", &source_title);
}
GKeyFile *origin = ostree_deployment_get_origin (deployment);
const char *deployment_status = "";
if (is_pending)
deployment_status = " (pending)";
else if (is_rollback)
deployment_status = " (rollback)";
g_print ("%c %s %s.%d%s\n",
is_booted ? '*' : ' ',
ostree_deployment_get_osname (deployment),
ostree_deployment_get_csum (deployment),
ostree_deployment_get_deployserial (deployment),
deployment_status);
if (version)
g_print (" Version: %s\n", version);
OstreeDeploymentUnlockedState unlocked = ostree_deployment_get_unlocked (deployment);
switch (unlocked)
{
case OSTREE_DEPLOYMENT_UNLOCKED_NONE:
break;
default:
g_print (" %s%sUnlocked: %s%s%s\n", ot_get_red_start (), ot_get_bold_start (),
ostree_deployment_unlocked_state_to_string (unlocked),
ot_get_bold_end (), ot_get_red_end ());
}
if (ostree_deployment_is_pinned (deployment))
g_print (" Pinned: yes\n");
if (!origin)
g_print (" origin: none\n");
else
{
g_autofree char *origin_refspec = g_key_file_get_string (origin, "origin", "refspec", NULL);
if (!origin_refspec)
g_print (" origin: <unknown origin type>\n");
else
g_print (" origin refspec: %s\n", origin_refspec);
if (source_title)
g_print (" `- %s\n", source_title);
}
if (deployment_get_gpg_verify (deployment, repo))
{
g_autoptr(GString) output_buffer = g_string_sized_new (256);
/* Print any digital signatures on this commit. */
g_autoptr(GError) local_error = NULL;
g_autoptr(OstreeGpgVerifyResult) result =
ostree_repo_verify_commit_ext (repo, ref, NULL, NULL,
cancellable, &local_error);
/* G_IO_ERROR_NOT_FOUND just means the commit is not signed. */
if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
g_clear_error (&local_error);
return TRUE;
}
else if (local_error != NULL)
{
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
const guint n_signatures = ostree_gpg_verify_result_count_all (result);
for (guint jj = 0; jj < n_signatures; jj++)
{
ostree_gpg_verify_result_describe (result, jj, output_buffer, " GPG: ",
OSTREE_GPG_SIGNATURE_FORMAT_DEFAULT);
}
g_print ("%s", output_buffer->str);
}
return TRUE;
}
gboolean gboolean
ot_admin_builtin_status (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error) ot_admin_builtin_status (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
{ {
const int is_tty = isatty (1);
const char *red_bold_prefix = is_tty ? "\x1b[31m\x1b[1m" : "";
const char *red_bold_suffix = is_tty ? "\x1b[22m\x1b[0m" : "";
g_autoptr(GOptionContext) context = g_option_context_new (""); g_autoptr(GOptionContext) context = g_option_context_new ("");
g_autoptr(OstreeSysroot) sysroot = NULL; g_autoptr(OstreeSysroot) sysroot = NULL;
@ -103,96 +202,13 @@ ot_admin_builtin_status (int argc, char **argv, OstreeCommandInvocation *invocat
for (guint i = 0; i < deployments->len; i++) for (guint i = 0; i < deployments->len; i++)
{ {
OstreeDeployment *deployment = deployments->pdata[i]; OstreeDeployment *deployment = deployments->pdata[i];
const char *ref = ostree_deployment_get_csum (deployment); if (!deployment_print_status (sysroot, repo, deployment,
deployment == booted_deployment,
/* Load the backing commit; shouldn't normally fail, but if it does, deployment == pending_deployment,
* we stumble on. deployment == rollback_deployment,
*/ cancellable,
g_autoptr(GVariant) commit = NULL; error))
(void)ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, ref, return FALSE;
&commit, NULL);
g_autoptr(GVariant) commit_metadata = NULL;
if (commit)
commit_metadata = g_variant_get_child_value (commit, 0);
const char *version = NULL;
const char *source_title = NULL;
if (commit_metadata)
{
(void) g_variant_lookup (commit_metadata, OSTREE_COMMIT_META_KEY_VERSION, "&s", &version);
(void) g_variant_lookup (commit_metadata, OSTREE_COMMIT_META_KEY_SOURCE_TITLE, "&s", &source_title);
}
GKeyFile *origin = ostree_deployment_get_origin (deployment);
const char *deployment_status = "";
if (deployment == pending_deployment)
deployment_status = " (pending)";
else if (deployment == rollback_deployment)
deployment_status = " (rollback)";
g_print ("%c %s %s.%d%s\n",
deployment == booted_deployment ? '*' : ' ',
ostree_deployment_get_osname (deployment),
ostree_deployment_get_csum (deployment),
ostree_deployment_get_deployserial (deployment),
deployment_status);
if (version)
g_print (" Version: %s\n", version);
OstreeDeploymentUnlockedState unlocked = ostree_deployment_get_unlocked (deployment);
switch (unlocked)
{
case OSTREE_DEPLOYMENT_UNLOCKED_NONE:
break;
default:
g_print (" %sUnlocked: %s%s\n", red_bold_prefix,
ostree_deployment_unlocked_state_to_string (unlocked),
red_bold_suffix);
}
if (!origin)
g_print (" origin: none\n");
else
{
g_autofree char *origin_refspec = g_key_file_get_string (origin, "origin", "refspec", NULL);
if (!origin_refspec)
g_print (" origin: <unknown origin type>\n");
else
g_print (" origin refspec: %s\n", origin_refspec);
if (source_title)
g_print (" `- %s\n", source_title);
}
if (deployment_get_gpg_verify (deployment, repo))
{
g_autoptr(GString) output_buffer = g_string_sized_new (256);
/* Print any digital signatures on this commit. */
g_autoptr(GError) local_error = NULL;
g_autoptr(OstreeGpgVerifyResult) result =
ostree_repo_verify_commit_ext (repo, ref, NULL, NULL,
cancellable, &local_error);
/* G_IO_ERROR_NOT_FOUND just means the commit is not signed. */
if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
g_clear_error (&local_error);
continue;
}
else if (local_error != NULL)
{
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
const guint n_signatures = ostree_gpg_verify_result_count_all (result);
for (guint jj = 0; jj < n_signatures; jj++)
{
ostree_gpg_verify_result_describe (result, jj, output_buffer, " GPG: ",
OSTREE_GPG_SIGNATURE_FORMAT_DEFAULT);
}
g_print ("%s", output_buffer->str);
}
} }
} }

View File

@ -34,11 +34,6 @@
static gboolean opt_reboot; static gboolean opt_reboot;
static char *opt_osname; static char *opt_osname;
/* ATTENTION:
* Please remember to update the bash-completion script (bash/ostree) and
* man page (man/ostree-admin-switch.xml) when changing the option list.
*/
static GOptionEntry options[] = { static GOptionEntry options[] = {
{ "reboot", 'r', 0, G_OPTION_ARG_NONE, &opt_reboot, "Reboot after switching trees", NULL }, { "reboot", 'r', 0, G_OPTION_ARG_NONE, &opt_reboot, "Reboot after switching trees", NULL },
{ "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Use a different operating system root than the current one", "OSNAME" }, { "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Use a different operating system root than the current one", "OSNAME" },

View File

@ -29,11 +29,6 @@
#include "ostree.h" #include "ostree.h"
#include "otutil.h" #include "otutil.h"
/* ATTENTION:
* Please remember to update the bash-completion script (bash/ostree) and
* man page (man/ostree-admin-undeploy.xml) when changing the option list.
*/
static GOptionEntry options[] = { static GOptionEntry options[] = {
{ NULL } { NULL }
}; };

View File

@ -34,11 +34,6 @@
static gboolean opt_hotfix; static gboolean opt_hotfix;
/* ATTENTION:
* Please remember to update the bash-completion script (bash/ostree) and
* man page (man/ostree-admin-unlock.xml) when changing the option list.
*/
static GOptionEntry options[] = { static GOptionEntry options[] = {
{ "hotfix", 0, 0, G_OPTION_ARG_NONE, &opt_hotfix, "Retain changes across reboots", NULL }, { "hotfix", 0, 0, G_OPTION_ARG_NONE, &opt_hotfix, "Retain changes across reboots", NULL },
{ NULL } { NULL }

View File

@ -40,11 +40,6 @@ static gboolean opt_deploy_only;
static char *opt_osname; static char *opt_osname;
static char *opt_override_commit; static char *opt_override_commit;
/* ATTENTION:
* Please remember to update the bash-completion script (bash/ostree) and
* man page (man/ostree-admin-upgrade.xml) when changing the option list.
*/
static GOptionEntry options[] = { static GOptionEntry options[] = {
{ "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Use a different operating system root than the current one", "OSNAME" }, { "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Use a different operating system root than the current one", "OSNAME" },
{ "reboot", 'r', 0, G_OPTION_ARG_NONE, &opt_reboot, "Reboot after a successful upgrade", NULL }, { "reboot", 'r', 0, G_OPTION_ARG_NONE, &opt_reboot, "Reboot after a successful upgrade", NULL },
@ -88,33 +83,18 @@ ot_admin_builtin_upgrade (int argc, char **argv, OstreeCommandInvocation *invoca
g_autoptr(GKeyFile) origin = ostree_sysroot_upgrader_dup_origin (upgrader); g_autoptr(GKeyFile) origin = ostree_sysroot_upgrader_dup_origin (upgrader);
if (origin != NULL) if (origin != NULL)
{ {
gboolean origin_changed = FALSE; /* Should we consider requiring --discard-hotfix here? */
ostree_deployment_origin_remove_transient_state (origin);
if (opt_override_commit != NULL) if (opt_override_commit != NULL)
{ {
/* Override the commit to pull and deploy. */ /* Override the commit to pull and deploy. */
g_key_file_set_string (origin, "origin", g_key_file_set_string (origin, "origin",
"override-commit", "override-commit",
opt_override_commit); opt_override_commit);
origin_changed = TRUE;
}
else
{
/* Strip any override-commit from the origin file so
* we always upgrade to the latest available commit. */
origin_changed = g_key_file_remove_key (origin, "origin",
"override-commit", NULL);
} }
/* Should we consider requiring --discard-hotfix here? */ if (!ostree_sysroot_upgrader_set_origin (upgrader, origin, NULL, error))
origin_changed |= g_key_file_remove_key (origin, "origin", "unlocked", NULL); return FALSE;
if (origin_changed)
{
/* XXX GCancellable parameter is not used. */
if (!ostree_sysroot_upgrader_set_origin (upgrader, origin, NULL, error))
return FALSE;
}
} }
gboolean changed; gboolean changed;

View File

@ -39,6 +39,7 @@ BUILTINPROTO(init_fs);
BUILTINPROTO(undeploy); BUILTINPROTO(undeploy);
BUILTINPROTO(deploy); BUILTINPROTO(deploy);
BUILTINPROTO(cleanup); BUILTINPROTO(cleanup);
BUILTINPROTO(pin);
BUILTINPROTO(unlock); BUILTINPROTO(unlock);
BUILTINPROTO(status); BUILTINPROTO(status);
BUILTINPROTO(set_origin); BUILTINPROTO(set_origin);

View File

@ -28,11 +28,6 @@
#include "otutil.h" #include "otutil.h"
/* ATTENTION:
* Please remember to update the bash-completion script (bash/ostree) and
* man page (man/ostree-admin-instutil.xml) when changing the option list.
*/
static GOptionEntry options[] = { static GOptionEntry options[] = {
{ NULL } { NULL }
}; };

View File

@ -173,11 +173,6 @@ selinux_relabel_dir (OstreeSePolicy *sepolicy,
return ret; return ret;
} }
/* ATTENTION:
* Please remember to update the bash-completion script (bash/ostree) and
* man page (man/ostree-admin-instutil.xml) when changing the option list.
*/
static GOptionEntry options[] = { static GOptionEntry options[] = {
{ NULL } { NULL }
}; };

View File

@ -34,11 +34,6 @@ static gboolean opt_merge;
static char **opt_replace; static char **opt_replace;
static char **opt_append; static char **opt_append;
/* ATTENTION:
* Please remember to update the bash-completion script (bash/ostree) and
* man page (man/ostree-admin-instutil.xml) when changing the option list.
*/
static GOptionEntry options[] = { static GOptionEntry options[] = {
{ "import-proc-cmdline", 0, 0, G_OPTION_ARG_NONE, &opt_proc_cmdline, "Import current /proc/cmdline", NULL }, { "import-proc-cmdline", 0, 0, G_OPTION_ARG_NONE, &opt_proc_cmdline, "Import current /proc/cmdline", NULL },
{ "merge", 0, 0, G_OPTION_ARG_NONE, &opt_merge, "Merge with previous command line", NULL }, { "merge", 0, 0, G_OPTION_ARG_NONE, &opt_merge, "Merge with previous command line", NULL },

View File

@ -54,6 +54,9 @@ static OstreeCommand admin_subcommands[] = {
{ "set-origin", OSTREE_BUILTIN_FLAG_NO_REPO, { "set-origin", OSTREE_BUILTIN_FLAG_NO_REPO,
ot_admin_builtin_set_origin, ot_admin_builtin_set_origin,
"Set Origin and create a new origin file" }, "Set Origin and create a new origin file" },
{ "pin", OSTREE_BUILTIN_FLAG_NO_REPO,
ot_admin_builtin_pin,
"Change the \"pinning\" state of a deployment" },
{ "status", OSTREE_BUILTIN_FLAG_NO_REPO, { "status", OSTREE_BUILTIN_FLAG_NO_REPO,
ot_admin_builtin_status, ot_admin_builtin_status,
"List deployments" }, "List deployments" },

View File

@ -174,6 +174,15 @@ ostree_builtin_prune (int argc, char **argv, OstreeCommandInvocation *invocation
else if (!delete_commit (repo, opt_delete_commit, cancellable, error)) else if (!delete_commit (repo, opt_delete_commit, cancellable, error))
return FALSE; return FALSE;
} }
else
{
/* In the future we should make this useful, but for now let's
* error out since what we were doing before was very misleading.
* https://github.com/ostreedev/ostree/issues/1479
*/
if (opt_static_deltas_only)
return glnx_throw (error, "--static-deltas-only requires --delete-commit; see https://github.com/ostreedev/ostree/issues/1479");
}
OstreeRepoPruneFlags pruneflags = 0; OstreeRepoPruneFlags pruneflags = 0;
if (opt_refs_only) if (opt_refs_only)

View File

@ -41,6 +41,7 @@ static gboolean opt_bareuseronly_files;
static char** opt_subpaths; static char** opt_subpaths;
static char** opt_http_headers; static char** opt_http_headers;
static char* opt_cache_dir; static char* opt_cache_dir;
static char* opt_append_user_agent;
static int opt_depth = 0; static int opt_depth = 0;
static int opt_frequency = 0; static int opt_frequency = 0;
static char* opt_url; static char* opt_url;
@ -69,6 +70,8 @@ static GOptionEntry options[] = {
{ "update-frequency", 0, 0, G_OPTION_ARG_INT, &opt_frequency, "Sets the update frequency, in milliseconds (0=1000ms) (default: 0)", "FREQUENCY" }, { "update-frequency", 0, 0, G_OPTION_ARG_INT, &opt_frequency, "Sets the update frequency, in milliseconds (0=1000ms) (default: 0)", "FREQUENCY" },
{ "localcache-repo", 'L', 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_localcache_repos, "Add REPO as local cache source for objects during this pull", "REPO" }, { "localcache-repo", 'L', 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_localcache_repos, "Add REPO as local cache source for objects during this pull", "REPO" },
{ "timestamp-check", 'T', 0, G_OPTION_ARG_NONE, &opt_timestamp_check, "Require fetched commits to have newer timestamps", NULL }, { "timestamp-check", 'T', 0, G_OPTION_ARG_NONE, &opt_timestamp_check, "Require fetched commits to have newer timestamps", NULL },
/* let's leave this hidden for now; we just need it for tests */
{ "append-user-agent", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &opt_append_user_agent, "Append string to user agent", NULL },
{ NULL } { NULL }
}; };
@ -333,6 +336,10 @@ ostree_builtin_pull (int argc, char **argv, OstreeCommandInvocation *invocation,
g_variant_new_variant (g_variant_builder_end (&hdr_builder))); g_variant_new_variant (g_variant_builder_end (&hdr_builder)));
} }
if (opt_append_user_agent)
g_variant_builder_add (&builder, "{s@v}", "append-user-agent",
g_variant_new_variant (g_variant_new_string (opt_append_user_agent)));
if (!opt_dry_run) if (!opt_dry_run)
{ {
if (console.is_tty) if (console.is_tty)

View File

@ -91,3 +91,18 @@ gboolean ostree_ensure_repo_writable (OstreeRepo *repo, GError **error);
void ostree_print_gpg_verify_result (OstreeGpgVerifyResult *result); void ostree_print_gpg_verify_result (OstreeGpgVerifyResult *result);
gboolean ot_enable_tombstone_commits (OstreeRepo *repo, GError **error); gboolean ot_enable_tombstone_commits (OstreeRepo *repo, GError **error);
/* Copied from rpm-ostree's rpmostree-libbuiltin.h */
#define TERM_ESCAPE_SEQUENCE(type,seq) \
static inline const char* ot_get_##type (void) { \
if (glnx_stdout_is_tty ()) \
return seq; \
return ""; \
}
TERM_ESCAPE_SEQUENCE(red_start, "\x1b[31m")
TERM_ESCAPE_SEQUENCE(red_end, "\x1b[22m")
TERM_ESCAPE_SEQUENCE(bold_start, "\x1b[1m")
TERM_ESCAPE_SEQUENCE(bold_end, "\x1b[0m")
#undef TERM_ESCAPE_SEQUENCE

View File

@ -104,4 +104,19 @@ read_proc_cmdline_ostree (void)
return ret; return ret;
} }
/* This is an API for other projects to determine whether or not the
* currently running system is ostree-controlled.
*/
static inline void
touch_run_ostree (void)
{
int fd = open ("/run/ostree-booted", O_CREAT | O_WRONLY | O_NOCTTY | O_CLOEXEC, 0640);
/* We ignore failures here in case /run isn't mounted...not much we
* can do about that, but we don't want to fail.
*/
if (fd == -1)
return;
(void) close (fd);
}
#endif /* __OSTREE_MOUNT_UTIL_H_ */ #endif /* __OSTREE_MOUNT_UTIL_H_ */

View File

@ -48,23 +48,6 @@
#include "ostree-mount-util.h" #include "ostree-mount-util.h"
/* This is an API for other projects to determine whether or not the
* currently running system is ostree-controlled.
*/
static void
touch_run_ostree (void)
{
int fd;
fd = open ("/run/ostree-booted", O_CREAT | O_WRONLY | O_NOCTTY | O_CLOEXEC, 0640);
/* We ignore failures here in case /run isn't mounted...not much we
* can do about that, but we don't want to fail.
*/
if (fd == -1)
return;
(void) close (fd);
}
static char* static char*
resolve_deploy_path (const char * root_mountpoint) resolve_deploy_path (const char * root_mountpoint)
{ {
@ -205,7 +188,13 @@ main(int argc, char *argv[])
err (EXIT_FAILURE, "failed to bind mount (class:readonly) /usr"); err (EXIT_FAILURE, "failed to bind mount (class:readonly) /usr");
} }
touch_run_ostree ();
/* We only stamp /run now if we're running in an initramfs, i.e. we're
* not pid 1. Otherwise it's handled later via ostree-remount.service.
* https://mail.gnome.org/archives/ostree-list/2018-March/msg00012.html
*/
if (getpid () != 1)
touch_run_ostree ();
if (strcmp(root_mountpoint, "/") == 0) if (strcmp(root_mountpoint, "/") == 0)
{ {

View File

@ -46,6 +46,16 @@ main(int argc, char *argv[])
struct stat stbuf; struct stat stbuf;
int i; int i;
/* See comments in ostree-prepare-root.c for this.
*
* This service is triggered via
* ConditionKernelCommandLine=ostree
* but it's a lot easier for various bits of userspace to check for
* a file versus parsing the kernel cmdline. So let's ensure
* the stamp file is created here too.
*/
touch_run_ostree ();
/* The /sysroot mount needs to be private to avoid having a mount for e.g. /var/cache /* The /sysroot mount needs to be private to avoid having a mount for e.g. /var/cache
* also propagate to /sysroot/ostree/deploy/$stateroot/var/cache * also propagate to /sysroot/ostree/deploy/$stateroot/var/cache
* *

View File

@ -21,7 +21,7 @@
set -euo pipefail set -euo pipefail
echo "1..$((82 + ${extra_basic_tests:-0}))" echo "1..$((83 + ${extra_basic_tests:-0}))"
CHECKOUT_U_ARG="" CHECKOUT_U_ARG=""
CHECKOUT_H_ARGS="-H" CHECKOUT_H_ARGS="-H"
@ -476,6 +476,17 @@ cd ${test_tmpdir}
$OSTREE prune $OSTREE prune
echo "ok prune didn't fail" echo "ok prune didn't fail"
# https://github.com/ostreedev/ostree/issues/1467
cd ${test_tmpdir}
mv repo/refs/remotes{,.orig}
if $OSTREE refs --list >/dev/null 2>err.txt; then
fatal "listed refs without remotes dir?"
fi
assert_file_has_content err.txt 'Listing refs.*opendir.*No such file or directory'
mv repo/refs/remotes{.orig,}
$OSTREE refs --list >/dev/null
echo "ok refs enoent error"
cd ${test_tmpdir} cd ${test_tmpdir}
# Verify we can't cat dirs # Verify we can't cat dirs
for path in / /baz; do for path in / /baz; do

View File

@ -1,4 +1,4 @@
#!/usr/bin/python #!/usr/bin/python3
# #
# Copyright (C) 2015 Red Hat # Copyright (C) 2015 Red Hat
# #
@ -38,8 +38,8 @@ def fatal(msg):
sys.stderr.write('\n') sys.stderr.write('\n')
sys.exit(1) sys.exit(1)
def compare_entries_descending(a, b): def entry_get_version(entry):
return int(b['version']) - int(a['version']) return int(entry['version'])
def get_ostree_option(optionstring): def get_ostree_option(optionstring):
for o in optionstring.split(): for o in optionstring.split():
@ -65,7 +65,7 @@ for fname in os.listdir(loaderpath):
v = line[s+1:] v = line[s+1:]
entry[k] = v entry[k] = v
entries.append(entry) entries.append(entry)
entries.sort(compare_entries_descending) entries.sort(key=entry_get_version, reverse=True)
# Parse SYSLINUX config # Parse SYSLINUX config
with open(syslinuxpath) as f: with open(syslinuxpath) as f:

View File

@ -234,10 +234,9 @@ ostree_repo_init() {
# The original one; use setup_fake_remote_repo2 for newer code, # The original one; use setup_fake_remote_repo2 for newer code,
# down the line we'll try to port tests. # down the line we'll try to port tests.
setup_fake_remote_repo1() { setup_fake_remote_repo1() {
mode=$1 mode=$1; shift
commit_opts=${2:-} commit_opts=${1:-}
args=${3:-} [ $# -eq 0 ] || shift
shift
oldpwd=`pwd` oldpwd=`pwd`
mkdir ostree-srv mkdir ostree-srv
cd ostree-srv cd ostree-srv
@ -263,7 +262,7 @@ setup_fake_remote_repo1() {
mkdir ${test_tmpdir}/httpd mkdir ${test_tmpdir}/httpd
cd httpd cd httpd
ln -s ${test_tmpdir}/ostree-srv ostree ln -s ${test_tmpdir}/ostree-srv ostree
${OSTREE_HTTPD} --autoexit --log-file $(pwd)/httpd.log --daemonize -p ${test_tmpdir}/httpd-port $args ${OSTREE_HTTPD} --autoexit --log-file $(pwd)/httpd.log --daemonize -p ${test_tmpdir}/httpd-port "$@"
port=$(cat ${test_tmpdir}/httpd-port) port=$(cat ${test_tmpdir}/httpd-port)
echo "http://127.0.0.1:${port}" > ${test_tmpdir}/httpd-address echo "http://127.0.0.1:${port}" > ${test_tmpdir}/httpd-address
cd ${oldpwd} cd ${oldpwd}

View File

@ -26,7 +26,7 @@ set -euo pipefail
# Exports OSTREE_SYSROOT so --sysroot not needed. # Exports OSTREE_SYSROOT so --sysroot not needed.
setup_os_repository "archive" "syslinux" setup_os_repository "archive" "syslinux"
echo "1..3" echo "1..6"
${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmaster/x86_64-runtime ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmaster/x86_64-runtime
rev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmaster/x86_64-runtime) rev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmaster/x86_64-runtime)
@ -63,3 +63,50 @@ assert_has_dir sysroot/boot/ostree/testos-${bootcsum}
assert_file_has_content sysroot/ostree/deploy/testos/deploy/${newrev}.0/etc/os-release 'NAME=TestOS' assert_file_has_content sysroot/ostree/deploy/testos/deploy/${newrev}.0/etc/os-release 'NAME=TestOS'
echo "ok manual cleanup" echo "ok manual cleanup"
assert_n_pinned() {
local n=$1
${CMD_PREFIX} ostree admin status > status.txt
local n_pinned="$(grep -F -c -e 'Pinned: yes' < status.txt)"
if test "${n_pinned}" '!=' "${n}"; then
cat status.txt
fatal "${n_pinned} != ${n}"
fi
}
assert_n_deployments() {
local n=$1
${CMD_PREFIX} ostree admin status > status.txt
local n_deployments="$(grep -F -c -e 'Version: ' < status.txt)"
if test "${n_deployments}" '!=' "${n}"; then
cat status.txt
fatal "${n_deployments} != ${n}"
fi
}
assert_n_pinned 0
${CMD_PREFIX} ostree admin pin 0
assert_n_pinned 1
${CMD_PREFIX} ostree admin pin -u 0
assert_n_pinned 0
echo "ok pin unpin"
${CMD_PREFIX} ostree admin pin 0
${CMD_PREFIX} ostree admin pin 1
assert_n_pinned 2
assert_n_deployments 2
os_repository_new_commit
${CMD_PREFIX} ostree admin upgrade --os=testos
assert_n_pinned 2
assert_n_deployments 3
echo "ok pin across upgrades"
${CMD_PREFIX} ostree admin pin -u 1
os_repository_new_commit
${CMD_PREFIX} ostree admin upgrade --os=testos
assert_n_pinned 1
assert_n_deployments 3
os_repository_new_commit
${CMD_PREFIX} ostree admin upgrade --os=testos
assert_n_pinned 1
assert_n_deployments 3
echo "ok pinning"

View File

@ -28,7 +28,7 @@ extra_basic_tests=5
. $(dirname $0)/basic-test.sh . $(dirname $0)/basic-test.sh
$CMD_PREFIX ostree --version > version.yaml $CMD_PREFIX ostree --version > version.yaml
python -c 'import yaml; yaml.safe_load(open("version.yaml"))' python3 -c 'import yaml; yaml.safe_load(open("version.yaml"))'
echo "ok yaml version" echo "ok yaml version"
# Reset things so we don't inherit a lot of state from earlier tests # Reset things so we don't inherit a lot of state from earlier tests

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# #
# Copyright (C) 2017 Colin Walters <walters@verbum.org> # Copyright (C) 2017 Colin Walters <walters@verbum.org>
# #
@ -17,6 +17,7 @@
# Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA. # Boston, MA 02111-1307, USA.
from __future__ import division
from __future__ import print_function from __future__ import print_function
import os import os
import sys import sys
@ -33,8 +34,8 @@ def fatal(msg):
# different files with different checksums. # different files with different checksums.
def mktree(dname, serial=0): def mktree(dname, serial=0):
print('Creating tree', dname, file=sys.stderr) print('Creating tree', dname, file=sys.stderr)
os.mkdir(dname, 0755) os.mkdir(dname, 0o755)
for v in xrange(20): for v in range(20):
with open('{}/{}'.format(dname, v), 'w') as f: with open('{}/{}'.format(dname, v), 'w') as f:
f.write('{} {} {}\n'.format(dname, serial, v)) f.write('{} {} {}\n'.format(dname, serial, v))
@ -78,13 +79,13 @@ def run(n_committers, n_pruners):
pruners = set() pruners = set()
print('n_committers', n_committers, 'n_pruners', n_pruners, file=sys.stderr) print('n_committers', n_committers, 'n_pruners', n_pruners, file=sys.stderr)
n_trees = n_committers / 2 n_trees = n_committers // 2
for v in xrange(n_trees): for v in range(n_trees):
mktree('tree{}'.format(v)) mktree('tree{}'.format(v))
for v in xrange(n_committers): for v in range(n_committers):
committers.add(commit(v / 2)) committers.add(commit(v // 2))
for v in xrange(n_pruners): for v in range(n_pruners):
pruners.add(prune()) pruners.add(prune())
failed = False failed = False
@ -97,12 +98,12 @@ def run(n_committers, n_pruners):
if failed: if failed:
fatal('A child process exited abnormally') fatal('A child process exited abnormally')
for v in xrange(n_trees): for v in range(n_trees):
shutil.rmtree('tree{}'.format(v)) shutil.rmtree('tree{}'.format(v))
# No concurrent pruning # No concurrent pruning
run(cpu_count()/2 + 2, 0) run(cpu_count() // 2 + 2, 0)
print("ok no concurrent prunes") print("ok no concurrent prunes")
run(cpu_count()/2 + 4, 3) run(cpu_count() // 2 + 4, 3)
print("ok concurrent prunes") print("ok concurrent prunes")

View File

@ -52,6 +52,13 @@ assert_repo_has_n_commits() {
assert_streq "$(find ${repo}/objects -name '*.commit' | wc -l)" "${count}" assert_streq "$(find ${repo}/objects -name '*.commit' | wc -l)" "${count}"
} }
# Test --no-prune
objectcount_orig=$(find repo/objects | wc -l)
${CMD_PREFIX} ostree prune --repo=repo --refs-only --depth=0 --no-prune | tee noprune.txt
assert_file_has_content noprune.txt 'Would delete: [1-9][0-9]* objects, freeing [1-9][0-9]*'
objectcount_new=$(find repo/objects | wc -l)
assert_streq "${objectcount_orig}" "${objectcount_new}"
${CMD_PREFIX} ostree prune --repo=repo --refs-only --depth=2 -v ${CMD_PREFIX} ostree prune --repo=repo --refs-only --depth=2 -v
assert_repo_has_n_commits repo 3 assert_repo_has_n_commits repo 3
find repo/objects -name '*.tombstone-commit' | wc -l > tombstonecommitcount find repo/objects -name '*.tombstone-commit' | wc -l > tombstonecommitcount
@ -134,9 +141,10 @@ assert_file_has_content deltascount "^1$"
${CMD_PREFIX} ostree --repo=repo static-delta generate test ${CMD_PREFIX} ostree --repo=repo static-delta generate test
${CMD_PREFIX} ostree --repo=repo static-delta list | wc -l > deltascount ${CMD_PREFIX} ostree --repo=repo static-delta list | wc -l > deltascount
assert_file_has_content deltascount "^2$" assert_file_has_content deltascount "^2$"
${CMD_PREFIX} ostree --repo=repo prune --static-deltas-only --keep-younger-than="October 20 2015" if ${CMD_PREFIX} ostree --repo=repo prune --static-deltas-only --keep-younger-than="October 20 2015" 2>err.txt; then
${CMD_PREFIX} ostree --repo=repo static-delta list | wc -l > deltascount fatal "pruned deltas only"
assert_file_has_content deltascount "^1$" fi
assert_file_has_content_literal err.txt "--static-deltas-only requires --delete-commit"
echo "ok prune" echo "ok prune"

View File

@ -147,6 +147,13 @@ ${CMD_PREFIX} ostree --repo=repo refs local1 --create=origin:local1
${CMD_PREFIX} ostree --repo=repo refs | wc -l > refscount.create6 ${CMD_PREFIX} ostree --repo=repo refs | wc -l > refscount.create6
assert_file_has_content refscount.create6 "^11$" assert_file_has_content refscount.create6 "^11$"
#Check that we can list just remote refs
${CMD_PREFIX} ostree --repo=repo refs origin: | wc -l > refscount.create7
assert_file_has_content refscount.create7 "^2$" # origin:remote1 origin:local1
#Also support :. for backcompat with flatpak
${CMD_PREFIX} ostree --repo=repo refs origin:. | wc -l > refscount.create8
assert_file_has_content refscount.create8 "^2$" # origin:remote1 origin:local1
echo "ok refs" echo "ok refs"
# Test symlinking a ref # Test symlinking a ref

View File

@ -27,7 +27,8 @@ echo '1..4'
. $(dirname $0)/libtest.sh . $(dirname $0)/libtest.sh
setup_fake_remote_repo1 "archive" "" \ setup_fake_remote_repo1 "archive" "" \
"--expected-cookies foo=bar --expected-cookies baz=badger" --expected-cookies foo=bar \
--expected-cookies baz=badger
assert_fail (){ assert_fail (){
if $@; then if $@; then

View File

@ -25,8 +25,13 @@ echo '1..2'
. $(dirname $0)/libtest.sh . $(dirname $0)/libtest.sh
V=$($CMD_PREFIX ostree --version | \
python3 -c 'import sys, yaml; print(yaml.safe_load(sys.stdin)["libostree"]["Version"])')
setup_fake_remote_repo1 "archive" "" \ setup_fake_remote_repo1 "archive" "" \
"--expected-header foo=bar --expected-header baz=badger" --expected-header foo=bar \
--expected-header baz=badger \
--expected-header "User-Agent=libostree/$V dodo/2.15"
assert_fail (){ assert_fail (){
set +e set +e
@ -46,9 +51,22 @@ ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat
# Sanity check the setup, without headers the pull should fail # Sanity check the setup, without headers the pull should fail
assert_fail ${CMD_PREFIX} ostree --repo=repo pull origin main assert_fail ${CMD_PREFIX} ostree --repo=repo pull origin main
# without proper User-Agent, the pull should fail
assert_fail ${CMD_PREFIX} ostree --repo=repo pull origin main \
--http-header foo=bar \
--http-header baz=badger
assert_fail ${CMD_PREFIX} ostree --repo=repo pull origin main \
--http-header foo=bar \
--http-header baz=badger \
--append-user-agent bar/1.2
echo "ok setup done" echo "ok setup done"
# Now pull should succeed now # Now pull should succeed now
${CMD_PREFIX} ostree --repo=repo pull --http-header foo=bar --http-header baz=badger origin main ${CMD_PREFIX} ostree --repo=repo pull \
--http-header foo=bar \
--http-header baz=badger \
--append-user-agent dodo/2.15 \
origin main
echo "ok pull succeeded" echo "ok pull succeeded"

View File

@ -54,7 +54,7 @@ echo 'ok documented symbols'
# ONLY update this checksum in release commits! # ONLY update this checksum in release commits!
cat > released-sha256.txt <<EOF cat > released-sha256.txt <<EOF
6f8beb8ec59190c74368b7f2b1aca7a382c9e4b1763b724037932f73ba6b29cd ${released_syms} d77bacdfe04f2a150e4d5e1637410e851c273b238468d820c0d2a168971900f3 ${released_syms}
EOF EOF
sha256sum -c released-sha256.txt sha256sum -c released-sha256.txt