Merge tag 'upstream/2016.5' into debian/master

Upstream version 2016.5
This commit is contained in:
Simon McVittie 2016-04-16 22:22:20 +01:00
commit fa16aa8401
91 changed files with 2325 additions and 614 deletions

80
.gitignore vendored
View File

@ -1,80 +0,0 @@
# Standard C/Automake goo
.deps
.libs
.dirstamp
*.typelib
*.la
*.lo
*.o
*.pyc
*.stamp
*~
Makefile
Makefile.in
aclocal.m4
autom4te.cache
compile
config.guess
config.h
config.h.in
config.log
config.status
config.sub
configure
depcomp
gtk-doc.make
INSTALL
install-sh
libtool
ltmain.sh
missing
stamp-h1
ylwrap
py-compile
config
m4
po
ABOUT-NLS
_build
/build-aux/test-driver
/doc/ostree-decl.txt
/doc/ostree-overrides.txt
/doc/ostree-undeclared.txt
/doc/ostree-undocumented.txt
/doc/ostree-unused.txt
/doc/ostree.types
/doc/version.xml
/doc/tmpl
/doc/html
/doc/xml
/doc/ostree.1
/ostree
/ostree-prepare-root
/ostree-remount
/OSTree-1.0.gir
/src/libostree/ostree-1.pc
/test-admin-deploy-1.test
/test-admin-deploy-2.test
/test-archivez.test
/test-basic.test
/test-corruption.test
/test-libarchive.test
/test-pull-archive-z.test
/test-pull-corruption.test
/test-pull-resume.test
/test-remote-add.test
/test-setuid.test
/test-xattrs.test
test-varint
test*.test
*.trs
*.log
*.tar.xz
*.src.rpm
packaging/*.spec

24
.travis.yml Normal file
View File

@ -0,0 +1,24 @@
# We're just using a "stubbed out" Travis right now so we can
# use Homu <https://github.com/barosl/homu> to auto-squash
# etc.
#
# In the future we'll hook up better tests.
language: c
dist: trusty
addons:
apt:
packages:
- automake
- autotools-dev
script:
- env NOCONFIGURE=1 ./autogen.sh
notifications:
# This is Colin's personal Homu instance. We will
# also work on productizing this in Project Atomic.
webhooks: http://escher.verbum.org:54856/travis
email: false
branches:
only:
- auto

View File

@ -1,4 +1,4 @@
# Makefile for dracut module
# Makefile for boot module
#
# Copyright (C) 2013 Colin Walters <walters@verbum.org>
#
@ -39,14 +39,17 @@ systemdsystemunit_DATA = src/boot/ostree-prepare-root.service \
src/boot/ostree-remount.service
endif
dist_pkglibexec_SCRIPTS = src/boot/grub2-15_ostree
if BUILDOPT_GRUB2
if !BUILDOPT_BUILTIN_GRUB2_MKCONFIG
# We're using the system grub2-mkconfig generator
pkglibexec_SCRIPTS += src/boot/grub2/grub2-15_ostree
install-grub2-config-hook:
mkdir -p $(DESTDIR)$(grub2configdir)
ln -sf $(pkglibexecdir)/grub2-15_ostree $(DESTDIR)$(grub2configdir)/15_ostree
grub2configdir = $(sysconfdir)/grub.d
INSTALL_DATA_HOOKS += install-grub2-config-hook
else
# We're using our internal generator
libexec_SCRIPTS = src/boot/grub2/ostree-grub-generator
endif
EXTRA_DIST += src/boot/dracut/module-setup.sh \
@ -54,4 +57,6 @@ EXTRA_DIST += src/boot/dracut/module-setup.sh \
src/boot/mkinitcpio/ostree \
src/boot/ostree-prepare-root.service \
src/boot/ostree-remount.service \
src/boot/grub2/grub2-15_ostree \
src/boot/grub2/ostree-grub-generator \
$(NULL)

View File

@ -43,9 +43,10 @@ gir_DATA =
typelibdir = $(libdir)/girepository-1.0
typelib_DATA =
gsettings_SCHEMAS =
# git.mk
GITIGNOREFILES =
# This is a special facility to chain together hooks easily
INSTALL_DATA_HOOKS =
install-data-hook: $(INSTALL_DATA_HOOKS)
ALL_LOCAL_RULES =
all-local: $(ALL_LOCAL_RULES)

View File

@ -23,7 +23,12 @@ include $(top_srcdir)/buildutil/glib-tap.mk
# include the builddir in $PATH so we find our just-built ostree
# binary.
TESTS_ENVIRONMENT += OT_TESTS_DEBUG=1 \
PATH=$$(cd $(top_builddir) && pwd):$${PATH}
GI_TYPELIB_PATH=$$(cd $(top_builddir) && pwd) \
LD_LIBRARY_PATH=$$(cd $(top_builddir)/.libs && pwd) \
PATH=$$(cd $(top_builddir) && pwd):$${PATH} \
$(NULL)
uninstalled_test_scripts = tests/test-abi.sh
test_scripts = \
tests/test-basic.sh \
@ -35,6 +40,7 @@ test_scripts = \
tests/test-export.sh \
tests/test-help.sh \
tests/test-libarchive.sh \
tests/test-parent.sh \
tests/test-pull-archive-z.sh \
tests/test-pull-commit-only.sh \
tests/test-pull-corruption.sh \
@ -44,6 +50,8 @@ test_scripts = \
tests/test-pull-metalink.sh \
tests/test-pull-summary-sigs.sh \
tests/test-pull-resume.sh \
tests/test-pull-untrusted.sh \
tests/test-local-pull.sh \
tests/test-local-pull-depth.sh \
tests/test-gpg-signed-commit.sh \
tests/test-admin-upgrade-unconfigured.sh \
@ -53,6 +61,7 @@ test_scripts = \
tests/test-admin-deploy-switch.sh \
tests/test-admin-deploy-etcmerge-cornercases.sh \
tests/test-admin-deploy-uboot.sh \
tests/test-admin-deploy-grub2.sh \
tests/test-admin-instutil-set-kargs.sh \
tests/test-admin-upgrade-not-backwards.sh \
tests/test-admin-pull-deploy-commit.sh \
@ -85,13 +94,13 @@ installed_test_data = tests/archive-test.sh \
tests/admin-test.sh \
tests/basic-test.sh \
tests/test-basic-user.sh \
tests/test-local-pull.sh \
tests/corrupt-repo-ref.js \
tests/pre-endian-deltas-repo-big.tar.xz \
tests/pre-endian-deltas-repo-little.tar.xz \
$(NULL)
test_extra_scripts = tests/syslinux-entries-crosscheck.py
test_extra_scripts = tests/bootloader-entries-crosscheck.py \
tests/ostree-grub-generator
# We can't use nobase_ as we need to strip off the tests/, can't
# use plain installed_ as we do need the gpghome/ prefix.
@ -123,6 +132,9 @@ libreaddir_rand_la_SOURCES = tests/readdir-rand.c
libreaddir_rand_la_CFLAGS = $(OT_INTERNAL_GIO_UNIX_CFLAGS)
libreaddir_rand_la_LIBADD = $(OT_INTERNAL_GIO_UNIX_LIBS)
libreaddir_rand_la_LDFLAGS = -avoid-version
if !ENABLE_INSTALLED_TESTS
libreaddir_rand_la_LDFLAGS += -rpath $(abs_builddir)
endif
test_programs = tests/test-varint tests/test-ot-unix-utils tests/test-bsdiff tests/test-mutable-tree \
tests/test-keyfile-utils tests/test-ot-opt-utils tests/test-ot-tool-util \
@ -203,6 +215,7 @@ tests_test_gpg_verify_result_CFLAGS = $(TESTS_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS
tests_test_gpg_verify_result_LDADD = $(TESTS_LDADD) $(OT_INTERNAL_GPGME_LIBS)
EXTRA_DIST += \
tests/libostreetest.h \
tests/gpg-verify-data/README.md \
tests/gpg-verify-data/lgpl2 \
tests/gpg-verify-data/lgpl2.sig \
@ -211,6 +224,11 @@ EXTRA_DIST += \
tests/gpg-verify-data/trustdb.gpg \
tests/gpg-verify-data/gpg.conf
tests/libreaddir-rand.so: Makefile
$(AM_V_GEN) ln -fns ../.libs/libreaddir-rand.so tests
ALL_LOCAL_RULES += tests/libreaddir-rand.so
CLEANFILES += tests/libreaddir-rand.so
# Unfortunately the glib test data APIs don't actually handle
# non-recursive Automake, so we change our code to canonically look
# for tests/ which is just a symlink when installed.

View File

@ -24,11 +24,14 @@ AM_CPPFLAGS += -DDATADIR='"$(datadir)"' -DLIBEXECDIR='"$(libexecdir)"' \
-DLOCALEDIR=\"$(datadir)/locale\" -DSYSCONFDIR=\"$(sysconfdir)\" \
-DSHORTENED_SYSCONFDIR=\"$(shortened_sysconfdir)\" \
-DOSTREE_FEATURES='"$(OSTREE_FEATURES)"' \
-DG_LOG_DOMAIN=\"OSTree\" \
-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_40 -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_40 \
-DSOUP_VERSION_MIN_REQUIRED=SOUP_VERSION_2_40 -DSOUP_VERSION_MAX_ALLOWED=SOUP_VERSION_2_48
AM_CFLAGS += $(WARN_CFLAGS)
DISTCHECK_CONFIGURE_FLAGS += --enable-gtk-doc --disable-maintainer-mode
GITIGNOREFILES = aclocal.m4 build-aux/ buildutil/*.m4 config.h.in gtk-doc.make
SUBDIRS += .
if ENABLE_GTK_DOC
@ -100,3 +103,5 @@ release-tarball-embedded:
$(embed_dependency) embedded-dependencies/libsoup; \
mv ostree-embeddeps-$${GITVERSION}.tar{.tmp,}; \
gzip -f ostree-embeddeps-$${GITVERSION}.tar
-include $(top_srcdir)/git.mk

53
apidoc/.gitignore vendored
View File

@ -1,2 +1,51 @@
ostree*.1
ostree*.5
*.lo
*.o
.deps
.libs
/*.bak
/*.gcda
/*.gcno
/*.orig
/*.rej
/*.tab.c
/*~
/.*.sw[nop]
/.dirstamp
/.gitignore
/GPATH
/GRTAGS
/GSYMS
/GTAGS
/ID
/Makefile
/Makefile.in
/TAGS
/gtkdoc-check.test
/html
/html-build.stamp
/html.stamp
/ostree-decl-list.txt
/ostree-decl.txt
/ostree-undeclared.txt
/ostree-undocumented.txt
/ostree-unused.txt
/ostree.args
/ostree.hierarchy
/ostree.interfaces
/ostree.pdf
/ostree.prerequisites
/ostree.signals
/ostree.types
/pdf-build.stamp
/pdf.stamp
/scan-build.stamp
/setup-build.stamp
/sgml-build.stamp
/sgml.stamp
/so_locations
/tags
/tmpl
/tmpl/*.bak
/tmpl/ostree-unused.sgml
/xml
_libs

View File

@ -121,3 +121,5 @@ EXTRA_DIST += \
version.xml \
ostree-sections.txt \
$(NULL)
-include $(top_srcdir)/git.mk

View File

@ -269,6 +269,7 @@ ostree_repo_load_file
ostree_repo_load_object_stream
ostree_repo_query_object_storage_size
ostree_repo_import_object_from
ostree_repo_import_object_from_with_trust
ostree_repo_delete_object
OstreeRepoCommitFilterResult
OstreeRepoCommitFilter

View File

@ -13,7 +13,7 @@ touch ${tempdir}/.testtmp
function cleanup () {
if test -n "${TEST_SKIP_CLEANUP:-}"; then
echo "Skipping cleanup of ${tempdir}"
else if test -f ${tempdir}/.test; then
else if test -f ${tempdir}/.testtmp; then
rm "${tempdir}" -rf
fi
fi

2
cfg.mk
View File

@ -1,4 +1,4 @@
export VC_LIST_EXCEPT_DEFAULT=^(lib/.*|m4/.*|md5/.*|build-aux/.*|src/gettext\.h|.*ChangeLog|buildutil/.*)$$
export VC_LIST_EXCEPT_DEFAULT=^(docs/.*|git.mk|lib/.*|m4/.*|md5/.*|build-aux/.*|src/gettext\.h|.*ChangeLog|buildutil/.*)$$
local-checks-to-skip = \
sc_const_long_option \

View File

@ -1,5 +1,5 @@
AC_PREREQ([2.63])
AC_INIT([ostree], [2016.4], [walters@verbum.org])
AC_INIT([ostree], [2016.5], [walters@verbum.org])
AC_CONFIG_HEADER([config.h])
AC_CONFIG_MACRO_DIR([buildutil])
AC_CONFIG_AUX_DIR([build-aux])
@ -251,11 +251,23 @@ AS_IF([test "x$with_dracut" = "xyes" || test "x$with_mkinitcpio" = "xyes"], [
])
AM_CONDITIONAL(BUILDOPT_SYSTEMD, test x$with_systemd = xyes)
AC_ARG_WITH(grub2,
AS_HELP_STRING([--with-grub2],
[Install grub2 hook (default: yes)]),,
[with_grub2=yes])
AM_CONDITIONAL(BUILDOPT_GRUB2, test x$with_grub2 = xyes)
AC_ARG_WITH(builtin-grub2-mkconfig,
AS_HELP_STRING([--with-builtin-grub2-mkconfig],
[Use a builtin minimal grub2-mkconfig to generate a GRUB2 configuration file (default: no)]),,
[with_builtin_grub2_mkconfig=no])
AM_CONDITIONAL(BUILDOPT_BUILTIN_GRUB2_MKCONFIG, test x$with_builtin_grub2_mkconfig = xyes)
AM_COND_IF(BUILDOPT_BUILTIN_GRUB2_MKCONFIG,
AC_DEFINE([USE_BUILTIN_GRUB2_MKCONFIG], 1, [Define if using internal ostree-grub-generator]))
AC_ARG_WITH(grub2-mkconfig-path,
AS_HELP_STRING([--with-grub2-mkconfig-path],
[Path to grub2-mkconfig]))
AS_IF([test x$with_grub2_mkconfig_path = x], [
dnl Otherwise, look for the path to the system generator. On some
dnl distributions GRUB2 *-mkconfig executable has 'grub2' prefix and
dnl on some 'grub'. We default to grub2-mkconfig.
AC_CHECK_PROGS(GRUB2_MKCONFIG, [grub2-mkconfig grub-mkconfig], [grub2-mkconfig])
],[GRUB2_MKCONFIG=$with_grub2_mkconfig_path])
AC_DEFINE_UNQUOTED([GRUB2_MKCONFIG_PATH], ["$GRUB2_MKCONFIG"], [The system grub2-mkconfig executible name])
dnl for tests
AS_IF([test "x$found_introspection" = xyes], [
@ -293,6 +305,11 @@ echo "
gjs-based tests: $have_gjs
dracut: $with_dracut
mkinitcpio: $with_mkinitcpio"
AS_IF([test x$with_builtin_grub2_mkconfig = xyes], [
echo " builtin grub2-mkconfig (instead of system): $with_builtin_grub2_mkconfig"
], [
echo " grub2-mkconfig path: $GRUB2_MKCONFIG"
])
AS_IF([test "x$with_systemd" = "xyes"], [
echo " systemd unit dir: $with_systemdsystemunitdir"
])

View File

@ -47,50 +47,50 @@ func GoBool(b C.gboolean) bool {
}
type GError struct {
ptr unsafe.Pointer
ptr unsafe.Pointer
}
func NewGError() GError {
return GError{nil}
return GError{nil}
}
func (e *GError) Native() *C.GError {
if e == nil {
return nil
}
return (*C.GError)(e.ptr)
if e == nil {
return nil
}
return (*C.GError)(e.ptr)
}
func ConvertGError(e *C.GError) error {
defer C.g_error_free(e)
return errors.New(C.GoString((*C.char)(C._g_error_get_message(e))))
defer C.g_error_free(e)
return errors.New(C.GoString((*C.char)(C._g_error_get_message(e))))
}
type GType uint
func (t GType) Name() string {
return C.GoString((*C.char)(C.g_type_name(C.GType(t))))
return C.GoString((*C.char)(C.g_type_name(C.GType(t))))
}
type GVariant struct {
ptr unsafe.Pointer
ptr unsafe.Pointer
}
func GVariantNew(p unsafe.Pointer) *GVariant {
o := &GVariant{p}
runtime.SetFinalizer(o, (*GVariant).Unref)
return o;
o := &GVariant{p}
runtime.SetFinalizer(o, (*GVariant).Unref)
return o;
}
func GVariantNewSink(p unsafe.Pointer) *GVariant {
o := &GVariant{p}
runtime.SetFinalizer(o, (*GVariant).Unref)
o.RefSink()
return o;
o := &GVariant{p}
runtime.SetFinalizer(o, (*GVariant).Unref)
o.RefSink()
return o;
}
func (v *GVariant) native() *C.GVariant {
return (*C.GVariant)(v.ptr);
return (*C.GVariant)(v.ptr);
}
func (v *GVariant) Ref() {
@ -98,7 +98,7 @@ func (v *GVariant) Ref() {
}
func (v *GVariant) Unref() {
C.g_variant_unref(v.native())
C.g_variant_unref(v.native())
}
func (v *GVariant) RefSink() {
@ -116,14 +116,14 @@ func (v *GVariant) GetChildValue(i int) *GVariant {
}
func (v *GVariant) LookupString(key string) (string, error) {
ckey := C.CString(key)
defer C.free(unsafe.Pointer(ckey))
// TODO: Find a way to have constant C strings in golang
cstr := C._g_variant_lookup_string(v.native(), ckey)
if cstr == nil {
return "", fmt.Errorf("No such key: %s", key)
}
return C.GoString(cstr), nil
ckey := C.CString(key)
defer C.free(unsafe.Pointer(ckey))
// TODO: Find a way to have constant C strings in golang
cstr := C._g_variant_lookup_string(v.native(), ckey)
if cstr == nil {
return "", fmt.Errorf("No such key: %s", key)
}
return C.GoString(cstr), nil
}
/*
@ -144,9 +144,9 @@ type GObject struct {
}
func GObjectNew(p unsafe.Pointer) *GObject {
o := &GObject{p}
runtime.SetFinalizer(o, (*GObject).Unref)
return o;
o := &GObject{p}
runtime.SetFinalizer(o, (*GObject).Unref)
return o;
}
func (v *GObject) Ptr() unsafe.Pointer {
@ -172,7 +172,7 @@ func (v *GObject) Ref() {
}
func (v *GObject) Unref() {
C.g_object_unref(C.gpointer(v.ptr))
C.g_object_unref(C.gpointer(v.ptr))
}
func (v *GObject) RefSink() {
@ -191,7 +191,7 @@ func (v *GObject) ForceFloating() {
// GIO types
type GCancellable struct {
*GObject
*GObject
}
func (self *GCancellable) native() *C.GCancellable {

View File

@ -16,11 +16,11 @@ import (
import "C"
type Repo struct {
*GObject
*GObject
}
func RepoGetType() GType {
return GType(C.ostree_repo_get_type())
return GType(C.ostree_repo_get_type())
}
func (r *Repo) native() *C.OstreeRepo {
@ -28,67 +28,67 @@ func (r *Repo) native() *C.OstreeRepo {
}
func repoFromNative(p *C.OstreeRepo) *Repo {
if p == nil {
return nil
}
o := GObjectNew(unsafe.Pointer(p))
r := &Repo{o}
return r
if p == nil {
return nil
}
o := GObjectNew(unsafe.Pointer(p))
r := &Repo{o}
return r
}
func RepoNewOpen(path string) (*Repo, error) {
var cerr *C.GError = nil
cpath := C.CString(path)
pathc := C.g_file_new_for_path(cpath);
defer C.g_object_unref(C.gpointer(pathc))
crepo := C.ostree_repo_new(pathc)
repo := repoFromNative(crepo);
r := GoBool(C.ostree_repo_open(repo.native(), nil, &cerr))
if !r {
return nil, ConvertGError(cerr)
}
return repo, nil
var cerr *C.GError = nil
cpath := C.CString(path)
pathc := C.g_file_new_for_path(cpath);
defer C.g_object_unref(C.gpointer(pathc))
crepo := C.ostree_repo_new(pathc)
repo := repoFromNative(crepo);
r := GoBool(C.ostree_repo_open(repo.native(), nil, &cerr))
if !r {
return nil, ConvertGError(cerr)
}
return repo, nil
}
func (r *Repo) GetParent() *Repo {
return repoFromNative(C.ostree_repo_get_parent(r.native()))
return repoFromNative(C.ostree_repo_get_parent(r.native()))
}
type ObjectType int
const (
OBJECT_TYPE_FILE ObjectType = C.OSTREE_OBJECT_TYPE_FILE
OBJECT_TYPE_DIR_TREE = C.OSTREE_OBJECT_TYPE_DIR_TREE
OBJECT_TYPE_DIR_META = C.OSTREE_OBJECT_TYPE_DIR_META
OBJECT_TYPE_COMMIT = C.OSTREE_OBJECT_TYPE_COMMIT
OBJECT_TYPE_TOMBSTONE_COMMIT = C.OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT
OBJECT_TYPE_FILE ObjectType = C.OSTREE_OBJECT_TYPE_FILE
OBJECT_TYPE_DIR_TREE = C.OSTREE_OBJECT_TYPE_DIR_TREE
OBJECT_TYPE_DIR_META = C.OSTREE_OBJECT_TYPE_DIR_META
OBJECT_TYPE_COMMIT = C.OSTREE_OBJECT_TYPE_COMMIT
OBJECT_TYPE_TOMBSTONE_COMMIT = C.OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT
)
func (repo *Repo) LoadVariant(t ObjectType, checksum string) (*GVariant, error) {
var cerr *C.GError = nil
var cvariant *C.GVariant = nil
var cerr *C.GError = nil
var cvariant *C.GVariant = nil
r := GoBool(C.ostree_repo_load_variant(repo.native(), C.OstreeObjectType(t), C.CString(checksum), &cvariant, &cerr))
if !r {
return nil, ConvertGError(cerr)
}
variant := GVariantNew(unsafe.Pointer(cvariant))
return variant, nil
r := GoBool(C.ostree_repo_load_variant(repo.native(), C.OstreeObjectType(t), C.CString(checksum), &cvariant, &cerr))
if !r {
return nil, ConvertGError(cerr)
}
variant := GVariantNew(unsafe.Pointer(cvariant))
return variant, nil
}
func (repo *Repo) ResolveRev(ref string) (string, error) {
var cerr *C.GError = nil
var crev *C.char = nil
var cerr *C.GError = nil
var crev *C.char = nil
r := GoBool(C.ostree_repo_resolve_rev(repo.native(), C.CString(ref), GBool(true), &crev, &cerr))
if !r {
return "", ConvertGError(cerr)
}
defer C.free(unsafe.Pointer(crev))
return C.GoString(crev), nil
r := GoBool(C.ostree_repo_resolve_rev(repo.native(), C.CString(ref), GBool(true), &crev, &cerr))
if !r {
return "", ConvertGError(cerr)
}
defer C.free(unsafe.Pointer(crev))
return C.GoString(crev), nil
}
func (commit *GVariant) CommitGetMetadataKeyString(key string) (string, error) {
cmeta := GVariantNew(unsafe.Pointer(C.g_variant_get_child_value(commit.native(), 0)))
return cmeta.LookupString(key)
cmeta := GVariantNew(unsafe.Pointer(C.g_variant_get_child_value(commit.native(), 0)))
return cmeta.LookupString(key)
}

View File

@ -9,47 +9,47 @@ import (
)
func TestTypeName(t *testing.T) {
name := RepoGetType().Name();
if name != "OstreeRepo" {
t.Errorf("%s != OstreeRepo");
}
name := RepoGetType().Name();
if name != "OstreeRepo" {
t.Errorf("%s != OstreeRepo");
}
}
func TestRepoNew(t *testing.T) {
r, err := RepoNewOpen("/ostree/repo")
if err != nil {
t.Errorf("%s", err);
return
}
parent := r.GetParent()
if parent != nil {
t.Errorf("Expected no parent")
return
}
r, err := RepoNewOpen("/ostree/repo")
if err != nil {
t.Errorf("%s", err);
return
}
parent := r.GetParent()
if parent != nil {
t.Errorf("Expected no parent")
return
}
}
func TestRepoGetMetadataVersion(t *testing.T) {
r, err := RepoNewOpen("/ostree/repo")
if err != nil {
t.Errorf("%s", err);
return
}
commit,err := r.ResolveRev("rhel-atomic-host/7/x86_64/standard")
if err != nil {
t.Errorf("%s", err)
return
}
commitv,err := r.LoadVariant(OBJECT_TYPE_COMMIT, commit)
if err != nil {
t.Errorf("%s", err)
return
}
ver, err := commitv.CommitGetMetadataKeyString("version")
if err != nil {
t.Errorf("%s", err)
return
}
if ver != "7.1.3" {
t.Errorf("expected 7.1.3")
}
r, err := RepoNewOpen("/ostree/repo")
if err != nil {
t.Errorf("%s", err);
return
}
commit,err := r.ResolveRev("rhel-atomic-host/7/x86_64/standard")
if err != nil {
t.Errorf("%s", err)
return
}
commitv,err := r.LoadVariant(OBJECT_TYPE_COMMIT, commit)
if err != nil {
t.Errorf("%s", err)
return
}
ver, err := commitv.CommitGetMetadataKeyString("version")
if err != nil {
t.Errorf("%s", err)
return
}
if ver != "7.1.3" {
t.Errorf("expected 7.1.3")
}
}

View File

@ -1,29 +1,46 @@
Submitting patches
------------------
You can:
A majority of current maintainers prefer the Github pull request
model, and this motivated moving the primary git repository to
<https://github.com/ostreedev/ostree>.
However, we do not use the "Merge pull request" button, because we do
not like merge commits for one-patch pull requests, among other
reasons. See [this issue](https://github.com/isaacs/github/issues/2)
for more information. Instead, we use an instance of
[Homu](https://github.com/servo/homu), currently known as
`cgwalters-bot`.
As a review proceeeds, the preferred method is to push `fixup!`
commits via `git commit --fixup`. Homu knows how to use
`--autosquash` when performing the final merge. See the
[Git documentation](https://git-scm.com/docs/git-rebase]) for more
information.
Alternative methods if you don't like Github (also fully supported):
1. Send mail to <ostree-list@gnome.org>, with the patch attached
1. Submit a pull request against <https://github.com/GNOME/ostree>
1. Attach them to <https://bugzilla.gnome.org/>
Please look at `git log` and match the commit log style.
It is likely however once a patch is ready to apply a maintainer
will push it to a github PR, and merge via Homu.
Commit message style
--------------------
Please look at `git log` and match the commit log style, which is very
similar to the
[Linux kernel](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git).
You may use `Signed-off-by`, but we're not requiring it.
Running the test suite
----------------------
Currently, OSTree uses <https://wiki.gnome.org/GnomeGoals/InstalledTests>
To run just OSTree's tests:
./configure ... --enable-installed-tests
gnome-desktop-testing-runner -p 0 ostree/
Also, there is a regular:
make check
That runs a different set of tests.
OSTree uses both `make check` and supports the
[Installed Tests](https://wiki.gnome.org/GnomeGoals/InstalledTests)
model as well (if `--enable-installed-tests` is provided).
Coding style
------------

View File

@ -23,7 +23,7 @@ deployment.
Because OSTree only preserves `/var` across upgrades (each
deployment's chroot directory will be garbage collected
eventually), you will need to choose how to handle other
toplevel writable directories specified by the [Filesystem Hierarchy Standard](http://www.pathname.com/fhs/")
toplevel writable directories specified by the [Filesystem Hierarchy Standard](http://www.pathname.com/fhs/).
Your operating system may of course choose
not to support some of these such as `/usr/local`, but following is the
recommended set:
@ -37,9 +37,9 @@ recommended set:
- `/tmp``/sysroot/tmp`
Furthermore, since `/var` is empty by default, your operating system
will need to dynamically create the <emphasis>targets</emphasis> of
these at boot. A good way to do this is using `systemd-tmpfiles`, if
your OS uses systemd. For example:
will need to dynamically create the *targets* of these at boot. A
good way to do this is using `systemd-tmpfiles`, if your OS uses
systemd. For example:
```
d /var/log/journal 0755 root root -
@ -64,10 +64,10 @@ d /run/media 0755 root root -
Particularly note here the double indirection of `/home`. By default,
each deployment will share the global toplevel `/home` directory on
the physical root filesystem. It is then up to higher levels of
management tools to keep <filename>/etc/passwd</filename> or
equivalent synchronized between operating systems. Each deployment
can easily be reconfigured to have its own home directory set simply
by making `/var/home` a real directory. </chapter>
management tools to keep `/etc/passwd` or equivalent synchronized
between operating systems. Each deployment can easily be reconfigured
to have its own home directory set simply by making `/var/home` a real
directory.
## Booting and initramfs technology
@ -144,11 +144,11 @@ these new packages on top. A command like this:
```
ostree commit -b osname/releasename/description
--tree=ref=$osname/releasename/description
--tree=ref=$osname/$releasename/$description
--tree=dir=/var/tmp/newpackages.13A8D0/
```
will create a new commit in the `$osname/releasename/description`
will create a new commit in the `$osname/$releasename/$description`
branch. The OSTree SHA256 checksum of all the files in
`/var/tmp/newpackages.13A8D0/` will be computed, but we will not
re-checksum the present existing tree. In this layering model,
@ -156,4 +156,4 @@ earlier directories will take precedence, but files in later layers
will silently override earlier layers.
Then to actually deploy this tree for the next boot:
`ostree admin deploy <replaceable>osname/releasename/description`
`ostree admin deploy $osname/$releasename/$description`

View File

@ -18,7 +18,7 @@ implements this.
To begin a simple upgrade, OSTree fetches the contents of the ref from
the remote server. Suppose we're tracking a ref named
`exampleos/buildmaster/x86_64-runtime`. OSTree fetches the URL
`http://$example.com/repo/refs/exampleos/buildmaster/x86_64-runtime`,
`http://example.com/repo/refs/exampleos/buildmaster/x86_64-runtime`,
which contains a SHA256 checksum. This determines the tree to deploy,
and `/etc` will be merged from currently booted tree.
@ -35,7 +35,7 @@ we need to perform a deployment.
As mentioned in the introduction, OSTree is also designed to allow a
model where filesystem trees are computed on the client. It is
completely agnostic as to how those trees are generated; hey could be
completely agnostic as to how those trees are generated; they could be
computed with traditional packages, packages with post-deployment
scripts on top, or built by developers directly from revision control
locally, etc.
@ -58,7 +58,7 @@ Given a commit to deploy, OSTree first allocates a directory for
it. This is of the form `/boot/loader/entries/ostree-$osname-$checksum.$serial.conf`.
The `$serial` is normally 0, but if a
given commit is deployed more than once, it will be incremented.
his is supported because the previous deployment may have
This is supported because the previous deployment may have
configuration in `/etc` that we do not want to use or overwrite.
Now that we have a deployment directory, a 3-way merge is
@ -94,7 +94,7 @@ collected at any point.
## The /ostree/boot directory
However, we want to optimize for the case where we the set of
However, we want to optimize for the case where the set of
kernel/initramfs pairs is the same between both the old and new
deployment lists. This happens when doing an upgrade that does not
include the kernel; think of a simple translation update. OSTree
@ -106,11 +106,11 @@ automatically remount read-write just for the portion of time
necessary to update the bootloader configuration.
To implement this, OSTree also maintains the directory
`/ostree/boot.<replaceable>bootversion</replaceable>`, which is a set
`/ostree/boot.$bootversion`, which is a set
of symbolic links to the deployment directories. The
<replaceable>bootversion</replaceable> here must match the version of
`$bootversion` here must match the version of
`/boot`. However, in order to allow atomic transitions of
<emphasis>this</emphasis> directory, this is also a swapped directory,
*this* directory, this is also a swapped directory,
so just like `/boot`, it has a version of `0` or `1` appended.
Each bootloader entry has a special `ostree=` argument which refers to

View File

@ -63,7 +63,7 @@ But let's discuss building our own. If you're just experimenting,
it's quite easy to start with the command line. We'll assume for this
purpose that you have a build process that outputs a directory tree -
we'll call this tool `$pkginstallroot` (which could be `yum
--installroot` or `dbootstrap`, etc.).
--installroot` or `debootstrap`, etc.).
Your initial prototype is going to look like:
@ -132,7 +132,7 @@ the desired version).
Now, to construct our final tree:
```
rm exampleos-build -rf
rm -rf exampleos-build
for package in bash systemd; do
ostree --repo=build-repo checkout -U --union exampleos/x86_64/${package} exampleos-build
done
@ -178,3 +178,8 @@ commit.
```
ostree --repo=repo static-delta generate exampleos/x86_64/standard
```
## More sophisticated repository management
Next, see [Repository Management](repository-management.md) for the
next steps in managing content in OSTree repositories.

View File

@ -54,9 +54,9 @@ to avoid computing checksums on the client by default.
The deployment should not have a traditional UNIX `/etc`; instead, it
should include `/usr/etc`. This is the "default configuration". When
OSTree creates a deployment, it performs a 3-way merge using the
<emphasis>old</emphasis> default configuration, the active system's
`/etc`, and the new default configuration. In the final filesystem
tree for a deployment then, `/etc` is a regular writable directory.
*old* default configuration, the active system's `/etc`, and the new
default configuration. In the final filesystem tree for a deployment
then, `/etc` is a regular writable directory.
Besides the exceptions of `/var` and `/etc` then, the rest of the
contents of the tree are checked out as hard links into the
@ -87,4 +87,4 @@ deployment.
At present, not all bootloaders implement the BootLoaderSpec, so
OSTree contains code for some of these to regenerate native config
files (such as `/boot/syslinux/syslinux.conf` based on the entries.
files (such as `/boot/syslinux/syslinux.conf`) based on the entries.

View File

@ -18,7 +18,7 @@ date, and relatively agnostic.
Broadly speaking, projects in this area fall into two camps; either
a tool to snapshot systems on the client side (dpkg/rpm + BTRFS/LVM),
or a tool to compose on a server and replicate (ChromiumOS, Clear
Linux). OSTree is flexible enough to do both.
Linux). OSTree is flexible enough to do both.
## Combining dpkg/rpm + (BTRFS/LVM)
@ -63,7 +63,7 @@ awareness of BTRFS in dpkg/rpm itself) will be required.
The OSTree author believes that having total freedom at the block
storage layer is better for general purpose operating systems. For
example, with OSTree, one is free to use BTRFS in any way you like -
you can use a subvolume for `/home`, or you can not.
you may decide to use a subvolume for `/home`, or not.
Furthermore, in its most basic incarnation, the rpm/dpkg + BTRFS
doesn't solve the race conditions that happen when unpacking packages

View File

@ -87,7 +87,7 @@ two different generated filesystem trees. In this example, the
"runtime" tree contains just enough to run a basic system, and
"devel-debug" contains all of the developer tools and debuginfo.
The `ostree` supports a simple syntax using the carat `^` to refer to
The `ostree` supports a simple syntax using the caret `^` to refer to
the parent of a given commit. For example,
`exampleos/buildmaster/x86_64-runtime^` refers to the previous build,
and `exampleos/buildmaster/x86_64-runtime^^` refers to the one before

View File

@ -0,0 +1,211 @@
# Managing content in OSTree repositories
Once you have a build system going, if you actually want client
systems to retrieve the content, you will quickly feel a need for
"repository management".
OSTree itself does not currently come with tools to do this. One
reason is that how content is delivered and managed has concerns very
specific to the organization. For example, some operating system
content vendors may want integration with a specific errata
notification system.
In this section, we will describe some high level ideas and methods
for managing content in OSTree repositories, mostly independent of any
particular model or tool. That said, a goal is to include at least
some sample scripts and workflows upstream in a potential new
"contrib" git repository.
One example of software which can assist in managing OSTree
repositories today is the [Pulp Project](http://www.pulpproject.org/),
which has a
[Pulp OSTree plugin](https://pulp-ostree.readthedocs.org/en/latest/).
## Separate development vs release repositories
By default, OSTree accumulates server side history. This is actually
optional in that your build system can (using the API) write a commit
with no parent. But first, we'll investigate the ramifications of
server side history.
Many content vendors will want to separate their internal development
with what is made public to the world. Therefore, you will want (at
least) two OSTree repositories, we'll call them "dev" and "prod".
To phrase this another way, let's say you have a continuous delivery
system which is building from git and committing into your "dev"
OSTree repository. This might happen tens to hundreds of times per
day. That's a substantial amount of history over time, and it's
unlikely most of your content consumers (i.e. not developers/testers)
will be interested in all of it.
The original vision of OSTree was to fulfill this "dev" role, and in
particular the "archive-z2" format was designed for it.
Then, what you'll want to do is promote content from "dev" to "prod".
We'll discuss this later, but first, let's talk about promotion
*inside* our "dev" repository.
## Promoting content along OSTree branches - "buildmaster", "smoketested"
Besides multiple repositories, OSTree also supports multiple branches
inside one repository, equivalent to git's branches. We saw in an
earlier section an example branch name like
`exampleos/x86_64/standard`. Choosing the branch name for your "prod"
repository is absolutely critical as client systems will reference it.
It becomes an important part of your face to the world, in the same
way the "master" branch in a git repository is.
But with your "dev" repository internally, it can be very useful to
use OSTree's branching concepts to represent different stages in a
software delivery pipeline.
Deriving from `exampleos/x86_64/standard`, let's say our "dev"
repository contains `exampleos/x86_64/buildmaster/standard`. We choose the
term "buildmaster" to represent something that came straight from git
master. It may not be tested very much.
Our next step should be to hook up a testing system (Jenkins,
Buildbot, etc.) to this. When a build (commit) passes some tests, we
want to "promote" that commit. Let's create a new branch called
`smoketested` to say that some basic sanity checks pass on the
complete system. This might be where human testers get involved, for
example.
The build system can "promote" the `buildmaster` commit that passed
testing like this:
```
ostree commit -b exampleos/x86_64/smoketested/standard -s 'Passed tests' --tree=ref=aec070645fe53...
```
Here we're generating a new commit object (perhaps include in the commit
log links to build logs, etc.), but we're reusing the *content* from the `buildmaster`
commit `aec070645fe53` that passed the smoketests.
We can easily generalize this model to have an arbitrary number of
stages like `exampleos/x86_64/stage-1-pass/standard`,
`exampleos/x86_64/stage-2-pass/standard`, etc. depending on business
requirements and logic.
In this suggested model, the "stages" are increasingly expensive. The
logic is that we don't want to spend substantial time on e.g. network
performance tests if something basic like a systemd unit file fails on
bootup.
## Promoting content between OSTree repositories
Now, we have our internal continuous delivery stream flowing, it's
being tested and works. We want to periodically take the latest
commit on `exampleos/x86_64/stage-3-pass/standard` and expose it in
our "prod" repository as `exampleos/x86_64/standard`, with a much
smaller history.
We'll have other business requirements such as writing release notes
(and potentially putting them in the OSTree commit message), etc.
In [Build Systems](buildsystem-and-repos.md) we saw how the
`pull-local` command can be used to migrate content from the "build"
repository (in `bare-user` mode) into an `archive-z2` repository for
serving to client systems.
Following this section, we now have three repositories, let's call
them `repo-build`, `repo-dev`, and `repo-prod`. We've been pulling
content from `repo-build` into `repo-dev` (which involves gzip
compression among other things since it is a format change).
When using `pull-local` to migrate content between two `archive-z2`
repositories, the binary content is taken unmodified. Let's go ahead
and generate a new commit in our prod repository:
```
checksum=$(ostree --repo=repo-dev rev-parse exampleos/x86_64/stage-3-pass/standard`)
ostree --repo=repo-prod pull-local repo-dev ${checksum}
ostree --repo=repo-prod commit -b exampleos/x86_64/standard \
-s 'Release 1.2.3' --add-metadata-string=ostree.version=1.2.3 \
--tree=ref=${checksum}
```
There are a few things going on here. First, we found the latest
commit checksum for the "stage-3 dev", and told `pull-local` to copy
it, without using the branch name. We do this because we don't want
to expose the `exampleos/x86_64/stage-3-pass/standard` branch name in
our "prod" repository.
Next, we generate a new commit in prod that's referencing the exact
binary content in dev. If the "dev" and "prod" repositories are on
the same Unix filesystem, (like git) OSTree will make use of hard
links to avoid copying any content at all - making the process very
fast.
Another interesting thing to notice here is that we're adding an
`ostree.version` metadata string to the commit. This is an optional
piece of metadata, but we are encouraging its use in the OSTree
ecosystem of tools. Commands like `ostree admin status` show it by
default.
## Derived data - static deltas and the summary file
As discussed in [Formats](formats.md), the `archive-z2` repository we
use for "prod" requires one HTTP fetch per client request by default.
If we're only performing a release e.g. once a week, it's appropriate
to use "static deltas" to speed up client updates.
So once we've used the above command to pull content from `repo-dev`
into `repo-prod`, let's generate a delta against the previous commit:
```
ostree --repo=repo-prod static-delta generate exampleos/x86_64/standard
```
We may also want to support client systems upgrading from *two*
commits previous.
```
ostree --repo=repo-prod static-delta generate --from=exampleos/x86_64/standard^^ --to=exampleos/x86_64/standard
```
Generating a full permutation of deltas across all prior versions can
get expensive, and there is some support in the OSTree core for static
deltas which "recurse" to a parent. This can help create a model
where clients download a chain of deltas. Support for this is not
fully implemented yet however.
Regardless of whether or not you choose to generate static deltas,
you should update the summary file:
```
ostree --repo=repo-prod summary -u
```
(Remember, the `summary` command cannot be run concurrently, so this
should be triggered serially by other jobs).
There is some more information on the design of the summary file in
[Repo](repo.md).
## Pruning our build and dev repositories
First, the OSTree author believes you should *not* use OSTree as a
"primary content store". The binaries in an OSTree repository should
be derived from a git repository. Your build system should record
proper metadata such as the configuration options used to generate the
build, and you should be able to rebuild it if necessary. Art assets
should be stored in a system that's designed for that
(e.g. [Git LFS](https://git-lfs.github.com/)).
Another way to say this is that five years down the line, we are
unlikely to care about retaining the exact binaries from an OS build
on Wednesday afternoon three years ago.
We want to save space and prune our "dev" repository.
```
ostree --repo=repo-dev prune --refs-only --keep-younger-than="6 months ago"
```
That will truncate the history older than 6 months. Deleted commits
will have "tombstone markers" added so that you know they were
explicitly deleted, but all content in them (that is not referenced by
a still retained commit) will be garbage collected.

348
git.mk Normal file
View File

@ -0,0 +1,348 @@
# git.mk, a small Makefile to autogenerate .gitignore files
# for autotools-based projects.
#
# Copyright 2009, Red Hat, Inc.
# Copyright 2010,2011,2012,2013 Behdad Esfahbod
# Written by Behdad Esfahbod
#
# Copying and distribution of this file, with or without modification,
# is permitted in any medium without royalty provided the copyright
# notice and this notice are preserved.
#
# The latest version of this file can be downloaded from:
GIT_MK_URL = https://raw.githubusercontent.com/behdad/git.mk/master/git.mk
#
# Bugs, etc, should be reported upstream at:
# https://github.com/behdad/git.mk
#
# To use in your project, import this file in your git repo's toplevel,
# then do "make -f git.mk". This modifies all Makefile.am files in
# your project to -include git.mk. Remember to add that line to new
# Makefile.am files you create in your project, or just rerun the
# "make -f git.mk".
#
# This enables automatic .gitignore generation. If you need to ignore
# more files, add them to the GITIGNOREFILES variable in your Makefile.am.
# But think twice before doing that. If a file has to be in .gitignore,
# chances are very high that it's a generated file and should be in one
# of MOSTLYCLEANFILES, CLEANFILES, DISTCLEANFILES, or MAINTAINERCLEANFILES.
#
# The only case that you need to manually add a file to GITIGNOREFILES is
# when remove files in one of mostlyclean-local, clean-local, distclean-local,
# or maintainer-clean-local make targets.
#
# Note that for files like editor backup, etc, there are better places to
# ignore them. See "man gitignore".
#
# If "make maintainer-clean" removes the files but they are not recognized
# by this script (that is, if "git status" shows untracked files still), send
# me the output of "git status" as well as your Makefile.am and Makefile for
# the directories involved and I'll diagnose.
#
# For a list of toplevel files that should be in MAINTAINERCLEANFILES, see
# Makefile.am.sample in the git.mk git repo.
#
# Don't EXTRA_DIST this file. It is supposed to only live in git clones,
# not tarballs. It serves no useful purpose in tarballs and clutters the
# build dir.
#
# This file knows how to handle autoconf, automake, libtool, gtk-doc,
# gnome-doc-utils, yelp.m4, mallard, intltool, gsettings, dejagnu, appdata,
# appstream.
#
# This makefile provides the following targets:
#
# - all: "make all" will build all gitignore files.
# - gitignore: makes all gitignore files in the current dir and subdirs.
# - .gitignore: make gitignore file for the current dir.
# - gitignore-recurse: makes all gitignore files in the subdirs.
#
# KNOWN ISSUES:
#
# - Recursive configure doesn't work as $(top_srcdir)/git.mk inside the
# submodule doesn't find us. If you have configure.{in,ac} files in
# subdirs, add a proxy git.mk file in those dirs that simply does:
# "include $(top_srcdir)/../git.mk". Add more ..'s to your taste.
# And add those files to git. See vte/gnome-pty-helper/git.mk for
# example.
#
###############################################################################
# Variables user modules may want to add to toplevel MAINTAINERCLEANFILES:
###############################################################################
#
# Most autotools-using modules should be fine including this variable in their
# toplevel MAINTAINERCLEANFILES:
GITIGNORE_MAINTAINERCLEANFILES_TOPLEVEL = \
$(srcdir)/aclocal.m4 \
$(srcdir)/autoscan.log \
$(srcdir)/configure.scan \
`AUX_DIR=$(srcdir)/$$(cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_AUX_DIR:$$1' ./configure.ac); \
test "x$$AUX_DIR" = "x$(srcdir)/" && AUX_DIR=$(srcdir); \
for x in \
ar-lib \
compile \
config.guess \
config.sub \
depcomp \
install-sh \
ltmain.sh \
missing \
mkinstalldirs \
test-driver \
ylwrap \
; do echo "$$AUX_DIR/$$x"; done` \
`cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_HEADERS:$$1' ./configure.ac | \
head -n 1 | while read f; do echo "$(srcdir)/$$f.in"; done`
#
# All modules should also be fine including the following variable, which
# removes automake-generated Makefile.in files:
GITIGNORE_MAINTAINERCLEANFILES_MAKEFILE_IN = \
`cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_FILES:$$1' ./configure.ac | \
while read f; do \
case $$f in Makefile|*/Makefile) \
test -f "$(srcdir)/$$f.am" && echo "$(srcdir)/$$f.in";; esac; \
done`
#
# Modules that use libtool and use AC_CONFIG_MACRO_DIR() may also include this,
# though it's harmless to include regardless.
GITIGNORE_MAINTAINERCLEANFILES_M4_LIBTOOL = \
`MACRO_DIR=$(srcdir)/$$(cd $(top_srcdir); $(AUTOCONF) --trace 'AC_CONFIG_MACRO_DIR:$$1' ./configure.ac); \
if test "x$$MACRO_DIR" != "x$(srcdir)/"; then \
for x in \
libtool.m4 \
ltoptions.m4 \
ltsugar.m4 \
ltversion.m4 \
lt~obsolete.m4 \
; do echo "$$MACRO_DIR/$$x"; done; \
fi`
###############################################################################
# Default rule is to install ourselves in all Makefile.am files:
###############################################################################
git-all: git-mk-install
git-mk-install:
@echo "Installing git makefile"
@any_failed=; \
find "`test -z "$(top_srcdir)" && echo . || echo "$(top_srcdir)"`" -name Makefile.am | while read x; do \
if grep 'include .*/git.mk' $$x >/dev/null; then \
echo "$$x already includes git.mk"; \
else \
failed=; \
echo "Updating $$x"; \
{ cat $$x; \
echo ''; \
echo '-include $$(top_srcdir)/git.mk'; \
} > $$x.tmp || failed=1; \
if test x$$failed = x; then \
mv $$x.tmp $$x || failed=1; \
fi; \
if test x$$failed = x; then : else \
echo "Failed updating $$x"; >&2 \
any_failed=1; \
fi; \
fi; done; test -z "$$any_failed"
git-mk-update:
wget $(GIT_MK_URL) -O $(top_srcdir)/git.mk
.PHONY: git-all git-mk-install git-mk-update
###############################################################################
# Actual .gitignore generation:
###############################################################################
$(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk
@echo "git.mk: Generating $@"
@{ \
if test "x$(DOC_MODULE)" = x -o "x$(DOC_MAIN_SGML_FILE)" = x; then :; else \
for x in \
$(DOC_MODULE)-decl-list.txt \
$(DOC_MODULE)-decl.txt \
tmpl/$(DOC_MODULE)-unused.sgml \
"tmpl/*.bak" \
$(REPORT_FILES) \
$(DOC_MODULE).pdf \
xml html \
; do echo "/$$x"; done; \
FLAVOR=$$(cd $(top_srcdir); $(AUTOCONF) --trace 'GTK_DOC_CHECK:$$2' ./configure.ac); \
case $$FLAVOR in *no-tmpl*) echo /tmpl;; esac; \
if echo "$(SCAN_OPTIONS)" | grep -q "\-\-rebuild-types"; then \
echo "/$(DOC_MODULE).types"; \
fi; \
if echo "$(SCAN_OPTIONS)" | grep -q "\-\-rebuild-sections"; then \
echo "/$(DOC_MODULE)-sections.txt"; \
fi; \
if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \
for x in \
$(SETUP_FILES) \
$(DOC_MODULE).types \
; do echo "/$$x"; done; \
fi; \
fi; \
if test "x$(DOC_MODULE)$(DOC_ID)" = x -o "x$(DOC_LINGUAS)" = x; then :; else \
for lc in $(DOC_LINGUAS); do \
for x in \
$(if $(DOC_MODULE),$(DOC_MODULE).xml) \
$(DOC_PAGES) \
$(DOC_INCLUDES) \
; do echo "/$$lc/$$x"; done; \
done; \
for x in \
$(_DOC_OMF_ALL) \
$(_DOC_DSK_ALL) \
$(_DOC_HTML_ALL) \
$(_DOC_MOFILES) \
$(DOC_H_FILE) \
"*/.xml2po.mo" \
"*/*.omf.out" \
; do echo /$$x; done; \
fi; \
if test "x$(HELP_ID)" = x -o "x$(HELP_LINGUAS)" = x; then :; else \
for lc in $(HELP_LINGUAS); do \
for x in \
$(HELP_FILES) \
"$$lc.stamp" \
"$$lc.mo" \
; do echo "/$$lc/$$x"; done; \
done; \
fi; \
if test "x$(gsettings_SCHEMAS)" = x; then :; else \
for x in \
$(gsettings_SCHEMAS:.xml=.valid) \
$(gsettings__enum_file) \
; do echo "/$$x"; done; \
fi; \
if test "x$(appdata_XML)" = x; then :; else \
for x in \
$(appdata_XML:.xml=.valid) \
; do echo "/$$x"; done; \
fi; \
if test "x$(appstream_XML)" = x; then :; else \
for x in \
$(appstream_XML:.xml=.valid) \
; do echo "/$$x"; done; \
fi; \
if test -f $(srcdir)/po/Makefile.in.in; then \
for x in \
po/Makefile.in.in \
po/Makefile.in.in~ \
po/Makefile.in \
po/Makefile \
po/Makevars.template \
po/POTFILES \
po/Rules-quot \
po/stamp-it \
po/stamp-po \
po/.intltool-merge-cache \
"po/*.gmo" \
"po/*.header" \
"po/*.mo" \
"po/*.sed" \
"po/*.sin" \
po/$(GETTEXT_PACKAGE).pot \
intltool-extract.in \
intltool-merge.in \
intltool-update.in \
; do echo "/$$x"; done; \
fi; \
if test -f $(srcdir)/configure; then \
for x in \
autom4te.cache \
configure \
config.h \
stamp-h1 \
libtool \
config.lt \
; do echo "/$$x"; done; \
fi; \
if test "x$(DEJATOOL)" = x; then :; else \
for x in \
$(DEJATOOL) \
; do echo "/$$x.sum"; echo "/$$x.log"; done; \
echo /site.exp; \
fi; \
if test "x$(am__dirstamp)" = x; then :; else \
echo "$(am__dirstamp)"; \
fi; \
if test "x$(findstring libtool,$(LTCOMPILE))" = x -a "x$(findstring libtool,$(LTCXXCOMPILE))" = x -a "x$(GTKDOC_RUN)" = x; then :; else \
for x in \
"*.lo" \
".libs" "_libs" \
; do echo "$$x"; done; \
fi; \
for x in \
.gitignore \
$(GITIGNOREFILES) \
$(CLEANFILES) \
$(PROGRAMS) $(check_PROGRAMS) $(EXTRA_PROGRAMS) \
$(LIBRARIES) $(check_LIBRARIES) $(EXTRA_LIBRARIES) \
$(LTLIBRARIES) $(check_LTLIBRARIES) $(EXTRA_LTLIBRARIES) \
so_locations \
$(MOSTLYCLEANFILES) \
$(TEST_LOGS) \
$(TEST_LOGS:.log=.trs) \
$(TEST_SUITE_LOG) \
$(TESTS:=.test) \
"*.gcda" \
"*.gcno" \
$(DISTCLEANFILES) \
$(am__CONFIG_DISTCLEAN_FILES) \
$(CONFIG_CLEAN_FILES) \
TAGS ID GTAGS GRTAGS GSYMS GPATH tags \
"*.tab.c" \
$(MAINTAINERCLEANFILES) \
$(BUILT_SOURCES) \
$(patsubst %.vala,%.c,$(filter %.vala,$(SOURCES))) \
$(filter %_vala.stamp,$(DIST_COMMON)) \
$(filter %.vapi,$(DIST_COMMON)) \
$(filter $(addprefix %,$(notdir $(patsubst %.vapi,%.h,$(filter %.vapi,$(DIST_COMMON))))),$(DIST_COMMON)) \
Makefile \
Makefile.in \
"*.orig" \
"*.rej" \
"*.bak" \
"*~" \
".*.sw[nop]" \
".dirstamp" \
; do echo "/$$x"; done; \
for x in \
"*.$(OBJEXT)" \
$(DEPDIR) \
; do echo "$$x"; done; \
} | \
sed "s@^/`echo "$(srcdir)" | sed 's/\(.\)/[\1]/g'`/@/@" | \
sed 's@/[.]/@/@g' | \
LC_ALL=C sort | uniq > $@.tmp && \
mv $@.tmp $@;
all: $(srcdir)/.gitignore gitignore-recurse-maybe
gitignore: $(srcdir)/.gitignore gitignore-recurse
gitignore-recurse-maybe:
@for subdir in $(DIST_SUBDIRS); do \
case " $(SUBDIRS) " in \
*" $$subdir "*) :;; \
*) test "$$subdir" = . -o -e "$$subdir/.git" || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) gitignore || echo "Skipping $$subdir");; \
esac; \
done
gitignore-recurse:
@for subdir in $(DIST_SUBDIRS); do \
test "$$subdir" = . -o -e "$$subdir/.git" || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) gitignore || echo "Skipping $$subdir"); \
done
maintainer-clean: gitignore-clean
gitignore-clean:
-rm -f $(srcdir)/.gitignore
.PHONY: gitignore-clean gitignore gitignore-recurse gitignore-recurse-maybe

View File

@ -80,6 +80,14 @@ Boston, MA 02111-1307, USA.
Do no invoke fsync().
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--untrusted</option></term>
<listitem><para>
Do not trust source, verify checksums and don't hardlink into source.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -73,6 +73,14 @@ Boston, MA 02111-1307, USA.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--untrusted</option></term>
<listitem><para>
Do not trust local sources, verify checksums and don't hardlink into source.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--disable-static-deltas</option></term>

View File

@ -51,6 +51,12 @@ Boston, MA 02111-1307, USA.
<cmdsynopsis>
<command>ostree static-delta list</command>
</cmdsynopsis>
<cmdsynopsis>
<command>ostree static-delta show</command>
</cmdsynopsis>
<cmdsynopsis>
<command>ostree static-delta delete</command>
</cmdsynopsis>
<cmdsynopsis>
<command>ostree static-delta generate</command> <arg choice="req">--to=REV</arg> <arg choice="opt" rep="repeat">OPTIONS</arg>
</cmdsynopsis>

View File

@ -195,6 +195,15 @@ Boston, MA 02111-1307, USA.
ignored.
</para>
</refsect1>
<refsect1>
<title>Per-remote GPG keyrings and verification</title>
<para>
OSTree supports a per-remote GPG keyring. For more information see
<citerefentry><refentrytitle>ostree</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
in the section <literal>GPG verification</literal>.
</para>
</refsect1>
<refsect1>
<title>See Also</title>

View File

@ -425,13 +425,25 @@ Boston, MA 02111-1307, USA.
<title>GPG verification</title>
<para>
OSTree supports signing commits with GPG. The set of
trusted public keys is stored as keyring files in
<filename>/usr/share/ostree/trusted.gpg.d</filename>. Any
public key in a keyring file in that directory will be
trusted by the client. No private keys should be present
in this directory.
OSTree supports signing commits with GPG. Operations on the system
repository by default use keyring files in
<filename>/usr/share/ostree/trusted.gpg.d</filename>. Any
public key in a keyring file in that directory will be
trusted by the client. No private keys should be present
in this directory.
</para>
<para>
In addition to the system repository, OSTree supports a
per-remote
<filename><replaceable>remotename</replaceable>.trustedkeys.gpg</filename>
file stored in the toplevel of the repository (alongside
<filename>objects/</filename> and such). This is
particularly useful when downloading content that may not
be fully trusted (e.g. you want to inspect it but not
deploy it as an OS), or use it for containers. This file
is written via <command>ostree remote add
--gpg-import</command>.
</para>
</refsect1>
<refsect1>

View File

@ -10,4 +10,5 @@ pages:
- Adapting Existing Systems: 'manual/adapting-existing.md'
- Formats: 'manual/formats.md'
- Build Systems and Repos: 'manual/buildsystem-and-repos.md'
- Repository Management: 'manual/repository-management.md'
- Related Projects: 'manual/related-projects.md'

View File

@ -22,7 +22,7 @@ dist-snapshot:
tar -A -f $${TARFILE_TMP} submodule.tar; \
rm submodule.tar; \
done; \
mv $(PKG_VER).tar{.tmp,}; \
mv $(PKG_VER).tar.tmp $(PKG_VER).tar; \
rm -f $(PKG_VER).tar.xz; \
xz $(PKG_VER).tar

View File

@ -0,0 +1,101 @@
#!/bin/sh
# To use a custrom script for generating grub.cfg, set the --with-grub2-mkconfig=no
# configure switch when configuring and building OSTree.
#
# This script is called by ostree/src/libostree/ostree-bootloader-grub2.c whenever
# boot loader configuration file needs to be updated. It can be used as a template
# for a custom grub.cfg generator. What to consider when writing a custom grub.cfg
# generator:
#
# - The populate_menu() function converts boot loader entries as defined by
# https://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/ into GRUB2
# menuentry sections. This is the core logic that is required by OSTree
# based system.
#
# - Embedded systems: Be aware that this script is executed not only on a host machine by OS
# installer, but also on a target device, thus think about shell portability. A target device
# for example might be using busybox with a limited shell.
#
# Feel free to edit this script to fit your requirements.
set -e
script=$(basename ${0})
# Atomically safe location where to generete grub.cfg when executing system upgrade.
new_grub2_cfg=${2}
entries_path=$(dirname $new_grub2_cfg)/entries
read_config()
{
config_file=${entries_path}/${1}
title=""
initrd=""
options=""
linux=""
while read -r line
do
record=$(echo ${line} | cut -f 1 -d ' ')
value=$(echo ${line} | cut -s -f2- -d ' ')
case "${record}" in
"title")
title=${value}
;;
"initrd")
initrd=${value}
;;
"linux")
linux=${value}
;;
"options")
options=${value}
;;
esac
done < ${config_file}
if [ -z "${title}" ]; then
title="(Untitled)"
fi
}
populate_menu()
{
boot_prefix="${OSTREE_BOOT_PARTITION}"
for config in $(ls ${entries_path}); do
read_config ${config}
menu="${menu}menuentry '${title}' {\n"
menu="${menu}\t linux ${boot_prefix}${linux} ${options}\n"
menu="${menu}\t initrd ${boot_prefix}${initrd}\n"
menu="${menu}}\n\n"
done
# The printf command seems to be more reliable across shells for special character (\n, \t) evaluation
printf "$menu" >> ${new_grub2_cfg}
}
populate_warning()
{
cat >> ${new_grub2_cfg} <<EOF
# This file was generated by ${script}. Do not modify the generated file - all changes will
# be lost the next time file is regenerated. For more details refer to the ${script} script.
EOF
}
populate_header()
{
cat >> ${new_grub2_cfg} <<EOF
serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1
default=boot
timeout=10
EOF
}
generate_grub2_cfg()
{
populate_warning
populate_header
populate_menu
}
generate_grub2_cfg

View File

@ -328,8 +328,12 @@ global:
* NOTE NOTE NOTE
*/
/* UNCOMMENT WITH NEW SYMBOLS HERE:
LIBOSTREE_2016.5 {
global:
ostree_repo_import_object_from_with_trust;
ostree_sepolicy_get_csum;
ostree_repo_get_remote_option;
ostree_repo_get_remote_list_option;
ostree_repo_get_remote_boolean_option;
ostree_repo_set_cache_dir;
} LIBOSTREE_2016.4;
*/

View File

@ -299,8 +299,25 @@ _ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader,
g_autofree char *bootversion_str = g_strdup_printf ("%u", (guint)bootversion);
g_autoptr(GFile) config_path_efi_dir = NULL;
g_autofree char *grub2_mkconfig_chroot = NULL;
gboolean use_system_grub2_mkconfig = TRUE;
const gchar *grub_exec = NULL;
if (ostree_sysroot_get_booted_deployment (self->sysroot) == NULL
#ifdef USE_BUILTIN_GRUB2_MKCONFIG
use_system_grub2_mkconfig = FALSE;
#endif
/* Autotests can set this envvar to select which code path to test, useful for OS installers as well */
grub_exec = g_getenv ("OSTREE_GRUB2_EXEC");
if (grub_exec)
{
if (g_str_has_suffix (grub_exec, GRUB2_MKCONFIG_PATH))
use_system_grub2_mkconfig = TRUE;
else
use_system_grub2_mkconfig = FALSE;
}
else
grub_exec = use_system_grub2_mkconfig ? GRUB2_MKCONFIG_PATH : LIBEXECDIR "/ostree-grub-generator";
if (use_system_grub2_mkconfig && ostree_sysroot_get_booted_deployment (self->sysroot) == NULL
&& g_file_has_parent (self->sysroot->path, NULL))
{
g_autoptr(GPtrArray) deployments = NULL;
@ -318,6 +335,9 @@ _ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader,
*
* In the case of an installer, use the first deployment root (which
* will most likely be the only one.
*
* This all only applies if we're not using the builtin
* generator, which handles being run outside of the root.
*/
tool_deployment_root = ostree_sysroot_get_deployment_directory (self->sysroot, tool_deployment);
grub2_mkconfig_chroot = g_file_get_path (tool_deployment_root);
@ -361,7 +381,7 @@ _ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader,
Upstream is fixed though.
*/
proc = g_subprocess_launcher_spawn (launcher, error,
"grub2-mkconfig", "-o",
grub_exec, "-o",
gs_file_get_path_cached (new_config_path),
NULL);

View File

@ -46,7 +46,8 @@ ostree_cmd__private__ (void)
{
static OstreeCmdPrivateVTable table = {
impl_ostree_generate_grub2_config,
_ostree_repo_static_delta_dump
_ostree_repo_static_delta_dump,
_ostree_repo_static_delta_delete
};
return &table;

View File

@ -27,6 +27,7 @@ G_BEGIN_DECLS
typedef struct {
gboolean (* ostree_generate_grub2_config) (OstreeSysroot *sysroot, int bootversion, int target_fd, GCancellable *cancellable, GError **error);
gboolean (* ostree_static_delta_dump) (OstreeRepo *repo, const char *delta_id, GCancellable *cancellable, GError **error);
gboolean (* ostree_static_delta_delete) (OstreeRepo *repo, const char *delta_id, GCancellable *cancellable, GError **error);
} OstreeCmdPrivateVTable;
/* Note this not really "public", we just export the symbol, but not the header */

View File

@ -541,6 +541,7 @@ _ostree_fetcher_constructed (GObject *object)
self->thread_closure->output_stream_set = g_hash_table_new_full (NULL, NULL,
(GDestroyNotify) NULL,
(GDestroyNotify) g_object_unref);
g_mutex_init (&self->thread_closure->output_stream_set_lock);
if (g_getenv ("OSTREE_DEBUG_HTTP"))
{

View File

@ -491,7 +491,7 @@ try_metalink_targets (OstreeMetalinkRequest *self,
GError **error)
{
gboolean ret = FALSE;
SoupURI *target_uri;
SoupURI *target_uri = NULL;
if (!self->found_a_file_element)
{
@ -564,7 +564,7 @@ try_metalink_targets (OstreeMetalinkRequest *self,
self->urls->len, self->last_metalink_error);
goto out;
}
ret = TRUE;
if (out_target_uri)
*out_target_uri = soup_uri_copy (target_uri);

View File

@ -2525,7 +2525,7 @@ write_directory_content_to_mtree_internal (OstreeRepo *self,
}
if (!get_modified_xattrs (self, modifier,
child_relpath, child_info, child, dfd_iter->fd, name,
child_relpath, child_info, child, dfd_iter != NULL ? dfd_iter->fd : -1, name,
&xattrs,
cancellable, error))
goto out;

View File

@ -745,52 +745,6 @@ query_child_info_dir (OstreeRepo *repo,
return ret;
}
static gboolean
bsearch_in_file_variant (GVariant *variant,
const char *name,
int *out_pos)
{
gsize imax, imin;
gsize imid;
gsize n;
n = g_variant_n_children (variant);
if (n == 0)
return FALSE;
imax = n - 1;
imin = 0;
while (imax >= imin)
{
g_autoptr(GVariant) child = NULL;
const char *cur;
int cmp;
imid = (imin + imax) / 2;
child = g_variant_get_child_value (variant, imid);
g_variant_get_child (child, 0, "&s", &cur, NULL);
cmp = strcmp (cur, name);
if (cmp < 0)
imin = imid + 1;
else if (cmp > 0)
{
if (imid == 0)
break;
imax = imid - 1;
}
else
{
*out_pos = imid;
return TRUE;
}
}
*out_pos = imid;
return FALSE;
}
int
ostree_repo_file_tree_find_child (OstreeRepoFile *self,
const char *name,
@ -806,7 +760,7 @@ ostree_repo_file_tree_find_child (OstreeRepoFile *self,
dirs_variant = g_variant_get_child_value (self->tree_contents, 1);
i = -1;
if (bsearch_in_file_variant (files_variant, name, &i))
if (ot_variant_bsearch_str (files_variant, name, &i))
{
*is_dir = FALSE;
ret_container = files_variant;
@ -814,7 +768,7 @@ ostree_repo_file_tree_find_child (OstreeRepoFile *self,
}
else
{
if (bsearch_in_file_variant (dirs_variant, name, &i))
if (ot_variant_bsearch_str (dirs_variant, name, &i))
{
*is_dir = TRUE;
ret_container = dirs_variant;

View File

@ -33,7 +33,8 @@ G_BEGIN_DECLS
#define _OSTREE_OBJECT_SIZES_ENTRY_SIGNATURE "ay"
#define _OSTREE_SUMMARY_CACHE_PATH "tmp/cache/summaries"
#define _OSTREE_SUMMARY_CACHE_DIR "summaries"
#define _OSTREE_CACHE_DIR "cache"
/**
* OstreeRepo:
@ -52,6 +53,8 @@ struct OstreeRepo {
int repo_dir_fd;
GFile *tmp_dir;
int tmp_dir_fd;
int cache_dir_fd;
char *cache_dir;
GFile *objects_dir;
GFile *state_dir;
int objects_dir_fd;
@ -60,6 +63,7 @@ struct OstreeRepo {
int uncompressed_objects_dir_fd;
GFile *config_file;
GFile *sysroot_dir;
char *remotes_config_dir;
GFile *transaction_lock_path;
GHashTable *txn_refs;
@ -195,36 +199,6 @@ _ostree_repo_commit_modifier_apply (OstreeRepo *self,
gboolean
_ostree_repo_remote_name_is_file (const char *remote_name);
gboolean
_ostree_repo_get_remote_option (OstreeRepo *self,
const char *remote_name,
const char *option_name,
const char *default_value,
char **out_value,
GError **error);
gboolean
_ostree_repo_get_remote_list_option (OstreeRepo *self,
const char *remote_name,
const char *option_name,
char ***out_value,
GError **error);
gboolean
_ostree_repo_get_remote_boolean_option (OstreeRepo *self,
const char *remote_name,
const char *option_name,
gboolean default_value,
gboolean *out_value,
GError **error);
gboolean
_ostree_repo_get_remote_option_inherit (OstreeRepo *self,
const char *remote_name,
const char *option_name,
char **out_value,
GError **error);
#ifdef HAVE_LIBSOUP
OstreeFetcher *
_ostree_repo_remote_new_fetcher (OstreeRepo *self,

View File

@ -74,6 +74,8 @@ maybe_prune_loose_object (OtPruneData *data,
if (!g_hash_table_lookup_extended (data->reachable, key, NULL, NULL))
{
g_debug ("Pruning unneeded object %s.%s", checksum,
ostree_object_type_to_string (objtype));
if (!(flags & OSTREE_REPO_PRUNE_FLAGS_NO_PRUNE))
{
guint64 storage_size = 0;
@ -101,6 +103,8 @@ maybe_prune_loose_object (OtPruneData *data,
}
else
{
g_debug ("Keeping needed object %s.%s", checksum,
ostree_object_type_to_string (objtype));
if (OSTREE_OBJECT_TYPE_IS_META (objtype))
data->n_reachable_meta++;
else
@ -121,7 +125,10 @@ _ostree_repo_prune_tmp (OstreeRepo *self,
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
glnx_fd_close int fd = -1;
fd = glnx_opendirat_with_errno (self->repo_dir_fd, _OSTREE_SUMMARY_CACHE_PATH, FALSE);
if (self->cache_dir_fd == -1)
return TRUE;
fd = glnx_opendirat_with_errno (self->cache_dir_fd, _OSTREE_SUMMARY_CACHE_DIR, FALSE);
if (fd < 0)
{
if (errno == ENOENT)
@ -234,6 +241,7 @@ ostree_repo_prune_static_deltas (OstreeRepo *self, const char *commit,
continue;
}
g_debug ("Trying to prune static delta %s", deltaname);
deltadir = _ostree_get_relative_static_delta_path (from, to, NULL);
if (!glnx_shutil_rm_rf_at (self->repo_dir_fd, deltadir,
@ -310,6 +318,7 @@ ostree_repo_prune (OstreeRepo *self,
error))
goto out;
g_debug ("Finding objects to keep for commit %s", checksum);
if (!ostree_repo_traverse_commit_union (self, checksum, depth, data.reachable,
cancellable, &local_error))
{
@ -352,6 +361,7 @@ ostree_repo_prune (OstreeRepo *self,
error))
goto out;
g_debug ("Finding objects to keep for commit %s", checksum);
if (!ostree_repo_traverse_commit_union (self, checksum, depth, data.reachable,
cancellable, &local_error))
{

View File

@ -93,6 +93,7 @@ typedef struct {
gboolean is_mirror;
gboolean is_commit_only;
gboolean is_untrusted;
char *dir;
gboolean commitpartial_exists;
@ -447,12 +448,7 @@ scan_dirtree_object (OtPullData *pull_data,
files_variant = g_variant_get_child_value (tree, 0);
dirs_variant = g_variant_get_child_value (tree, 1);
/* Skip files if we're traversing a request only directory */
if (pull_data->dir)
n = 0;
else
n = g_variant_n_children (files_variant);
n = g_variant_n_children (files_variant);
for (i = 0; i < n; i++)
{
const char *filename;
@ -465,6 +461,14 @@ scan_dirtree_object (OtPullData *pull_data,
if (!ot_util_filename_validate (filename, error))
goto out;
/* Skip files if we're traversing a request only directory, unless it exactly
* matches the path */
if (pull_data->dir &&
/* Should always an initial slash, we assert it in scan_dirtree_object */
pull_data->dir[0] == '/' &&
strcmp (pull_data->dir+1, filename) != 0)
continue;
file_checksum = ostree_checksum_from_bytes_v (csum);
if (!ostree_repo_has_object (pull_data->repo, OSTREE_OBJECT_TYPE_FILE, file_checksum,
@ -473,9 +477,9 @@ scan_dirtree_object (OtPullData *pull_data,
if (!file_is_stored && pull_data->remote_repo_local)
{
if (!ostree_repo_import_object_from (pull_data->repo, pull_data->remote_repo_local,
OSTREE_OBJECT_TYPE_FILE, file_checksum,
cancellable, error))
if (!ostree_repo_import_object_from_with_trust (pull_data->repo, pull_data->remote_repo_local,
OSTREE_OBJECT_TYPE_FILE, file_checksum, !pull_data->is_untrusted,
cancellable, error))
goto out;
}
else if (!file_is_stored && !g_hash_table_lookup (pull_data->requested_content, file_checksum))
@ -1189,9 +1193,9 @@ scan_one_metadata_object_c (OtPullData *pull_data,
if (pull_data->remote_repo_local)
{
if (!is_stored &&
!ostree_repo_import_object_from (pull_data->repo, pull_data->remote_repo_local,
objtype, tmp_checksum,
cancellable, error))
!ostree_repo_import_object_from_with_trust (pull_data->repo, pull_data->remote_repo_local,
objtype, tmp_checksum, !pull_data->is_untrusted,
cancellable, error))
goto out;
is_stored = TRUE;
is_requested = TRUE;
@ -1779,12 +1783,15 @@ _ostree_repo_load_cache_summary_if_same_sig (OstreeRepo *self,
GError **error)
{
gboolean ret = FALSE;
const char *summary_cache_sig_file = glnx_strjoina (_OSTREE_SUMMARY_CACHE_PATH, "/", remote, ".sig");
const char *summary_cache_sig_file = glnx_strjoina (_OSTREE_SUMMARY_CACHE_DIR, "/", remote, ".sig");
glnx_fd_close int prev_fd = -1;
g_autoptr(GBytes) old_sig_contents = NULL;
if (!ot_openat_ignore_enoent (self->repo_dir_fd, summary_cache_sig_file, &prev_fd, error))
if (self->cache_dir_fd == -1)
return TRUE;
if (!ot_openat_ignore_enoent (self->cache_dir_fd, summary_cache_sig_file, &prev_fd, error))
goto out;
if (prev_fd < 0)
@ -1799,17 +1806,17 @@ _ostree_repo_load_cache_summary_if_same_sig (OstreeRepo *self,
if (g_bytes_compare (old_sig_contents, summary_sig) == 0)
{
const char *summary_cache_file = glnx_strjoina (_OSTREE_SUMMARY_CACHE_PATH, "/", remote);
const char *summary_cache_file = glnx_strjoina (_OSTREE_SUMMARY_CACHE_DIR, "/", remote);
glnx_fd_close int summary_fd = -1;
GBytes *summary_data;
summary_fd = openat (self->repo_dir_fd, summary_cache_file, O_CLOEXEC | O_RDONLY);
summary_fd = openat (self->cache_dir_fd, summary_cache_file, O_CLOEXEC | O_RDONLY);
if (summary_fd < 0)
{
if (errno == ENOENT)
{
(void) unlinkat (self->repo_dir_fd, summary_cache_sig_file, 0);
(void) unlinkat (self->cache_dir_fd, summary_cache_sig_file, 0);
ret = TRUE;
goto out;
}
@ -1838,13 +1845,16 @@ _ostree_repo_cache_summary (OstreeRepo *self,
GError **error)
{
gboolean ret = FALSE;
const char *summary_cache_file = glnx_strjoina (_OSTREE_SUMMARY_CACHE_PATH, "/", remote);
const char *summary_cache_sig_file = glnx_strjoina (_OSTREE_SUMMARY_CACHE_PATH, "/", remote, ".sig");
const char *summary_cache_file = glnx_strjoina (_OSTREE_SUMMARY_CACHE_DIR, "/", remote);
const char *summary_cache_sig_file = glnx_strjoina (_OSTREE_SUMMARY_CACHE_DIR, "/", remote, ".sig");
if (!glnx_shutil_mkdir_p_at (self->repo_dir_fd, _OSTREE_SUMMARY_CACHE_PATH, 0775, cancellable, error))
if (self->cache_dir_fd == -1)
return TRUE;
if (!glnx_shutil_mkdir_p_at (self->cache_dir_fd, _OSTREE_SUMMARY_CACHE_DIR, 0775, cancellable, error))
goto out;
if (!glnx_file_replace_contents_at (self->repo_dir_fd,
if (!glnx_file_replace_contents_at (self->cache_dir_fd,
summary_cache_file,
g_bytes_get_data (summary, NULL),
g_bytes_get_size (summary),
@ -1852,7 +1862,7 @@ _ostree_repo_cache_summary (OstreeRepo *self,
cancellable, error))
goto out;
if (!glnx_file_replace_contents_at (self->repo_dir_fd,
if (!glnx_file_replace_contents_at (self->cache_dir_fd,
summary_cache_sig_file,
g_bytes_get_data (summary_sig, NULL),
g_bytes_get_size (summary_sig),
@ -1899,16 +1909,20 @@ ostree_repo_pull_with_options (OstreeRepo *self,
GSource *update_timeout = NULL;
gboolean disable_static_deltas = FALSE;
gboolean require_static_deltas = FALSE;
gboolean opt_gpg_verify = FALSE;
gboolean opt_gpg_verify_summary = FALSE;
if (options)
{
int flags_i;
int flags_i = OSTREE_REPO_PULL_FLAGS_NONE;
(void) g_variant_lookup (options, "refs", "^a&s", &refs_to_fetch);
(void) g_variant_lookup (options, "flags", "i", &flags_i);
/* Reduce risk of issues if enum happens to be 64 bit for some reason */
flags = flags_i;
(void) g_variant_lookup (options, "subdir", "&s", &dir_to_pull);
(void) g_variant_lookup (options, "override-remote-name", "s", &pull_data->remote_name);
(void) g_variant_lookup (options, "gpg-verify", "b", &opt_gpg_verify);
(void) g_variant_lookup (options, "gpg-verify-summary", "b", &opt_gpg_verify_summary);
(void) g_variant_lookup (options, "depth", "i", &pull_data->maxdepth);
(void) g_variant_lookup (options, "disable-static-deltas", "b", &disable_static_deltas);
(void) g_variant_lookup (options, "require-static-deltas", "b", &require_static_deltas);
@ -1931,6 +1945,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
pull_data->is_mirror = (flags & OSTREE_REPO_PULL_FLAGS_MIRROR) > 0;
pull_data->is_commit_only = (flags & OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY) > 0;
pull_data->is_untrusted = (flags & OSTREE_REPO_PULL_FLAGS_UNTRUSTED) > 0;
if (error)
pull_data->async_error = &pull_data->cached_async_error;
@ -1965,18 +1980,26 @@ ostree_repo_pull_with_options (OstreeRepo *self,
if (_ostree_repo_remote_name_is_file (remote_name_or_baseurl))
{
/* For compatibility with pull-local, don't gpg verify local
* pulls.
* pulls by default.
*/
pull_data->gpg_verify = FALSE;
pull_data->gpg_verify_summary = FALSE;
pull_data->gpg_verify = opt_gpg_verify;
pull_data->gpg_verify_summary = opt_gpg_verify_summary;
if ((pull_data->gpg_verify || pull_data->gpg_verify_summary) &&
pull_data->remote_name == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Must specify remote name to enable gpg verification");
goto out;
}
}
else
{
pull_data->remote_name = g_strdup (remote_name_or_baseurl);
if (!ostree_repo_remote_get_gpg_verify (self, remote_name_or_baseurl,
if (!ostree_repo_remote_get_gpg_verify (self, pull_data->remote_name,
&pull_data->gpg_verify, error))
goto out;
if (!ostree_repo_remote_get_gpg_verify_summary (self, remote_name_or_baseurl,
if (!ostree_repo_remote_get_gpg_verify_summary (self, pull_data->remote_name,
&pull_data->gpg_verify_summary, error))
goto out;
}
@ -1991,9 +2014,9 @@ ostree_repo_pull_with_options (OstreeRepo *self,
requested_refs_to_fetch = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
commits_to_fetch = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
if (!_ostree_repo_get_remote_option (self,
remote_name_or_baseurl, "metalink",
NULL, &metalink_url_str, error))
if (!ostree_repo_get_remote_option (self,
remote_name_or_baseurl, "metalink",
NULL, &metalink_url_str, error))
goto out;
if (!metalink_url_str)
@ -2047,9 +2070,9 @@ ostree_repo_pull_with_options (OstreeRepo *self,
summary_bytes, FALSE);
}
if (!_ostree_repo_get_remote_list_option (self,
remote_name_or_baseurl, "branches",
&configured_branches, error))
if (!ostree_repo_get_remote_list_option (self,
remote_name_or_baseurl, "branches",
&configured_branches, error))
goto out;
if (strcmp (soup_uri_get_scheme (pull_data->base_uri), "file") == 0)
@ -2105,12 +2128,14 @@ ostree_repo_pull_with_options (OstreeRepo *self,
soup_uri_free (uri);
}
if (bytes_sig && !_ostree_repo_load_cache_summary_if_same_sig (self,
remote_name_or_baseurl,
bytes_sig,
&bytes_summary,
cancellable,
error))
if (bytes_sig &&
!pull_data->remote_repo_local &&
!_ostree_repo_load_cache_summary_if_same_sig (self,
remote_name_or_baseurl,
bytes_sig,
&bytes_summary,
cancellable,
error))
goto out;
if (bytes_summary)
@ -2158,7 +2183,8 @@ ostree_repo_pull_with_options (OstreeRepo *self,
if (!summary_from_cache && bytes_summary && bytes_sig)
{
if (!_ostree_repo_cache_summary (self,
if (!pull_data->remote_repo_local &&
!_ostree_repo_cache_summary (self,
remote_name_or_baseurl,
bytes_summary,
bytes_sig,
@ -2176,7 +2202,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
result = _ostree_repo_gpg_verify_with_metadata (self,
bytes_summary,
sig_variant,
remote_name_or_baseurl,
pull_data->remote_name,
NULL,
NULL,
cancellable,

View File

@ -749,7 +749,10 @@ _ostree_repo_write_ref (OstreeRepo *self,
{
if (!glnx_opendirat (self->repo_dir_fd, "refs/heads", TRUE,
&dfd, error))
goto out;
{
g_prefix_error (error, "Opening %s: ", "refs/heads");
goto out;
}
}
else
{
@ -757,7 +760,10 @@ _ostree_repo_write_ref (OstreeRepo *self,
if (!glnx_opendirat (self->repo_dir_fd, "refs/remotes", TRUE,
&refs_remotes_dfd, error))
goto out;
{
g_prefix_error (error, "Opening %s: ", "refs/remotes");
goto out;
}
if (rev != NULL)
{
@ -767,7 +773,10 @@ _ostree_repo_write_ref (OstreeRepo *self,
}
if (!glnx_opendirat (refs_remotes_dfd, remote, TRUE, &dfd, error))
goto out;
{
g_prefix_error (error, "Opening remotes/ dir %s: ", remote);
goto out;
}
}
if (rev == NULL)

View File

@ -455,7 +455,7 @@ get_unpacked_unlinked_content (OstreeRepo *repo,
GError **error)
{
gboolean ret = FALSE;
g_autofree char *tmpname = g_strdup ("tmpostree-deltaobj-XXXXXX");
g_autofree char *tmpname = g_strdup ("/var/tmp/tmpostree-deltaobj-XXXXXX");
glnx_fd_close int fd = -1;
g_autoptr(GBytes) ret_content = NULL;
g_autoptr(GInputStream) istream = NULL;

View File

@ -782,6 +782,41 @@ _ostree_delta_needs_byteswap (GVariant *superblock)
}
}
gboolean
_ostree_repo_static_delta_delete (OstreeRepo *self,
const char *delta_id,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
g_autofree char *from = NULL;
g_autofree char *to = NULL;
g_autofree char *deltadir = NULL;
struct stat buf;
_ostree_parse_delta_name (delta_id, &from, &to);
deltadir = _ostree_get_relative_static_delta_path (from, to, NULL);
if (fstatat (self->repo_dir_fd, deltadir, &buf, 0) != 0)
{
if (errno == ENOENT)
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"Can't find delta %s", delta_id);
else
glnx_set_error_from_errno (error);
goto out;
}
if (!glnx_shutil_rm_rf_at (self->repo_dir_fd, deltadir,
cancellable, error))
goto out;
ret = TRUE;
out:
return ret;
}
gboolean
_ostree_repo_static_delta_dump (OstreeRepo *self,
const char *delta_id,

View File

@ -196,6 +196,12 @@ _ostree_repo_static_delta_dump (OstreeRepo *repo,
GCancellable *cancellable,
GError **error);
gboolean
_ostree_repo_static_delta_delete (OstreeRepo *repo,
const char *delta_id,
GCancellable *cancellable,
GError **error);
/* Used for static deltas which due to a historical mistake are
* inconsistent endian.
*

View File

@ -106,6 +106,12 @@ OPPROTO(close)
OPPROTO(bspatch)
#undef OPPROTO
static void
static_delta_execution_state_init (StaticDeltaExecutionState *state)
{
state->read_source_fd = -1;
}
static gboolean
read_varuint64 (StaticDeltaExecutionState *state,
guint64 *out_value,
@ -195,6 +201,8 @@ _ostree_static_delta_part_execute (OstreeRepo *repo,
StaticDeltaExecutionState *state = &statedata;
guint n_executed = 0;
static_delta_execution_state_init (&statedata);
state->repo = repo;
state->async_error = error;
state->trusted = trusted;

View File

@ -328,6 +328,7 @@ traverse_iter (OstreeRepo *repo,
ostree_repo_commit_traverse_iter_get_file (iter, &name, &checksum);
g_debug ("Found file object %s", checksum);
key = ostree_object_name_serialize (checksum, OSTREE_OBJECT_TYPE_FILE);
g_hash_table_replace (inout_reachable, key, key);
key = NULL;
@ -341,6 +342,8 @@ traverse_iter (OstreeRepo *repo,
ostree_repo_commit_traverse_iter_get_dir (iter, &name, &content_checksum,
&meta_checksum);
g_debug ("Found dirtree object %s", content_checksum);
g_debug ("Found dirmeta object %s", meta_checksum);
key = ostree_object_name_serialize (meta_checksum, OSTREE_OBJECT_TYPE_DIR_META);
g_hash_table_replace (inout_reachable, key, key);
key = NULL;
@ -381,6 +384,7 @@ traverse_dirtree (OstreeRepo *repo,
&dirtree, error))
goto out;
g_debug ("Traversing dirtree %s", checksum);
if (!ostree_repo_commit_traverse_iter_init_dirtree (&iter, repo, dirtree,
OSTREE_REPO_COMMIT_TRAVERSE_FLAG_NONE,
error))
@ -444,6 +448,7 @@ ostree_repo_traverse_commit_union (OstreeRepo *repo,
g_hash_table_add (inout_reachable, key);
key = NULL;
g_debug ("Traversing commit %s", commit_checksum);
if (!ostree_repo_commit_traverse_iter_init_commit (&iter, repo, commit,
OSTREE_REPO_COMMIT_TRAVERSE_FLAG_NONE,
error))

View File

@ -88,6 +88,7 @@ enum {
PROP_0,
PROP_PATH,
PROP_REMOTES_CONFIG_DIR,
PROP_SYSROOT_PATH
};
@ -217,6 +218,27 @@ ost_repo_get_remote (OstreeRepo *self,
return remote;
}
static OstreeRemote *
ost_repo_get_remote_inherited (OstreeRepo *self,
const char *name,
GError **error)
{
local_cleanup_remote OstreeRemote *remote = NULL;
g_autoptr(GError) temp_error = NULL;
remote = ost_repo_get_remote (self, name, &temp_error);
if (remote == NULL)
{
if (self->parent_repo != NULL)
return ost_repo_get_remote_inherited (self->parent_repo, name, error);
g_propagate_error (error, g_steal_pointer (&temp_error));
return NULL;
}
return g_steal_pointer (&remote);
}
static void
ost_repo_add_remote (OstreeRepo *self,
OstreeRemote *remote)
@ -257,16 +279,34 @@ _ostree_repo_remote_name_is_file (const char *remote_name)
return g_str_has_prefix (remote_name, "file://");
}
/**
* ostree_repo_get_remote_option:
* @self: A OstreeRepo
* @remote_name: Name
* @option_name: Option
* @default_value: (allow-none): Value returned if @option_name is not present
* @out_value: (out): Return location for value
* @error: Error
*
* OSTree remotes are represented by keyfile groups, formatted like:
* `[remote "remotename"]`. This function returns a value named @option_name
* underneath that group, or @default_value if the remote exists but not the
* option name.
*
* Returns: %TRUE on success, otherwise %FALSE with @error set
*/
gboolean
_ostree_repo_get_remote_option (OstreeRepo *self,
const char *remote_name,
const char *option_name,
const char *default_value,
char **out_value,
GError **error)
ostree_repo_get_remote_option (OstreeRepo *self,
const char *remote_name,
const char *option_name,
const char *default_value,
char **out_value,
GError **error)
{
local_cleanup_remote OstreeRemote *remote = NULL;
gboolean ret = FALSE;
g_autoptr(GError) temp_error = NULL;
g_autofree char *value = NULL;
if (_ostree_repo_remote_name_is_file (remote_name))
{
@ -274,30 +314,71 @@ _ostree_repo_get_remote_option (OstreeRepo *self,
return TRUE;
}
remote = ost_repo_get_remote (self, remote_name, error);
remote = ost_repo_get_remote (self, remote_name, &temp_error);
if (remote != NULL)
{
ret = ot_keyfile_get_value_with_default (remote->options,
remote->group,
option_name,
default_value,
out_value,
error);
}
value = g_key_file_get_string (remote->options, remote->group, option_name, &temp_error);
if (value == NULL)
{
if (g_error_matches (temp_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND))
{
if (self->parent_repo != NULL)
return ostree_repo_get_remote_option (self->parent_repo,
remote_name, option_name,
default_value,
out_value,
error);
value = g_strdup (default_value);
ret = TRUE;
}
else
g_propagate_error (error, g_steal_pointer (&temp_error));
}
else
ret = TRUE;
}
else if (self->parent_repo != NULL)
return ostree_repo_get_remote_option (self->parent_repo,
remote_name, option_name,
default_value,
out_value,
error);
else
g_propagate_error (error, g_steal_pointer (&temp_error));
*out_value = g_steal_pointer (&value);
return ret;
}
/**
* ostree_repo_get_remote_list_option:
* @self: A OstreeRepo
* @remote_name: Name
* @option_name: Option
* @out_value: (out) (array zero-terminated=1): location to store the list
* of strings. The list should be freed with
* g_strfreev().
* @error: Error
*
* OSTree remotes are represented by keyfile groups, formatted like:
* `[remote "remotename"]`. This function returns a value named @option_name
* underneath that group, and returns it as an zero terminated array of strings.
* If the option is not set, @out_value will be set to %NULL.
*
* Returns: %TRUE on success, otherwise %FALSE with @error set
*/
gboolean
_ostree_repo_get_remote_list_option (OstreeRepo *self,
const char *remote_name,
const char *option_name,
char ***out_value,
GError **error)
ostree_repo_get_remote_list_option (OstreeRepo *self,
const char *remote_name,
const char *option_name,
char ***out_value,
GError **error)
{
local_cleanup_remote OstreeRemote *remote = NULL;
gboolean ret = FALSE;
g_autoptr(GError) temp_error = NULL;
g_auto(GStrv) value = NULL;
if (_ostree_repo_remote_name_is_file (remote_name))
{
@ -305,96 +386,110 @@ _ostree_repo_get_remote_list_option (OstreeRepo *self,
return TRUE;
}
remote = ost_repo_get_remote (self, remote_name, error);
remote = ost_repo_get_remote (self, remote_name, &temp_error);
if (remote != NULL)
{
g_auto(GStrv) value = NULL;
GError *local_error = NULL;
value = g_key_file_get_string_list (remote->options,
remote->group,
option_name,
NULL, &local_error);
NULL, &temp_error);
/* Default value if key not found is always NULL. */
if (g_error_matches (local_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND))
g_clear_error (&local_error);
if (local_error == NULL)
if (g_error_matches (temp_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND))
{
ot_transfer_out_value (out_value, &value);
if (self->parent_repo != NULL)
return ostree_repo_get_remote_list_option (self->parent_repo,
remote_name, option_name,
out_value,
error);
ret = TRUE;
}
else if (temp_error)
g_propagate_error (error, g_steal_pointer (&temp_error));
else
ret = TRUE;
}
else if (self->parent_repo != NULL)
return ostree_repo_get_remote_list_option (self->parent_repo,
remote_name, option_name,
out_value,
error);
else
g_propagate_error (error, g_steal_pointer (&temp_error));
*out_value = g_steal_pointer (&value);
return ret;
}
/**
* ostree_repo_get_remote_boolean_option:
* @self: A OstreeRepo
* @remote_name: Name
* @option_name: Option
* @default_value: (allow-none): Value returned if @option_name is not present
* @out_value: (out) : location to store the result.
* @error: Error
*
* OSTree remotes are represented by keyfile groups, formatted like:
* `[remote "remotename"]`. This function returns a value named @option_name
* underneath that group, and returns it as a boolean.
* If the option is not set, @out_value will be set to @default_value.
*
* Returns: %TRUE on success, otherwise %FALSE with @error set
*/
gboolean
_ostree_repo_get_remote_boolean_option (OstreeRepo *self,
const char *remote_name,
const char *option_name,
gboolean default_value,
gboolean *out_value,
GError **error)
ostree_repo_get_remote_boolean_option (OstreeRepo *self,
const char *remote_name,
const char *option_name,
gboolean default_value,
gboolean *out_value,
GError **error)
{
local_cleanup_remote OstreeRemote *remote = NULL;
g_autoptr(GError) temp_error = NULL;
gboolean ret = FALSE;
gboolean value = FALSE;
if (_ostree_repo_remote_name_is_file (remote_name))
{
*out_value = default_value;
return TRUE;
}
remote = ost_repo_get_remote (self, remote_name, error);
remote = ost_repo_get_remote (self, remote_name, &temp_error);
if (remote != NULL)
{
ret = ot_keyfile_get_boolean_with_default (remote->options,
remote->group,
option_name,
default_value,
out_value,
error);
value = g_key_file_get_boolean (remote->options, remote->group, option_name, &temp_error);
if (temp_error != NULL)
{
if (g_error_matches (temp_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND))
{
if (self->parent_repo != NULL)
return ostree_repo_get_remote_boolean_option (self->parent_repo,
remote_name, option_name,
default_value,
out_value,
error);
value = default_value;
ret = TRUE;
}
else
g_propagate_error (error, g_steal_pointer (&temp_error));
}
else
ret = TRUE;
}
else if (self->parent_repo != NULL)
return ostree_repo_get_remote_boolean_option (self->parent_repo,
remote_name, option_name,
default_value,
out_value,
error);
else
g_propagate_error (error, g_steal_pointer (&temp_error));
return ret;
}
gboolean
_ostree_repo_get_remote_option_inherit (OstreeRepo *self,
const char *remote_name,
const char *option_name,
char **out_value,
GError **error)
{
OstreeRepo *parent = ostree_repo_get_parent (self);
g_autofree char *value = NULL;
gboolean ret = FALSE;
if (!_ostree_repo_get_remote_option (self,
remote_name, option_name,
NULL, &value, error))
goto out;
if (value == NULL && parent != NULL)
{
if (!_ostree_repo_get_remote_option_inherit (parent,
remote_name, option_name,
&value, error))
goto out;
}
/* Success here just means no error occurred during lookup,
* not necessarily that we found a value for the option name. */
if (out_value != NULL)
*out_value = g_steal_pointer (&value);
ret = TRUE;
out:
*out_value = value;
return ret;
}
@ -412,9 +507,9 @@ _ostree_repo_remote_new_fetcher (OstreeRepo *self,
g_return_val_if_fail (OSTREE_IS_REPO (self), NULL);
g_return_val_if_fail (remote_name != NULL, NULL);
if (!_ostree_repo_get_remote_boolean_option (self, remote_name,
"tls-permissive", FALSE,
&tls_permissive, error))
if (!ostree_repo_get_remote_boolean_option (self, remote_name,
"tls-permissive", FALSE,
&tls_permissive, error))
goto out;
if (tls_permissive)
@ -426,13 +521,13 @@ _ostree_repo_remote_new_fetcher (OstreeRepo *self,
g_autofree char *tls_client_cert_path = NULL;
g_autofree char *tls_client_key_path = NULL;
if (!_ostree_repo_get_remote_option (self, remote_name,
"tls-client-cert-path", NULL,
&tls_client_cert_path, error))
if (!ostree_repo_get_remote_option (self, remote_name,
"tls-client-cert-path", NULL,
&tls_client_cert_path, error))
goto out;
if (!_ostree_repo_get_remote_option (self, remote_name,
"tls-client-key-path", NULL,
&tls_client_key_path, error))
if (!ostree_repo_get_remote_option (self, remote_name,
"tls-client-key-path", NULL,
&tls_client_key_path, error))
goto out;
if ((tls_client_cert_path != NULL) != (tls_client_key_path != NULL))
@ -462,9 +557,9 @@ _ostree_repo_remote_new_fetcher (OstreeRepo *self,
{
g_autofree char *tls_ca_path = NULL;
if (!_ostree_repo_get_remote_option (self, remote_name,
"tls-ca-path", NULL,
&tls_ca_path, error))
if (!ostree_repo_get_remote_option (self, remote_name,
"tls-ca-path", NULL,
&tls_ca_path, error))
goto out;
if (tls_ca_path != NULL)
@ -482,9 +577,9 @@ _ostree_repo_remote_new_fetcher (OstreeRepo *self,
{
g_autofree char *http_proxy = NULL;
if (!_ostree_repo_get_remote_option (self, remote_name,
"proxy", NULL,
&http_proxy, error))
if (!ostree_repo_get_remote_option (self, remote_name,
"proxy", NULL,
&http_proxy, error))
goto out;
if (http_proxy != NULL)
@ -519,6 +614,8 @@ ostree_repo_finalize (GObject *object)
g_clear_object (&self->tmp_dir);
if (self->tmp_dir_fd)
(void) close (self->tmp_dir_fd);
if (self->cache_dir_fd)
(void) close (self->cache_dir_fd);
g_clear_object (&self->objects_dir);
if (self->objects_dir_fd != -1)
(void) close (self->objects_dir_fd);
@ -529,6 +626,7 @@ ostree_repo_finalize (GObject *object)
(void) close (self->uncompressed_objects_dir_fd);
g_clear_object (&self->config_file);
g_clear_object (&self->sysroot_dir);
g_free (self->remotes_config_dir);
g_clear_object (&self->transaction_lock_path);
@ -568,6 +666,9 @@ ostree_repo_set_property(GObject *object,
case PROP_SYSROOT_PATH:
self->sysroot_dir = g_value_dup_object (value);
break;
case PROP_REMOTES_CONFIG_DIR:
self->remotes_config_dir = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -590,6 +691,9 @@ ostree_repo_get_property(GObject *object,
case PROP_SYSROOT_PATH:
g_value_set_object (value, self->sysroot_dir);
break;
case PROP_REMOTES_CONFIG_DIR:
g_value_set_string (value, self->remotes_config_dir);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -643,6 +747,13 @@ ostree_repo_class_init (OstreeRepoClass *klass)
"",
G_TYPE_FILE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_REMOTES_CONFIG_DIR,
g_param_spec_string ("remotes-config-dir",
"",
"",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
/**
* OstreeRepo::gpg-verify-result:
@ -690,6 +801,7 @@ ostree_repo_init (OstreeRepo *self)
g_mutex_init (&self->remotes_lock);
self->repo_dir_fd = -1;
self->cache_dir_fd = -1;
self->commit_stagedir_fd = -1;
self->objects_dir_fd = -1;
self->uncompressed_objects_dir_fd = -1;
@ -1216,6 +1328,25 @@ ostree_repo_remote_change (OstreeRepo *self,
g_assert_not_reached ();
}
static void
_ostree_repo_remote_list (OstreeRepo *self,
GHashTable *out)
{
GHashTableIter iter;
gpointer key, value;
g_mutex_lock (&self->remotes_lock);
g_hash_table_iter_init (&iter, self->remotes);
while (g_hash_table_iter_next (&iter, &key, &value))
g_hash_table_insert (out, g_strdup (key), NULL);
g_mutex_unlock (&self->remotes_lock);
if (self->parent_repo)
_ostree_repo_remote_list (self, out);
}
/**
* ostree_repo_remote_list:
* @self: Repo
@ -1233,10 +1364,15 @@ ostree_repo_remote_list (OstreeRepo *self,
{
char **remotes = NULL;
guint n_remotes;
g_autoptr(GHashTable) remotes_ht = NULL;
g_mutex_lock (&self->remotes_lock);
remotes_ht = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) g_free,
(GDestroyNotify) NULL);
n_remotes = g_hash_table_size (self->remotes);
_ostree_repo_remote_list (self, remotes_ht);
n_remotes = g_hash_table_size (remotes_ht);
if (n_remotes > 0)
{
@ -1245,7 +1381,7 @@ ostree_repo_remote_list (OstreeRepo *self,
remotes = g_new (char *, n_remotes + 1);
list = g_hash_table_get_keys (self->remotes);
list = g_hash_table_get_keys (remotes_ht);
list = g_list_sort (list, (GCompareFunc) strcmp);
for (link = list; link != NULL; link = link->next)
@ -1256,8 +1392,6 @@ ostree_repo_remote_list (OstreeRepo *self,
remotes[ii] = NULL;
}
g_mutex_unlock (&self->remotes_lock);
if (out_n_remotes)
*out_n_remotes = n_remotes;
@ -1293,7 +1427,7 @@ ostree_repo_remote_get_url (OstreeRepo *self,
}
else
{
if (!_ostree_repo_get_remote_option_inherit (self, name, "url", &url, error))
if (!ostree_repo_get_remote_option (self, name, "url", NULL, &url, error))
goto out;
if (url == NULL)
@ -1343,8 +1477,8 @@ ostree_repo_remote_get_gpg_verify (OstreeRepo *self,
return TRUE;
}
return _ostree_repo_get_remote_boolean_option (self, name, "gpg-verify",
TRUE, out_gpg_verify, error);
return ostree_repo_get_remote_boolean_option (self, name, "gpg-verify",
TRUE, out_gpg_verify, error);
}
/**
@ -1366,8 +1500,8 @@ ostree_repo_remote_get_gpg_verify_summary (OstreeRepo *self,
gboolean *out_gpg_verify_summary,
GError **error)
{
return _ostree_repo_get_remote_boolean_option (self, name, "gpg-verify-summary",
FALSE, out_gpg_verify_summary, error);
return ostree_repo_get_remote_boolean_option (self, name, "gpg-verify-summary",
FALSE, out_gpg_verify_summary, error);
}
/**
@ -1420,7 +1554,7 @@ ostree_repo_remote_gpg_import (OstreeRepo *self,
/* First make sure the remote name is valid. */
remote = ost_repo_get_remote (self, name, error);
remote = ost_repo_get_remote_inherited (self, name, error);
if (remote == NULL)
goto out;
@ -1889,8 +2023,8 @@ ostree_repo_remote_fetch_summary (OstreeRepo *self,
g_return_val_if_fail (OSTREE_REPO (self), FALSE);
g_return_val_if_fail (name != NULL, FALSE);
if (!_ostree_repo_get_remote_option (self, name, "metalink", NULL,
&metalink_url_string, error))
if (!ostree_repo_get_remote_option (self, name, "metalink", NULL,
&metalink_url_string, error))
goto out;
if (!repo_remote_fetch_summary (self,
@ -2196,19 +2330,32 @@ append_one_remote_config (OstreeRepo *self,
out:
return ret;
}
static GFile *
get_remotes_d_dir (OstreeRepo *self)
{
if (self->remotes_config_dir != NULL)
return g_file_resolve_relative_path (self->sysroot_dir, self->remotes_config_dir);
else if (ostree_repo_is_system (self))
return g_file_resolve_relative_path (self->sysroot_dir, SYSCONF_REMOTES);
return NULL;
}
static gboolean
append_remotes_d (OstreeRepo *self,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
g_autoptr(GFile) etc_ostree_remotes_d = NULL;
g_autoptr(GFile) remotes_d = NULL;
g_autoptr(GFileEnumerator) direnum = NULL;
etc_ostree_remotes_d = g_file_resolve_relative_path (self->sysroot_dir, SYSCONF_REMOTES);
remotes_d = get_remotes_d_dir (self);
if (remotes_d == NULL)
return TRUE;
if (!enumerate_directory_allow_noent (etc_ostree_remotes_d, OSTREE_GIO_FAST_QUERYINFO, 0,
if (!enumerate_directory_allow_noent (remotes_d, OSTREE_GIO_FAST_QUERYINFO, 0,
&direnum,
cancellable, error))
goto out;
@ -2255,6 +2402,7 @@ ostree_repo_open (OstreeRepo *self,
g_autofree char *version = NULL;
g_autofree char *mode = NULL;
g_autofree char *parent_repo_path = NULL;
g_autoptr(GError) temp_error = NULL;
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
@ -2382,15 +2530,40 @@ ostree_repo_open (OstreeRepo *self,
ostree_repo_set_disable_fsync (self, TRUE);
}
if (ostree_repo_is_system (self))
{
if (!append_remotes_d (self, cancellable, error))
goto out;
}
if (!append_remotes_d (self, cancellable, error))
goto out;
if (!glnx_opendirat (self->repo_dir_fd, "tmp", TRUE, &self->tmp_dir_fd, error))
goto out;
if (!glnx_shutil_mkdir_p_at (self->tmp_dir_fd, _OSTREE_CACHE_DIR, 0775, cancellable, &temp_error))
{
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED))
{
g_clear_error (&temp_error);
g_debug ("No permissions to create cache dir");
}
else
{
g_propagate_error (error, g_steal_pointer (&temp_error));
goto out;
}
}
if (!glnx_opendirat (self->tmp_dir_fd, _OSTREE_CACHE_DIR, TRUE, &self->cache_dir_fd, &temp_error))
{
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
g_clear_error (&temp_error);
g_debug ("No cache dir");
}
else
{
g_propagate_error (error, g_steal_pointer (&temp_error));
goto out;
}
}
if (self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 && self->enable_uncompressed_cache)
{
if (!gs_file_ensure_directory (self->uncompressed_objects_dir, TRUE, cancellable, error))
@ -2425,6 +2598,36 @@ ostree_repo_set_disable_fsync (OstreeRepo *self,
self->disable_fsync = disable_fsync;
}
/**
* ostree_repo_set_cache_dir:
* @self: An #OstreeRepo
* @dfd: directory fd
* @path: subpath in @dfd
*
* Set a custom location for the cache directory used for e.g.
* per-remote summary caches. Setting this manually is useful when
* doing operations on a system repo as a user because you don't have
* write permissions in the repo, where the cache is normally stored.
*/
gboolean
ostree_repo_set_cache_dir (OstreeRepo *self,
int dfd,
const char *path,
GCancellable *cancellable,
GError **error)
{
int fd;
if (!glnx_opendirat (dfd, path, TRUE, &fd, error))
return FALSE;
if (self->cache_dir_fd != -1)
close (self->cache_dir_fd);
self->cache_dir_fd = fd;
return TRUE;
}
/**
* ostree_repo_get_disable_fsync:
* @self: An #OstreeRepo
@ -3310,24 +3513,37 @@ import_one_object_copy (OstreeRepo *self,
OstreeRepo *source,
const char *checksum,
OstreeObjectType objtype,
gboolean trusted,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
guint64 length;
g_autoptr(GInputStream) object = NULL;
g_autoptr(GInputStream) object_stream = NULL;
if (!ostree_repo_load_object_stream (source, objtype, checksum,
&object, &length,
&object_stream, &length,
cancellable, error))
goto out;
if (objtype == OSTREE_OBJECT_TYPE_FILE)
{
if (!ostree_repo_write_content_trusted (self, checksum,
object, length,
cancellable, error))
goto out;
if (trusted)
{
if (!ostree_repo_write_content_trusted (self, checksum,
object_stream, length,
cancellable, error))
goto out;
}
else
{
g_autofree guchar *real_csum = NULL;
if (!ostree_repo_write_content (self, checksum,
object_stream, length,
&real_csum,
cancellable, error))
goto out;
}
}
else
{
@ -3336,10 +3552,29 @@ import_one_object_copy (OstreeRepo *self,
if (!copy_detached_metadata (self, source, checksum, cancellable, error))
goto out;
}
if (!ostree_repo_write_metadata_stream_trusted (self, objtype,
checksum, object, length,
cancellable, error))
goto out;
if (trusted)
{
if (!ostree_repo_write_metadata_stream_trusted (self, objtype,
checksum, object_stream, length,
cancellable, error))
goto out;
}
else
{
g_autofree guchar *real_csum = NULL;
g_autoptr(GVariant) variant = NULL;
if (!ostree_repo_load_variant (source, objtype, checksum,
&variant, error))
goto out;
if (!ostree_repo_write_metadata (self, objtype,
checksum, variant,
&real_csum,
cancellable, error))
goto out;
}
}
ret = TRUE;
@ -3419,11 +3654,43 @@ ostree_repo_import_object_from (OstreeRepo *self,
const char *checksum,
GCancellable *cancellable,
GError **error)
{
return
ostree_repo_import_object_from_with_trust (self, source, objtype,
checksum, TRUE, cancellable, error);
}
/**
* ostree_repo_import_object_from_with_trust:
* @self: Destination repo
* @source: Source repo
* @objtype: Object type
* @checksum: checksum
* @trusted: If %TRUE, assume the source repo is valid and trusted
* @cancellable: Cancellable
* @error: Error
*
* Copy object named by @objtype and @checksum into @self from the
* source repository @source. If both repositories are of the same
* type and on the same filesystem, this will simply be a fast Unix
* hard link operation.
*
* Otherwise, a copy will be performed.
*/
gboolean
ostree_repo_import_object_from_with_trust (OstreeRepo *self,
OstreeRepo *source,
OstreeObjectType objtype,
const char *checksum,
gboolean trusted,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
gboolean hardlink_was_supported = FALSE;
if (self->mode == source->mode)
if (trusted && /* Don't hardlink into untrusted remotes */
self->mode == source->mode)
{
if (!import_one_object_link (self, source, checksum, objtype,
&hardlink_was_supported,
@ -3438,10 +3705,10 @@ ostree_repo_import_object_from (OstreeRepo *self,
if (!ostree_repo_has_object (self, objtype, checksum, &has_object,
cancellable, error))
goto out;
if (!has_object)
{
if (!import_one_object_copy (self, source, checksum, objtype,
if (!import_one_object_copy (self, source, checksum, objtype, trusted,
cancellable, error))
goto out;
}
@ -3452,6 +3719,7 @@ ostree_repo_import_object_from (OstreeRepo *self,
return ret;
}
/**
* ostree_repo_query_object_storage_size:
* @self: Repo
@ -3818,11 +4086,17 @@ ostree_repo_pull_one_dir (OstreeRepo *self,
* Like ostree_repo_pull(), but supports an extensible set of flags.
* The following are currently defined:
*
* * subdir (s): Pull just this subdirectory
* * refs (as): Array of string refs
* * flags (i): An instance of #OstreeRepoPullFlags
* * refs: (as): Array of string refs
* * depth: (i): How far in the history to traverse; default is 0, -1 means infinite
* * override-commit-ids: (as): Array of specific commit IDs to fetch for refs
* * subdir (s): Pull just this subdirectory
* * override-remote-name (s): If local, add this remote to refspec
* * gpg-verify (b): GPG verify commits
* * gpg-verify-summary (b): GPG verify summary
* * depth (i): How far in the history to traverse; default is 0, -1 means infinite
* * disable-static-deltas (b): Do not use static deltas
* * require-static-deltas (b): Require static deltas
* * override-commit-ids (as): Array of specific commit IDs to fetch for refs
* * dry-run (b): Only print information on what will be downloaded (requires static deltas)
*/
gboolean
ostree_repo_pull_with_options (OstreeRepo *self,
@ -4296,6 +4570,35 @@ ostree_repo_add_gpg_signature_summary (OstreeRepo *self,
/* Special remote for _ostree_repo_gpg_verify_with_metadata() */
static const char *OSTREE_ALL_REMOTES = "__OSTREE_ALL_REMOTES__";
static GFile *
find_keyring (OstreeRepo *self,
OstreeRemote *remote,
GCancellable *cancellable)
{
g_autoptr(GFile) remotes_d = NULL;
g_autoptr(GFile) file = NULL;
file = g_file_get_child (self->repodir, remote->keyring);
if (g_file_query_exists (file, cancellable))
{
return g_steal_pointer (&file);
}
remotes_d = get_remotes_d_dir (self);
if (remotes_d)
{
g_autoptr(GFile) file2 = g_file_get_child (remotes_d, remote->keyring);
if (g_file_query_exists (file2, cancellable))
return g_steal_pointer (&file2);
}
if (self->parent_repo)
return find_keyring (self->parent_repo, remote, cancellable);
return NULL;
}
OstreeGpgVerifyResult *
_ostree_repo_gpg_verify_with_metadata (OstreeRepo *self,
GBytes *signed_data,
@ -4332,13 +4635,13 @@ _ostree_repo_gpg_verify_with_metadata (OstreeRepo *self,
OstreeRemote *remote;
g_autoptr(GFile) file = NULL;
remote = ost_repo_get_remote (self, remote_name, error);
remote = ost_repo_get_remote_inherited (self, remote_name, error);
if (remote == NULL)
goto out;
file = g_file_get_child (self->repodir, remote->keyring);
file = find_keyring (self, remote, cancellable);
if (g_file_query_exists (file, cancellable))
if (file != NULL)
{
_ostree_gpg_verifier_add_keyring (verifier, file);
add_global_keyring_dir = FALSE;

View File

@ -63,6 +63,13 @@ _OSTREE_PUBLIC
void ostree_repo_set_disable_fsync (OstreeRepo *self,
gboolean disable_fsync);
_OSTREE_PUBLIC
gboolean ostree_repo_set_cache_dir (OstreeRepo *self,
int dfd,
const char *path,
GCancellable *cancellable,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_repo_get_disable_fsync (OstreeRepo *self);
@ -147,6 +154,29 @@ gboolean ostree_repo_remote_get_gpg_verify_summary (OstreeRepo *self,
gboolean *out_gpg_verify_summary,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_repo_get_remote_option (OstreeRepo *self,
const char *remote_name,
const char *option_name,
const char *default_value,
char **out_value,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_repo_get_remote_list_option (OstreeRepo *self,
const char *remote_name,
const char *option_name,
char ***out_value,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_repo_get_remote_boolean_option (OstreeRepo *self,
const char *remote_name,
const char *option_name,
gboolean default_value,
gboolean *out_value,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_repo_remote_gpg_import (OstreeRepo *self,
const char *name,
@ -423,6 +453,14 @@ gboolean ostree_repo_import_object_from (OstreeRepo *self,
const char *checksum,
GCancellable *cancellable,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_repo_import_object_from_with_trust (OstreeRepo *self,
OstreeRepo *source,
OstreeObjectType objtype,
const char *checksum,
gboolean trusted,
GCancellable *cancellable,
GError **error);
_OSTREE_PUBLIC
gboolean ostree_repo_delete_object (OstreeRepo *self,
@ -891,11 +929,13 @@ gboolean ostree_repo_prune (OstreeRepo *self,
* @OSTREE_REPO_PULL_FLAGS_NONE: No special options for pull
* @OSTREE_REPO_PULL_FLAGS_MIRROR: Write out refs suitable for mirrors
* @OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY: Fetch only the commit metadata
* @OSTREE_REPO_PULL_FLAGS_UNTRUSTED: Don't trust local remote
*/
typedef enum {
OSTREE_REPO_PULL_FLAGS_NONE,
OSTREE_REPO_PULL_FLAGS_MIRROR = (1 << 0),
OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY = (1 << 1)
OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY = (1 << 1),
OSTREE_REPO_PULL_FLAGS_UNTRUSTED = (1 << 2)
} OstreeRepoPullFlags;
_OSTREE_PUBLIC

View File

@ -50,6 +50,7 @@ struct OstreeSePolicy {
GFile *selinux_policy_root;
struct selabel_handle *selinux_hnd;
char *selinux_policy_name;
char *selinux_policy_csum;
#endif
};
@ -77,6 +78,7 @@ ostree_sepolicy_finalize (GObject *object)
#ifdef HAVE_SELINUX
g_clear_object (&self->selinux_policy_root);
g_clear_pointer (&self->selinux_policy_name, g_free);
g_clear_pointer (&self->selinux_policy_csum, g_free);
if (self->selinux_hnd)
{
selabel_close (self->selinux_hnd);
@ -155,6 +157,93 @@ ostree_sepolicy_class_init (OstreeSePolicyClass *klass)
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}
#ifdef HAVE_SELINUX
/* Find the latest policy file in our root and return its checksum. */
static gboolean
get_policy_checksum (char **out_csum,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
const char *binary_policy_path = selinux_binary_policy_path ();
const char *binfile_prefix = glnx_basename (binary_policy_path);
g_autofree char *bindir_path = g_path_get_dirname (binary_policy_path);
glnx_fd_close int bindir_dfd = -1;
g_autofree char *best_policy = NULL;
int best_version = 0;
g_auto(GLnxDirFdIterator) dfd_iter = { 0,};
if (!glnx_opendirat (AT_FDCWD, bindir_path, TRUE, &bindir_dfd, error))
goto out;
if (!glnx_dirfd_iterator_init_at (bindir_dfd, ".", FALSE, &dfd_iter, error))
goto out;
while (TRUE)
{
struct dirent *dent = NULL;
if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent,
cancellable, error))
goto out;
if (dent == NULL)
break;
if (dent->d_type == DT_REG)
{
/* We could probably save a few hundred nanoseconds if we accept that
* the prefix will always be "policy" and hardcode that in a static
* compile-once GRegex... But picture how exciting it'd be if it *did*
* somehow change; there would be cheers & slow-mo high-fives at the
* sight of our code not breaking. Is that hope not worth a fraction
* of a millisecond? I believe it is... or maybe I'm just lazy. */
g_autofree char *regex = g_strdup_printf ("^\\Q%s\\E\\.[0-9]+$",
binfile_prefix);
/* we could use match groups to extract the version, but mehhh, we
* already have the prefix on hand */
if (g_regex_match_simple (regex, dent->d_name, 0, 0))
{
int version = /* do +1 for the period */
(int)g_ascii_strtoll (dent->d_name + strlen (binfile_prefix)+1,
NULL, 10);
g_assert (version > 0);
if (version > best_version)
{
best_version = version;
g_free (best_policy);
best_policy = g_strdup (dent->d_name);
}
}
}
}
if (!best_policy)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Could not find binary policy file");
goto out;
}
*out_csum = ot_checksum_file_at (bindir_dfd, best_policy, G_CHECKSUM_SHA256,
cancellable, error);
if (*out_csum == NULL)
goto out;
ret = TRUE;
out:
return ret;
}
#endif
static gboolean
initable_init (GInitable *initable,
GCancellable *cancellable,
@ -257,6 +346,12 @@ initable_init (GInitable *initable,
freecon (con);
}
if (!get_policy_checksum (&self->selinux_policy_csum, cancellable, error))
{
g_prefix_error (error, "While calculating SELinux checksum: ");
goto out;
}
self->selinux_policy_name = g_strdup (policytype);
self->selinux_policy_root = g_object_ref (etc_selinux_dir);
}
@ -306,6 +401,12 @@ ostree_sepolicy_get_path (OstreeSePolicy *self)
return self->path;
}
/**
* ostree_sepolicy_get_name:
* @self:
*
* Returns: (transfer none): Type of current policy
*/
const char *
ostree_sepolicy_get_name (OstreeSePolicy *self)
{
@ -316,6 +417,22 @@ ostree_sepolicy_get_name (OstreeSePolicy *self)
#endif
}
/**
* ostree_sepolicy_get_csum:
* @self:
*
* Returns: (transfer none): Checksum of current policy
*/
const char *
ostree_sepolicy_get_csum (OstreeSePolicy *self)
{
#ifdef HAVE_SELINUX
return self->selinux_policy_csum;
#else
return NULL;
#endif
}
/**
* ostree_sepolicy_get_label:
* @self: Self

View File

@ -44,6 +44,9 @@ GFile * ostree_sepolicy_get_path (OstreeSePolicy *self);
_OSTREE_PUBLIC
const char *ostree_sepolicy_get_name (OstreeSePolicy *self);
_OSTREE_PUBLIC
const char *ostree_sepolicy_get_csum (OstreeSePolicy *self);
_OSTREE_PUBLIC
gboolean ostree_sepolicy_get_label (OstreeSePolicy *self,
const char *relpath,

View File

@ -1850,4 +1850,3 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self,
out:
return ret;
}

View File

@ -140,17 +140,17 @@ ot_gio_checksum_stream (GInputStream *in,
}
char *
ot_checksum_file (GFile *file,
GChecksumType checksum_type,
GCancellable *cancellable,
GError **error)
ot_checksum_file_at (int dfd,
const char *path,
GChecksumType checksum_type,
GCancellable *cancellable,
GError **error)
{
GChecksum *checksum = NULL;
char *ret = NULL;
g_autoptr(GInputStream) in = NULL;
in = (GInputStream*)g_file_read (file, cancellable, error);
if (!in)
if (!ot_openat_read_stream (dfd, path, TRUE, &in, cancellable, error))
goto out;
checksum = g_checksum_new (checksum_type);

View File

@ -53,10 +53,11 @@ gboolean ot_gio_checksum_stream (GInputStream *in,
GCancellable *cancellable,
GError **error);
char * ot_checksum_file (GFile *file,
GChecksumType checksum_type,
GCancellable *cancellable,
GError **error);
char * ot_checksum_file_at (int dfd,
const char *path,
GChecksumType checksum_type,
GCancellable *cancellable,
GError **error);
void ot_gio_checksum_stream_async (GInputStream *in,
int io_priority,

View File

@ -319,7 +319,7 @@ ot_variant_bsearch_str (GVariant *array,
int *out_pos)
{
gsize imax, imin;
gsize imid;
gsize imid = -1;
gsize n;
n = g_variant_n_children (array);
@ -337,7 +337,7 @@ ot_variant_bsearch_str (GVariant *array,
imid = (imin + imax) / 2;
child = g_variant_get_child_value (array, imid);
g_variant_get_child (child, 0, "&s", &cur, NULL);
g_variant_get_child (child, 0, "&s", &cur, NULL);
cmp = strcmp (cur, str);
if (cmp < 0)

View File

@ -32,6 +32,8 @@
static char *opt_subject;
static char *opt_body;
static char *opt_parent;
static gboolean opt_orphan;
static char *opt_branch;
static char *opt_statoverride_file;
static char **opt_metadata_strings;
@ -67,9 +69,11 @@ parse_fsync_cb (const char *option_name,
}
static GOptionEntry options[] = {
{ "parent", 0, 0, G_OPTION_ARG_STRING, &opt_parent, "Parent ref, or \"none\"", "REF" },
{ "subject", 's', 0, G_OPTION_ARG_STRING, &opt_subject, "One line subject", "SUBJECT" },
{ "body", 'm', 0, G_OPTION_ARG_STRING, &opt_body, "Full description", "BODY" },
{ "branch", 'b', 0, G_OPTION_ARG_STRING, &opt_branch, "Branch", "BRANCH" },
{ "orphan", 0, 0, G_OPTION_ARG_NONE, &opt_orphan, "Create a commit without writing a ref", NULL },
{ "tree", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_trees, "Overlay the given argument as a tree", "dir=PATH or tar=TARFILE or ref=COMMIT" },
{ "add-metadata-string", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_metadata_strings, "Add a key/value pair to metadata", "KEY=VALUE" },
{ "add-detached-metadata-string", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_detached_metadata_strings, "Add a key/value pair to detached metadata", "KEY=VALUE" },
@ -190,9 +194,8 @@ commit_editor (OstreeRepo *repo,
input = g_strdup_printf ("\n"
"# Please enter the commit message for your changes. The first line will\n"
"# become the subject, and the remainder the body. Lines starting\n"
"# with '#' will be ignored, and an empty message aborts the commit.\n"
"#\n"
"# Branch: %s\n", branch);
"# with '#' will be ignored, and an empty message aborts the commit."
"%s%s\n", branch ? "\n#\n# Branch: " : "", branch ?: "");
output = ot_editor_prompt (repo, input, cancellable, error);
if (output == NULL)
@ -338,10 +341,10 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
goto out;
}
if (!opt_branch)
if (!(opt_branch || opt_orphan))
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"A branch must be specified with --branch");
"A branch must be specified with --branch, or use --orphan");
goto out;
}
@ -361,8 +364,22 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
modifier = ostree_repo_commit_modifier_new (flags, commit_filter, mode_adds, NULL);
}
if (!ostree_repo_resolve_rev (repo, opt_branch, TRUE, &parent, error))
goto out;
if (opt_parent)
{
if (g_str_equal (opt_parent, "none"))
parent = NULL;
else
{
if (!ostree_validate_checksum_string (opt_parent, error))
goto out;
parent = g_strdup (opt_parent);
}
}
else if (!opt_orphan)
{
if (!ostree_repo_resolve_rev (repo, opt_branch, TRUE, &parent, error))
goto out;
}
if (!opt_subject && !opt_body)
{
@ -547,7 +564,10 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
}
}
ostree_repo_transaction_set_ref (repo, NULL, opt_branch, commit_checksum);
if (opt_branch)
ostree_repo_transaction_set_ref (repo, NULL, opt_branch, commit_checksum);
else
g_assert (opt_orphan);
if (!ostree_repo_commit_transaction (repo, &stats, cancellable, error))
goto out;

View File

@ -32,11 +32,17 @@
static char *opt_remote;
static gboolean opt_disable_fsync;
static gboolean opt_untrusted;
static gboolean opt_gpg_verify;
static gboolean opt_gpg_verify_summary;
static int opt_depth = 0;
static GOptionEntry options[] = {
{ "remote", 0, 0, G_OPTION_ARG_STRING, &opt_remote, "Add REMOTE to refspec", "REMOTE" },
{ "disable-fsync", 0, 0, G_OPTION_ARG_NONE, &opt_disable_fsync, "Do not invoke fsync()", NULL },
{ "untrusted", 0, 0, G_OPTION_ARG_NONE, &opt_untrusted, "Do not trust source", NULL },
{ "gpg-verify", 0, 0, G_OPTION_ARG_NONE, &opt_gpg_verify, "GPG verify commits (must specify --remote)", NULL },
{ "gpg-verify-summary", 0, 0, G_OPTION_ARG_NONE, &opt_gpg_verify_summary, "GPG verify summary (must specify --remote)", NULL },
{ "depth", 0, 0, G_OPTION_ARG_INT, &opt_depth, "Traverse DEPTH parents (-1=infinite) (default: 0)", "DEPTH" },
{ NULL }
};
@ -54,6 +60,7 @@ ostree_builtin_pull_local (int argc, char **argv, GCancellable *cancellable, GEr
glnx_unref_object OstreeAsyncProgress *progress = NULL;
g_autoptr(GPtrArray) refs_to_fetch = NULL;
g_autoptr(GHashTable) source_objects = NULL;
OstreeRepoPullFlags pullflags = 0;
context = g_option_context_new ("SRC_REPO [REFS...] - Copy data from SRC_REPO");
@ -83,6 +90,9 @@ ostree_builtin_pull_local (int argc, char **argv, GCancellable *cancellable, GEr
src_repo_uri = g_strconcat ("file://", cwd, "/", src_repo_arg, NULL);
}
if (opt_untrusted)
pullflags |= OSTREE_REPO_PULL_FLAGS_UNTRUSTED;
if (opt_disable_fsync)
ostree_repo_set_disable_fsync (repo, TRUE);
@ -133,15 +143,21 @@ ostree_builtin_pull_local (int argc, char **argv, GCancellable *cancellable, GEr
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (&builder, "{s@v}", "flags",
g_variant_new_variant (g_variant_new_int32 (OSTREE_REPO_PULL_FLAGS_NONE)));
g_variant_new_variant (g_variant_new_int32 (pullflags)));
g_variant_builder_add (&builder, "{s@v}", "refs",
g_variant_new_variant (g_variant_new_strv ((const char *const*) refs_to_fetch->pdata, -1)));
if (opt_remote)
g_variant_builder_add (&builder, "{s@v}", "override-remote-name",
g_variant_new_variant (g_variant_new_string (opt_remote)));
if (opt_gpg_verify)
g_variant_builder_add (&builder, "{s@v}", "gpg-verify",
g_variant_new_variant (g_variant_new_boolean (TRUE)));
if (opt_gpg_verify_summary)
g_variant_builder_add (&builder, "{s@v}", "gpg-verify-summary",
g_variant_new_variant (g_variant_new_boolean (TRUE)));
g_variant_builder_add (&builder, "{s@v}", "depth",
g_variant_new_variant (g_variant_new_int32 (opt_depth)));
if (!ostree_repo_pull_with_options (repo, src_repo_uri,
g_variant_builder_end (&builder),
progress,

View File

@ -33,16 +33,20 @@ static gboolean opt_commit_only;
static gboolean opt_dry_run;
static gboolean opt_disable_static_deltas;
static gboolean opt_require_static_deltas;
static gboolean opt_untrusted;
static char* opt_subpath;
static char* opt_cache_dir;
static int opt_depth = 0;
static GOptionEntry options[] = {
{ "commit-metadata-only", 0, 0, G_OPTION_ARG_NONE, &opt_commit_only, "Fetch only the commit metadata", NULL },
{ "cache-dir", 0, 0, G_OPTION_ARG_STRING, &opt_cache_dir, "Use custom cache dir", NULL },
{ "disable-fsync", 0, 0, G_OPTION_ARG_NONE, &opt_disable_fsync, "Do not invoke fsync()", NULL },
{ "disable-static-deltas", 0, 0, G_OPTION_ARG_NONE, &opt_disable_static_deltas, "Do not use static deltas", NULL },
{ "require-static-deltas", 0, 0, G_OPTION_ARG_NONE, &opt_require_static_deltas, "Require static deltas", NULL },
{ "mirror", 0, 0, G_OPTION_ARG_NONE, &opt_mirror, "Write refs suitable for a mirror", NULL },
{ "subpath", 0, 0, G_OPTION_ARG_STRING, &opt_subpath, "Only pull the provided subpath", NULL },
{ "untrusted", 0, 0, G_OPTION_ARG_NONE, &opt_untrusted, "Do not trust (local) sources", NULL },
{ "dry-run", 0, 0, G_OPTION_ARG_NONE, &opt_dry_run, "Only print information on what will be downloaded (requires static deltas)", NULL },
{ "depth", 0, 0, G_OPTION_ARG_INT, &opt_depth, "Traverse DEPTH parents (-1=infinite) (default: 0)", "DEPTH" },
{ NULL }
@ -128,12 +132,21 @@ ostree_builtin_pull (int argc, char **argv, GCancellable *cancellable, GError **
if (opt_disable_fsync)
ostree_repo_set_disable_fsync (repo, TRUE);
if (opt_cache_dir)
{
if (!ostree_repo_set_cache_dir (repo, AT_FDCWD, opt_cache_dir, cancellable, error))
goto out;
}
if (opt_mirror)
pullflags |= OSTREE_REPO_PULL_FLAGS_MIRROR;
if (opt_commit_only)
pullflags |= OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY;
if (opt_untrusted)
pullflags |= OSTREE_REPO_PULL_FLAGS_UNTRUSTED;
if (opt_dry_run && !opt_require_static_deltas)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,

View File

@ -42,6 +42,7 @@ static gboolean opt_disable_bsdiff;
BUILTINPROTO(list);
BUILTINPROTO(show);
BUILTINPROTO(delete);
BUILTINPROTO(generate);
BUILTINPROTO(apply_offline);
@ -50,6 +51,7 @@ BUILTINPROTO(apply_offline);
static OstreeCommand static_delta_subcommands[] = {
{ "list", ot_static_delta_builtin_list },
{ "show", ot_static_delta_builtin_show },
{ "delete", ot_static_delta_builtin_delete },
{ "generate", ot_static_delta_builtin_generate },
{ "apply-offline", ot_static_delta_builtin_apply_offline },
{ NULL, NULL }
@ -168,6 +170,39 @@ ot_static_delta_builtin_show (int argc, char **argv, GCancellable *cancellable,
return ret;
}
static gboolean
ot_static_delta_builtin_delete (int argc, char **argv, GCancellable *cancellable, GError **error)
{
gboolean ret = FALSE;
GOptionContext *context;
glnx_unref_object OstreeRepo *repo = NULL;
const char *delta_id = NULL;
context = g_option_context_new ("DELETE - Remove a delta");
if (!ostree_option_context_parse (context, list_options, &argc, &argv, OSTREE_BUILTIN_FLAG_NONE, &repo, cancellable, error))
goto out;
if (argc < 3)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"DELTA must be specified");
goto out;
}
delta_id = argv[2];
if (!ostree_cmd__private__ ()->ostree_static_delta_delete (repo, delta_id, cancellable, error))
goto out;
ret = TRUE;
out:
if (context)
g_option_context_free (context);
return ret;
}
static gboolean
ot_static_delta_builtin_generate (int argc, char **argv, GCancellable *cancellable, GError **error)
{

View File

@ -132,7 +132,7 @@ ostree_run (int argc,
/* avoid gvfs (http://bugzilla.gnome.org/show_bug.cgi?id=526454) */
g_setenv ("GIO_USE_VFS", "local", TRUE);
g_log_set_handler (NULL, G_LOG_LEVEL_MESSAGE, message_handler, NULL);
g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, message_handler, NULL);
/*
* Parse the global options. We rearrange the options as
@ -255,7 +255,7 @@ ostree_option_context_parse (GOptionContext *context,
}
if (opt_verbose)
g_log_set_handler (NULL, G_LOG_LEVEL_DEBUG, message_handler, NULL);
g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, message_handler, NULL);
if (opt_repo == NULL && !(flags & OSTREE_BUILTIN_FLAG_NO_REPO))
{

View File

@ -25,7 +25,10 @@
#include "ot-main.h"
#include "ot-remote-builtins.h"
static char* opt_cache_dir;
static GOptionEntry option_entries[] = {
{ "cache-dir", 0, 0, G_OPTION_ARG_STRING, &opt_cache_dir, "Use custom cache dir", NULL },
};
gboolean
@ -49,6 +52,12 @@ ot_remote_builtin_refs (int argc, char **argv, GCancellable *cancellable, GError
goto out;
}
if (opt_cache_dir)
{
if (!ostree_repo_set_cache_dir (repo, AT_FDCWD, opt_cache_dir, cancellable, error))
goto out;
}
remote_name = argv[1];
if (!ostree_repo_remote_list_refs (repo, remote_name, &refs, cancellable, error))

View File

@ -28,7 +28,10 @@
static gboolean opt_raw;
static char* opt_cache_dir;
static GOptionEntry option_entries[] = {
{ "cache-dir", 0, 0, G_OPTION_ARG_STRING, &opt_cache_dir, "Use custom cache dir", NULL },
{ "raw", 0, 0, G_OPTION_ARG_NONE, &opt_raw, "Show raw variant data", NULL },
{ NULL }
};
@ -59,6 +62,12 @@ ot_remote_builtin_summary (int argc, char **argv, GCancellable *cancellable, GEr
remote_name = argv[1];
if (opt_cache_dir)
{
if (!ostree_repo_set_cache_dir (repo, AT_FDCWD, opt_cache_dir, cancellable, error))
goto out;
}
if (opt_raw)
flags |= OSTREE_DUMP_RAW;

View File

@ -66,4 +66,3 @@ path_is_on_readonly_fs (char *path)
return (stvfsbuf.f_flag & ST_RDONLY) != 0;
}

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
# Copyright (C) 2011,2014 Colin Walters <walters@verbum.org>
#
# This library is free software; you can redistribute it and/or
@ -21,10 +21,17 @@ set -euo pipefail
echo "1..16"
function validate_bootloader() {
(cd ${test_tmpdir};
if test -f sysroot/boot/syslinux/syslinux.cfg; then
$(dirname $0)/syslinux-entries-crosscheck.py sysroot
fi)
cd ${test_tmpdir};
bootloader=""
if test -f sysroot/boot/syslinux/syslinux.cfg; then
bootloader="syslinux"
elif test -f sysroot/boot/grub2/grub.cfg; then
bootloader="grub2"
fi
if test -n "${bootloader}"; then
$(dirname $0)/bootloader-entries-crosscheck.py sysroot ${bootloader}
fi
cd -
}
orig_mtime=$(stat -c '%.Y' sysroot/ostree/deploy)

View File

@ -19,7 +19,7 @@
set -euo pipefail
echo "1..50"
echo "1..53"
$OSTREE checkout test2 checkout-test2
echo "ok checkout"
@ -96,6 +96,33 @@ assert_file_has_content yet/another/tree/green 'leaf'
assert_file_has_content four '4'
echo "ok cwd contents"
cd ${test_tmpdir}
$OSTREE commit -b test2-no-parent -s '' $test_tmpdir/checkout-test2-4
assert_streq $($OSTREE log test2-no-parent |grep '^commit' | wc -l) "1"
$OSTREE commit -b test2-no-parent -s '' --parent=none $test_tmpdir/checkout-test2-4
assert_streq $($OSTREE log test2-no-parent |grep '^commit' | wc -l) "1"
echo "ok commit no parent"
cd ${test_tmpdir}
$OSTREE commit -b test2-custom-parent -s '' $test_tmpdir/checkout-test2-4
$OSTREE commit -b test2-custom-parent -s '' $test_tmpdir/checkout-test2-4
$OSTREE commit -b test2-custom-parent -s '' $test_tmpdir/checkout-test2-4
assert_streq $($OSTREE log test2-custom-parent |grep '^commit' | wc -l) "3"
prevparent=$($OSTREE rev-parse test2-custom-parent^)
$OSTREE commit -b test2-custom-parent -s '' --parent=${prevparent} $test_tmpdir/checkout-test2-4
assert_streq $($OSTREE log test2-custom-parent |grep '^commit' | wc -l) "3"
echo "ok commit custom parent"
cd ${test_tmpdir}
orphaned_rev=$($OSTREE commit --orphan -s "$(date)" $test_tmpdir/checkout-test2-4)
$OSTREE ls ${orphaned_rev} >/dev/null
$OSTREE prune --refs-only
if $OSTREE ls ${orphaned_rev} 2>err.txt; then
assert_not_reached "Found orphaned commit"
fi
assert_file_has_content err.txt "No such metadata object"
echo "ok commit orphaned"
cd ${test_tmpdir}
$OSTREE diff test2^ test2 > diff-test2
assert_file_has_content diff-test2 'D */a/5'

View File

@ -25,9 +25,14 @@ if len(sys.argv) == 1:
else:
sysroot = sys.argv[1]
bootloader = sys.argv[2]
loaderpath = sysroot + '/boot/loader/entries'
syslinuxpath = sysroot + '/boot/syslinux/syslinux.cfg'
if bootloader == "grub2":
sys.stdout.write('GRUB2 configuration validation not implemented.\n')
sys.exit(0)
def fatal(msg):
sys.stderr.write(msg)
sys.stderr.write('\n')

View File

@ -17,7 +17,17 @@
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
SRCDIR=$(dirname $0)
if [ -n "${G_TEST_SRCDIR:-}" ]; then
test_srcdir="${G_TEST_SRCDIR}/tests"
else
test_srcdir=$(dirname $0)
fi
if [ -n "${G_TEST_BUILDDIR:-}" ]; then
test_builddir="${G_TEST_BUILDDIR}/tests"
else
test_builddir=$(dirname $0)
fi
assert_not_reached () {
echo $@ 1>&2; exit 1
@ -31,8 +41,12 @@ test_tmpdir=$(pwd)
if ! test -f .testtmp; then
files=$(ls)
if test -n "${files}"; then
ls -l
assert_not_reached "test tmpdir=${test_tmpdir} is not empty; run this test via \`make check TESTS=\`, not directly"
fi
# Remember that this is an acceptable test $(pwd), for the benefit of
# C and JS tests which may source this file again
touch .testtmp
fi
export G_DEBUG=fatal-warnings
@ -54,7 +68,7 @@ export TEST_GPG_KEYID_3="DF444D67"
# homedir in order to create lockfiles. Work around
# this by copying locally.
echo "Copying gpghome to ${test_tmpdir}"
cp -a ${SRCDIR}/gpghome ${test_tmpdir}
cp -a "${test_srcdir}/gpghome" ${test_tmpdir}
export TEST_GPG_KEYHOME=${test_tmpdir}/gpghome
export OSTREE_GPG_HOME=${test_tmpdir}/gpghome/trusted
@ -63,9 +77,9 @@ if test -n "${OT_TESTS_DEBUG:-}"; then
fi
if test -n "${OT_TESTS_VALGRIND:-}"; then
CMD_PREFIX="env G_SLICE=always-malloc valgrind -q --leak-check=full --num-callers=30 --suppressions=${SRCDIR}/ostree-valgrind.supp"
CMD_PREFIX="env G_SLICE=always-malloc valgrind -q --leak-check=full --num-callers=30 --suppressions=${test_srcdir}/ostree-valgrind.supp"
else
CMD_PREFIX="env LD_PRELOAD=${SRCDIR}/libreaddir-rand.so"
CMD_PREFIX="env LD_PRELOAD=${test_builddir}/libreaddir-rand.so"
fi
assert_streq () {
@ -215,6 +229,20 @@ setup_os_boot_uboot() {
ln -s loader/uEnv.txt sysroot/boot/uEnv.txt
}
setup_os_boot_grub2() {
grub2_options=$1
mkdir -p sysroot/boot/grub2/
ln -s ../loader/grub.cfg sysroot/boot/grub2/grub.cfg
export OSTREE_BOOT_PARTITION="/boot"
case "$grub2_options" in
*ostree-grub-generator*)
cp ${test_srcdir}/ostree-grub-generator ${test_tmpdir}
chmod +x ${test_tmpdir}/ostree-grub-generator
export OSTREE_GRUB2_EXEC=${test_tmpdir}/ostree-grub-generator
;;
esac
}
setup_os_repository () {
mode=$1
bootmode=$2
@ -287,6 +315,9 @@ EOF
"uboot")
setup_os_boot_uboot
;;
*grub2*)
setup_os_boot_grub2 "${bootmode}"
;;
esac
cd ${test_tmpdir}
@ -324,3 +355,32 @@ os_repository_new_commit ()
${CMD_PREFIX} ostree --repo=${test_tmpdir}/testos-repo commit --add-metadata-string "version=${version}" -b testos/buildmaster/x86_64-runtime -s "Build"
cd ${test_tmpdir}
}
skip_without_user_xattrs () {
touch test-xattrs
if ! setfattr -n user.testvalue -v somevalue test-xattrs; then
echo "1..0 # SKIP this test requires xattr support"
exit 0
fi
}
skip_without_fuse () {
if ! fusermount --version >/dev/null 2>&1; then
echo "1..0 # SKIP no fusermount"
exit 0
fi
if ! [ -w /dev/fuse ]; then
echo "1..0 # SKIP no write access to /dev/fuse"
exit 0
fi
if ! [ -e /etc/mtab ]; then
echo "1..0 # SKIP no /etc/mtab"
exit 0
fi
}
libtest_cleanup_gpg () {
gpg-connect-agent --homedir ${test_tmpdir}/gpghome killagent /bye || true
}

1
tests/ostree-grub-generator Symbolic link
View File

@ -0,0 +1 @@
../src/boot/grub2/ostree-grub-generator

28
tests/test-abi.sh Executable file
View File

@ -0,0 +1,28 @@
#!/bin/bash
#
# Copyright (C) 2016 Colin Walters <walters@verbum.org>
#
# 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.
set -euo pipefail
echo '1..1'
grep ' ostree_[A-Za-z0-9_]*;' ${G_TEST_SRCDIR}/src/libostree/libostree.sym | sed -e 's,^ *\([A-Za-z0-9_]*\);,\1,' | sort -u > expected-symbols.txt
eu-readelf -a ${G_TEST_BUILDDIR}/.libs/libostree-1.so | grep 'FUNC.*GLOBAL.*DEFAULT.*@@LIBOSTREE_' | sed -e 's,^.* \(ostree_[A-Za-z0-9_]*\)@@LIBOSTREE_[0-9_.]*,\1,' |sort -u > found-symbols.txt
diff -u expected-symbols.txt found-symbols.txt
echo 'ok'

View File

@ -21,11 +21,7 @@ set -euo pipefail
. $(dirname $0)/libtest.sh
echo "1..1"
# Exports OSTREE_SYSROOT so --sysroot not needed.
setup_os_repository "archive-z2" "grub2"
echo "ok setup"
setup_os_repository "archive-z2" "grub2 ostree-grub-generator"
. $(dirname $0)/admin-test.sh

View File

@ -25,8 +25,8 @@ set -euo pipefail
setup_os_repository "archive-z2" "syslinux"
# If parallel is not installed, skip the test
if ! parallel --help >/dev/null 2>&1; then
echo "1..0 # SKIP no /usr/bin/parallel"
if ! parallel --gnu /bin/true </dev/null >/dev/null 2>&1; then
echo "1..0 # SKIP GNU parallel not available"
exit 0
fi
@ -42,7 +42,7 @@ echo "rev=${rev}"
${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os=testos testos:testos/buildmaster/x86_64-runtime
assert_has_dir sysroot/boot/ostree/testos-${bootcsum}
parallel_cmd=parallel
parallel_cmd="parallel --gnu"
if parallel --help | grep -q -e --no-notice; then
parallel_cmd="${parallel_cmd} --no-notice"
fi

View File

@ -25,7 +25,7 @@ echo '1..11'
setup_test_repository "archive-z2"
. ${SRCDIR}/archive-test.sh
. ${test_srcdir}/archive-test.sh
cd ${test_tmpdir}
mkdir repo2

View File

@ -19,10 +19,12 @@
set -euo pipefail
echo "1..1"
. $(dirname $0)/libtest.sh
skip_without_user_xattrs
echo "1..1"
setup_test_repository "bare-user"
echo "ok setup"

View File

@ -132,5 +132,6 @@ if ${CMD_PREFIX} ostree --repo=repo show main | grep -o 'Found [[:digit:]] signa
fi
rm -rf repo gnomerepo-files
libtest_cleanup_gpg
echo "ok"

View File

@ -21,10 +21,12 @@ set -euo pipefail
. $(dirname $0)/libtest.sh
skip_without_user_xattrs
bindatafiles="bash true ostree"
morebindatafiles="false ls"
echo '1..7'
echo '1..8'
mkdir repo
${CMD_PREFIX} ostree --repo=repo init --mode=archive-z2
@ -128,9 +130,9 @@ assert_streq "${totalsize_orig}" "${totalsize_swapped}"
echo 'ok generate + show endian swapped'
tar xf ${SRCDIR}/pre-endian-deltas-repo-big.tar.xz
tar xf ${test_srcdir}/pre-endian-deltas-repo-big.tar.xz
mv pre-endian-deltas-repo{,-big}
tar xf ${SRCDIR}/pre-endian-deltas-repo-little.tar.xz
tar xf ${test_srcdir}/pre-endian-deltas-repo-little.tar.xz
mv pre-endian-deltas-repo{,-little}
legacy_origrev=$(${CMD_PREFIX} ostree --repo=pre-endian-deltas-repo-big rev-parse main^)
legacy_newrev=$(${CMD_PREFIX} ostree --repo=pre-endian-deltas-repo-big rev-parse main)
@ -184,3 +186,18 @@ ${CMD_PREFIX} ostree --repo=repo2 fsck
${CMD_PREFIX} ostree --repo=repo2 ls ${newrev} >/dev/null
echo 'ok apply offline inline'
${CMD_PREFIX} ostree --repo=repo static-delta list | grep ^${origrev}-${newrev}$ || exit 1
${CMD_PREFIX} ostree --repo=repo static-delta list | grep ^${origrev}$ || exit 1
${CMD_PREFIX} ostree --repo=repo static-delta delete ${origrev} || exit 1
${CMD_PREFIX} ostree --repo=repo static-delta list | grep ^${origrev}-${newrev}$ || exit 1
${CMD_PREFIX} ostree --repo=repo static-delta list | grep ^${origrev}$ && exit 1
${CMD_PREFIX} ostree --repo=repo static-delta delete ${origrev}-${newrev} || exit 1
${CMD_PREFIX} ostree --repo=repo static-delta list | grep ^${origrev}-${newrev}$ && exit 1
${CMD_PREFIX} ostree --repo=repo static-delta list | grep ^${origrev}$ && exit 1
echo 'ok delete'

View File

@ -19,13 +19,11 @@
set -euo pipefail
if ! fusermount --version >/dev/null 2>&1; then
echo "1..0 # SKIP no fusermount"
exit 0
fi
. $(dirname $0)/libtest.sh
skip_without_fuse
skip_without_user_xattrs
echo "1..1"
# Run "triggers" like ldconfig, gtk-update-icon-cache, etc.
@ -44,14 +42,14 @@ exampleos_build_commit_package() {
mkdir -p ${pkg}-package/usr/bin/
echo "${pkg}-content ${version}" > ${pkg}-package/usr/bin/${pkg}
# Use a dummy subject for this.
ostree --repo=build-repo commit -b exampleos/x86_64/${pkg} -s '' --tree=dir=${pkg}-package
${CMD_PREFIX} ostree --repo=build-repo commit -b exampleos/x86_64/${pkg} -s '' --tree=dir=${pkg}-package
rm ${pkg}-package -rf
}
exampleos_recompose() {
rm exampleos-build -rf
for pkg in ${packages}; do
ostree --repo=build-repo checkout -U --union exampleos/x86_64/${pkg} exampleos-build
${CMD_PREFIX} ostree --repo=build-repo checkout -U --union exampleos/x86_64/${pkg} exampleos-build
done
# Now that we have our rootfs, run triggers
@ -62,15 +60,15 @@ exampleos_recompose() {
# Then we commit it, using --link-checkout-speedup to effectively
# only re-checksum the ldconfig file. We also have dummy commit
# message here.
ostree --repo=build-repo commit -b exampleos/x86_64/standard -s 'exampleos build' --link-checkout-speedup exampleos-build
${CMD_PREFIX} ostree --repo=build-repo commit -b exampleos/x86_64/standard -s 'exampleos build' --link-checkout-speedup exampleos-build
}
packages="bash systemd"
mkdir build-repo
ostree --repo=build-repo init --mode=bare-user
${CMD_PREFIX} ostree --repo=build-repo init --mode=bare-user
mkdir repo
ostree --repo=repo init --mode=archive-z2
${CMD_PREFIX} ostree --repo=repo init --mode=archive-z2
# Our FUSE mount point
mkdir mnt
@ -83,7 +81,7 @@ exampleos_build_commit_package systemd 224
exampleos_recompose
# This is our first commit - let's publish it.
ostree --repo=repo pull-local build-repo exampleos/x86_64/standard
${CMD_PREFIX} ostree --repo=repo pull-local build-repo exampleos/x86_64/standard
# Now, update the bash package - this is a new commit on the branch
# exampleos/x86_64/bash.
@ -93,11 +91,11 @@ exampleos_build_commit_package bash 0.5.0
exampleos_recompose
# Publish again:
ostree --repo=repo pull-local build-repo exampleos/x86_64/standard
${CMD_PREFIX} ostree --repo=repo pull-local build-repo exampleos/x86_64/standard
# Optional: Generate a static delta vs the previous build
ostree --repo=repo static-delta generate exampleos/x86_64/standard
${CMD_PREFIX} ostree --repo=repo static-delta generate exampleos/x86_64/standard
# Optional: Regenerate the summary file
ostree --repo=repo summary -u
${CMD_PREFIX} ostree --repo=repo summary -u
# Try: ostree --repo=demo-repo ls -R exampleos/x86_64/standard

View File

@ -78,4 +78,6 @@ if ${OSTREE} show test2 | grep -o 'Found [[:digit:]] signature'; then
assert_not_reached
fi
libtest_cleanup_gpg
echo "ok"

View File

@ -19,10 +19,15 @@
set -euo pipefail
echo "1..1"
# We don't want OSTREE_GPG_HOME used for these tests.
unset OSTREE_GPG_HOME
. $(dirname $0)/libtest.sh
skip_without_user_xattrs
echo "1..7"
setup_test_repository "archive-z2"
echo "ok setup"
@ -55,3 +60,38 @@ find checkout3 -printf '%P %s %#m %u/%g %y %l\n' | sort > checkout3.files
cmp checkout1.files checkout2.files
cmp checkout1.files checkout3.files
echo "ok checkouts same"
mkdir repo4
${CMD_PREFIX} ostree --repo=repo4 init --mode="archive-z2"
${CMD_PREFIX} ostree --repo=repo4 remote add --gpg-import ${test_tmpdir}/gpghome/key1.asc origin repo
if ${CMD_PREFIX} ostree --repo=repo4 pull-local --remote=origin --gpg-verify repo test2 2>&1; then
assert_not_reached "GPG verification unexpectedly succeeded"
fi
echo "ok --gpg-verify with no signature"
${OSTREE} gpg-sign --gpg-homedir=${TEST_GPG_KEYHOME} test2 ${TEST_GPG_KEYID_1}
mkdir repo5
${CMD_PREFIX} ostree --repo=repo5 init --mode="archive-z2"
${CMD_PREFIX} ostree --repo=repo5 remote add --gpg-import ${test_tmpdir}/gpghome/key1.asc origin repo
${CMD_PREFIX} ostree --repo=repo5 pull-local --remote=origin --gpg-verify repo test2
echo "ok --gpg-verify"
mkdir repo6
${CMD_PREFIX} ostree --repo=repo6 init --mode="archive-z2"
${CMD_PREFIX} ostree --repo=repo6 remote add --gpg-import ${test_tmpdir}/gpghome/key1.asc origin repo
if ${CMD_PREFIX} ostree --repo=repo6 pull-local --remote=origin --gpg-verify-summary repo test2 2>&1; then
assert_not_reached "GPG summary verification with no summary unexpectedly succeeded"
fi
${OSTREE} summary -u update
if ${CMD_PREFIX} ostree --repo=repo6 pull-local --remote=origin --gpg-verify-summary repo test2 2>&1; then
assert_not_reached "GPG summary verification with signed no summary unexpectedly succeeded"
fi
${OSTREE} summary -u update --gpg-sign=${TEST_GPG_KEYID_1} --gpg-homedir=${TEST_GPG_KEYHOME}
${CMD_PREFIX} ostree --repo=repo6 pull-local --remote=origin --gpg-verify-summary repo test2 2>&1
echo "ok --gpg-verify-summary"

50
tests/test-parent.sh Executable file
View File

@ -0,0 +1,50 @@
#!/bin/bash
#
# Copyright (C) 2016 Alexander Larsson <alexl@redhat.com>
#
# 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.
set -euo pipefail
. $(dirname $0)/libtest.sh
echo '1..2'
setup_test_repository "archive-z2"
export OSTREE_GPG_SIGN="${OSTREE} gpg-sign --gpg-homedir=${TEST_GPG_KEYHOME}"
cd ${test_tmpdir}
# Create a repo
${CMD_PREFIX} ostree --repo=repo2 init
${CMD_PREFIX} ostree --repo=repo2 remote add --gpg-import=${test_tmpdir}/gpghome/trusted/pubring.gpg --set=gpg-verify=true aremote file://$(pwd)/repo test2
# Create a repo with repo2 as parent
${CMD_PREFIX} ostree init --repo=repo3 --mode=bare-user
${CMD_PREFIX} ostree config --repo=repo3 set core.parent `pwd`/repo2
# Ensure the unsigned pull fails so we know we imported the gpg config correctly
if ${CMD_PREFIX} ostree --repo=repo3 pull aremote; then
assert_not_reached "GPG verification unexpectedly succeeded"
fi
echo "ok unsigned pull w/parent"
# Make a signed commit and ensure we can now pull
${OSTREE} commit -b test2 -s "A GPG signed commit" -m "Signed commit body" --gpg-sign=${TEST_GPG_KEYID_1} --gpg-homedir=${TEST_GPG_KEYHOME} --tree=dir=files
${CMD_PREFIX} ostree --repo=repo3 pull aremote
echo "ok signed pull w/parent"

View File

@ -21,6 +21,8 @@ set -euo pipefail
. $(dirname $0)/libtest.sh
skip_without_user_xattrs
setup_fake_remote_repo1 "archive-z2"
echo '1..2'
@ -128,9 +130,9 @@ assert_file_has_content deltascount "^1$"
echo "ok prune"
rm repo -rf
ostree --repo=repo init --mode=bare-user
${CMD_PREFIX} ostree --repo=repo init --mode=bare-user
${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo
${CMD_PREFIX} ostree --repo=repo pull --depth=-1 --commit-metadata-only origin test
ostree --repo=repo prune
${CMD_PREFIX} ostree --repo=repo prune
echo "ok prune with partial repo"

View File

@ -23,4 +23,4 @@ set -euo pipefail
setup_fake_remote_repo1 "archive-z2"
. ${SRCDIR}/pull-test.sh
. ${test_srcdir}/pull-test.sh

View File

@ -121,3 +121,5 @@ echo "ok pull mirror with invalid summary sig and no verification"
# assert_file_has_content deltas.txt "${origmain}-${newmain}"
# echo "ok pull mirror with signed summary covering static deltas"
libtest_cleanup_gpg

View File

@ -44,6 +44,10 @@ assert_file_has_content err.txt "Couldn't find file object"
rev=$(${CMD_PREFIX} ostree --repo=repo rev-parse origin:main)
assert_has_file repo/state/${rev}.commitpartial
# Test pulling a file, not a dir
${CMD_PREFIX} ostree --repo=repo pull --subpath=/firstfile origin main
${CMD_PREFIX} ostree --repo=repo ls origin:main /firstfile
${CMD_PREFIX} ostree --repo=repo pull origin main
assert_not_has_file repo/state/${rev}.commitpartial
${CMD_PREFIX} ostree --repo=repo fsck

View File

@ -21,7 +21,7 @@ set -euo pipefail
. $(dirname $0)/libtest.sh
echo "1..6"
echo "1..7"
COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}"
setup_fake_remote_repo1 "archive-z2" "${COMMIT_SIGN}"
@ -91,6 +91,21 @@ assert_has_file repo/tmp/cache/summaries/origin
assert_has_file repo/tmp/cache/summaries/origin.sig
echo "ok prune summary cache"
cd ${test_tmpdir}
repo_reinit
mkdir cachedir
${OSTREE} --repo=repo pull --cache-dir=cachedir origin main
assert_not_has_file repo/tmp/cache/summaries/origin
assert_not_has_file repo/tmp/cache/summaries/origin.sig
assert_has_file cachedir/summaries/origin
assert_has_file cachedir/summaries/origin.sig
rm cachedir/summaries/origin
${OSTREE} --repo=repo pull --cache-dir=cachedir origin main
assert_not_has_file repo/tmp/cache/summaries/origin
assert_has_file cachedir/summaries/origin
echo "ok pull with signed summary and cachedir"
cd ${test_tmpdir}
repo_reinit
@ -133,3 +148,5 @@ assert_file_has_content summary.txt "Good signature from \"Ostree Tester <test@t
grep static-deltas summary.txt > static-deltas.txt
assert_file_has_content static-deltas.txt \
$(${OSTREE} --repo=repo rev-parse origin:main)
libtest_cleanup_gpg

69
tests/test-pull-untrusted.sh Executable file
View File

@ -0,0 +1,69 @@
#!/bin/bash
#
# Copyright (C) 2014 Alexander Larsson <alexl@redhat.com>
#
# 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.
set -euo pipefail
. $(dirname $0)/libtest.sh
echo '1..3'
setup_test_repository "bare"
cd ${test_tmpdir}
mkdir repo2
${CMD_PREFIX} ostree --repo=repo2 init --mode="bare"
${CMD_PREFIX} ostree --repo=repo2 --untrusted pull-local repo
find repo2 -type f -links +1 | while read line; do
assert_not_reached "pull-local created hardlinks"
done
echo "ok pull-local --untrusted didn't hardlink"
# Corrupt repo
for i in ${test_tmpdir}/repo/objects/*/*.file; do
# make sure it's not a symlink
if [ -L $i ]; then
continue
fi
echo "corrupting $i"
echo "broke" >> $i
break;
done
rm -rf repo2
mkdir repo2
${CMD_PREFIX} ostree --repo=repo2 init --mode="bare"
if ${CMD_PREFIX} ostree --repo=repo2 pull-local repo; then
echo "ok trusted pull with corruption succeeded"
else
assert_not_reached "corrupted trusted pull unexpectedly succeeded!"
fi
rm -rf repo2
mkdir repo2
${CMD_PREFIX} ostree --repo=repo2 init --mode="bare"
if ${CMD_PREFIX} ostree --repo=repo2 pull-local --untrusted repo; then
assert_not_reached "corrupted untrusted pull unexpectedly failed!"
else
echo "ok untrusted pull with corruption failed"
fi

View File

@ -143,4 +143,5 @@ if ${OSTREE} pull R2:main >/dev/null 2>&1; then
fi
${OSTREE} pull R3:main >/dev/null
libtest_cleanup_gpg
echo "ok"

View File

@ -19,12 +19,11 @@
set -euo pipefail
if ! fusermount --version >/dev/null 2>&1; then
echo "1..0 # SKIP no fusermount"
exit 0
fi
. $(dirname $0)/libtest.sh
skip_without_fuse
skip_without_user_xattrs
setup_test_repository "bare-user"
echo "1..5"

View File

@ -19,15 +19,12 @@
set -euo pipefail
touch test-xattrs
if ! setfattr -n user.testvalue -v somevalue test-xattrs; then
exit 77
fi
. $(dirname $0)/libtest.sh
skip_without_user_xattrs
echo "1..2"
. $(dirname $0)/libtest.sh
setup_test_repository "archive-z2"
cd ${test_tmpdir}