summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel@debian.org>2024-11-10 05:42:41 +0100
committerDaniel Baumann <daniel@debian.org>2024-11-10 05:42:41 +0100
commit1c7231d4915b1e90dc43cade7c7bac62e6b7cf31 (patch)
treeb0ec7b23af36be6f652b67ad43ebe5f6df20af95
parentAdding upstream packaging 19.2.0-1. (diff)
downloadceph-19-1c7231d4915b1e90dc43cade7c7bac62e6b7cf31.tar.xz
ceph-19-1c7231d4915b1e90dc43cade7c7bac62e6b7cf31.zip
Adding ubuntu packaging 19.2.0-0ubuntu2.
Signed-off-by: Daniel Baumann <daniel@debian.org>
-rw-r--r--debian/.gitignore41
-rw-r--r--debian/.gitlab-ci.yml14
-rw-r--r--debian/README.Debian120
-rwxr-xr-xdebian/calc-max-parallel.sh27
l---------debian/ceph-base.ceph.init1
-rw-r--r--debian/ceph-base.dirs4
-rw-r--r--debian/ceph-base.docs1
-rw-r--r--debian/ceph-base.install17
-rw-r--r--debian/ceph-base.lintian-overrides6
-rw-r--r--debian/ceph-base.maintscript2
-rw-r--r--debian/ceph-base.postinst44
-rw-r--r--debian/ceph-base.postrm50
-rw-r--r--debian/ceph-base.preinst10
-rw-r--r--debian/ceph-base.prerm23
-rwxr-xr-xdebian/ceph-common.install24
-rw-r--r--debian/ceph-common.lintian-overrides2
-rw-r--r--debian/ceph-common.manpages1
-rw-r--r--debian/ceph-common.postinst83
-rw-r--r--debian/ceph-common.postrm24
-rw-r--r--debian/ceph-common.preinst29
l---------debian/ceph-common.rbdmap.init1
-rw-r--r--debian/ceph-exporter.install2
-rw-r--r--debian/ceph-fs-common.install4
-rw-r--r--debian/ceph-fuse.install1
-rw-r--r--debian/ceph-fuse.lintian-overrides2
-rw-r--r--debian/ceph-fuse.manpages1
-rw-r--r--debian/ceph-mds.lintian-overrides13
-rw-r--r--debian/ceph-mds.postinst32
-rw-r--r--debian/ceph-mds.prerm23
-rw-r--r--debian/ceph-mgr-cephadm.requires4
-rw-r--r--debian/ceph-mgr-dashboard.prerm8
-rw-r--r--debian/ceph-mgr-dashboard.requires11
-rw-r--r--debian/ceph-mgr-diskprediction-cloud.prerm8
-rw-r--r--debian/ceph-mgr-diskprediction-local.prerm8
-rw-r--r--debian/ceph-mgr-diskprediction-local.requires3
-rw-r--r--debian/ceph-mgr-k8sevents.install1
-rw-r--r--debian/ceph-mgr-k8sevents.postinst43
-rw-r--r--debian/ceph-mgr-k8sevents.requires2
-rw-r--r--debian/ceph-mgr-modules-core.requires8
-rw-r--r--debian/ceph-mgr-rook.prerm8
-rw-r--r--debian/ceph-mgr-rook.requires2
-rw-r--r--debian/ceph-mgr-ssh.install1
-rw-r--r--debian/ceph-mgr-ssh.postinst43
-rw-r--r--debian/ceph-mgr.prerm23
-rw-r--r--debian/ceph-mgr.requires6
-rw-r--r--debian/ceph-mon.postinst13
-rw-r--r--debian/ceph-mon.prerm23
-rw-r--r--[-rwxr-xr-x]debian/ceph-osd.install15
-rw-r--r--debian/ceph-osd.postinst8
-rw-r--r--debian/ceph-osd.prerm23
-rw-r--r--debian/ceph-test.install20
-rw-r--r--debian/ceph-volume.install4
-rw-r--r--debian/ceph.NEWS180
-rw-r--r--debian/ceph.lintian-overrides1
-rw-r--r--debian/ceph.postinst10
-rw-r--r--debian/ceph.postrm10
-rw-r--r--debian/ceph.preinst10
-rw-r--r--debian/cephadm.install1
-rw-r--r--debian/cephadm.postinst25
-rw-r--r--debian/cephfs-mirror.install2
-rw-r--r--debian/cephfs-shell.install2
-rw-r--r--debian/cephfs-top.install2
-rw-r--r--debian/changelog2715
-rw-r--r--debian/clean36
-rw-r--r--debian/compat1
-rw-r--r--debian/control1664
-rw-r--r--debian/copyright398
-rw-r--r--debian/crimson-osd.install1
-rw-r--r--debian/gbp.conf3
-rwxr-xr-xdebian/lib-systemd/system-sleep/ceph12
-rw-r--r--debian/lib-systemd/system/ceph-create-keys.service9
-rw-r--r--debian/lib-systemd/system/ceph-mds.service16
-rw-r--r--debian/lib-systemd/system/ceph-mon.service22
-rw-r--r--debian/lib-systemd/system/ceph-osd@.service22
-rw-r--r--debian/libcephfs-dev.install3
-rw-r--r--debian/libcephfs-jni.install2
-rw-r--r--debian/libcephfs-jni.lintian-overrides1
-rw-r--r--debian/libcephfs2.install2
-rw-r--r--debian/libcephfs2.lintian-overrides2
-rw-r--r--debian/libcephfs2.symbols206
-rw-r--r--debian/librados-dev.install3
-rw-r--r--debian/librados2.install5
-rw-r--r--debian/librados2.lintian-overrides2
-rw-r--r--debian/librados2.symbols404
-rw-r--r--debian/libradosstriper-dev.install2
-rw-r--r--debian/libradosstriper1.install2
-rw-r--r--debian/libradosstriper1.symbols38
-rw-r--r--debian/librbd-dev.install3
-rw-r--r--debian/librbd1.install5
-rw-r--r--debian/librbd1.symbols283
-rw-r--r--debian/librgw-dev.install2
-rw-r--r--debian/librgw2.install2
-rw-r--r--debian/libsqlite3-mod-ceph.install2
-rw-r--r--debian/libsqlite3-mod-ceph.symbols37
-rw-r--r--debian/man/ceph-crush-location.124
-rw-r--r--debian/man/mount.fuse.ceph.830
-rw-r--r--debian/missing-sources/bootstrap.js2377
-rw-r--r--debian/missing-sources/two.js10244
-rw-r--r--debian/patches/boost-url.patch63
-rw-r--r--debian/patches/bug1914584.patch44
-rw-r--r--debian/patches/ceph-exporter-systemd.patch60
-rw-r--r--debian/patches/dout-fix.patch23
-rw-r--r--debian/patches/enable-strsignal.patch16
-rw-r--r--debian/patches/fix-CheckCxxAtomic-riscv64.patch16
-rw-r--r--debian/patches/fix-bash-completion-location9
-rw-r--r--debian/patches/fix-cephadm-build.patch45
-rw-r--r--debian/patches/fix-fmt-check.patch15
-rw-r--r--debian/patches/fix-mantic-misc.patch35
-rw-r--r--debian/patches/logentry-c++23-compat.patch21
-rw-r--r--debian/patches/lp1986747-fix-osd-class-dir.patch21
-rw-r--r--debian/patches/lp2080208.patch46
-rw-r--r--debian/patches/mgr-distutils.patch32
-rw-r--r--debian/patches/pass-build-flags.patch25
-rw-r--r--debian/patches/ppc64el-fix-linking.patch24
-rw-r--r--debian/patches/riscv64-link-pthread.patch14
-rw-r--r--debian/patches/series22
-rw-r--r--debian/patches/spdk-fix-make-exe.patch22
-rw-r--r--debian/patches/spdk_top-string-format.patch39
-rw-r--r--debian/patches/update-java-source-target-flags.patch40
-rw-r--r--debian/py3dist-overrides4
-rw-r--r--[-rwxr-xr-x]debian/python3-ceph-argparse.install6
-rw-r--r--debian/python3-ceph-common.install2
-rw-r--r--debian/python3-ceph.lintian-overrides1
-rw-r--r--debian/radosgw.install6
-rw-r--r--debian/radosgw.lintian-overrides8
-rw-r--r--debian/radosgw.postinst7
-rw-r--r--debian/radosgw.postrm13
-rw-r--r--debian/radosgw.preinst13
-rw-r--r--debian/radosgw.prerm1
-rw-r--r--debian/rbd-nbd.install1
-rw-r--r--debian/rest-bench.install1
-rwxr-xr-xdebian/rules265
-rw-r--r--debian/source/format2
-rw-r--r--debian/source/lintian-overrides10
-rwxr-xr-xdebian/tests/build-rados31
-rwxr-xr-xdebian/tests/build-rbd24
-rwxr-xr-xdebian/tests/ceph-client11
-rw-r--r--debian/tests/control9
-rwxr-xr-xdebian/tests/python-ceph7
-rw-r--r--debian/udev/95-ceph-osd-lvm.rules13
-rw-r--r--debian/watch3
141 files changed, 18806 insertions, 1974 deletions
diff --git a/debian/.gitignore b/debian/.gitignore
deleted file mode 100644
index 32ca866d7..000000000
--- a/debian/.gitignore
+++ /dev/null
@@ -1,41 +0,0 @@
-/*.substvars
-/*.debhelper.log
-/ceph-common-dbg
-/ceph-common
-/ceph-fuse-dbg
-/ceph-fuse
-/ceph-fs-common-dbg
-/ceph-fs-common
-/ceph-mds-dbg
-/ceph-mds
-/ceph-mgr-dbg
-/ceph-mgr
-/ceph-mon-dbg
-/ceph-mon
-/ceph-osd-dbg
-/ceph-osd
-/ceph-resource-agents
-/ceph.init
-/radosgw.init
-/ceph.logrotate
-/*.debhelper
-/ceph
-/files
-/libcephfs2-dbg
-/libcephfs-dev
-/libcephfs2
-/librados2-dbg
-/librados-dev
-/librados2
-/librbd1-dbg
-/librbd-dev
-/librbd1
-/radosgw-dbg
-/radosgw
-/python-ceph
-/python-rados
-/python-rbd
-/python-cephfs
-/libcephfs-java
-/libcephfs-jni
-/tmp
diff --git a/debian/.gitlab-ci.yml b/debian/.gitlab-ci.yml
new file mode 100644
index 000000000..9815b7cd1
--- /dev/null
+++ b/debian/.gitlab-ci.yml
@@ -0,0 +1,14 @@
+include:
+ - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml
+ - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml
+
+variables:
+ RELEASE: 'unstable'
+ SALSA_CI_DISABLE_APTLY: 0
+ SALSA_CI_DISABLE_AUTOPKGTEST: 0
+ SALSA_CI_DISABLE_BLHC: 0
+ SALSA_CI_DISABLE_LINTIAN: 0
+ SALSA_CI_DISABLE_PIUPARTS: 0
+ SALSA_CI_DISABLE_REPROTEST: 1
+ SALSA_CI_DISABLE_BUILD_PACKAGE_ALL: 1
+ SALSA_CI_DISABLE_BUILD_PACKAGE_ANY: 1
diff --git a/debian/README.Debian b/debian/README.Debian
new file mode 100644
index 000000000..be21ad791
--- /dev/null
+++ b/debian/README.Debian
@@ -0,0 +1,120 @@
+## See online installation and setup documentation at
+
+ http://ceph.com/docs/master/install/manual-deployment/
+
+-------- -------- --------
+
+## "systemd" requires manual activation of services:
+
+ ## MON
+ # systemctl start ceph-mon
+ # systemctl enable ceph-mon
+
+ ## OSD.0 (set other OSDs like this)
+ # systemctl start ceph-osd@0
+ # systemctl enable ceph-osd@0
+
+ ## MDS
+ # systemctl start ceph-mds
+ # systemctl enable ceph-mds
+
+ ## "ceph" meta-service (starts/stops all the above like old init script)
+ # systemctl start ceph
+ # systemctl enable ceph
+
+ The ceph cluster can be set in the "/etc/default/ceph" file
+ by setting the CLUSTER environment variable.
+
+-------- -------- --------
+
+## Upgrade procedure (0.72.2 to 0.80):
+
+ * Read "Upgrade Sequencing" in release notes:
+
+ http://ceph.com/docs/firefly/release-notes/
+
+ * Upgrade packages.
+
+ * Restart MONs.
+
+ * Restart all OSDs.
+
+ * Run `ceph osd crush tunables default`.
+
+ * (Restart MDSes).
+
+ * Consider setting the 'hashpspool' flag on your pools (new default):
+
+ ceph osd pool set {pool} hashpspool true
+
+ This changes the pool to use a new hashing algorithm for the distribution of
+ Placement Groups (PGs) to OSDs. This new algorithm ensures a better distribution
+ to all OSDs. Be aware that this change will temporarly put some of your PGs into
+ "misplaced" state and cause additional I/O until all PGs are moved to their new
+ location. See http://tracker.ceph.com/issues/4128 for the details about the new
+ algorithm.
+
+ Read more about tunables in
+
+ http://ceph.com/docs/master/rados/operations/crush-map/#tunables
+
+ Upgrading all OSDs and setting correct tunables is necessary to avoid the errors like:
+
+ ## rbdmap errors:
+ libceph: mon2 192.168.0.222:6789 socket error on read
+
+ Wrong tunables may produce the following error:
+
+ libceph: mon0 192.168.0.222:6789 socket error on read
+ libceph: mon2 192.168.0.250:6789 feature set mismatch, my 4a042a42 < server's 2004a042a42, missing 20000000000
+
+ ## MDS errors:
+ one or more OSDs do not support TMAP2OMAP; upgrade OSDs before starting MDS (or downgrade MDS)
+
+ See also:
+
+ http://ceph.com/docs/firefly/install/upgrading-ceph/
+
+-------- -------- --------
+
+ Jerasure pool(s) will bump requirements to Linux_3.15 (not yet released) for
+ kernel CephFS and RBD clients.
+
+-------- -------- --------
+
+ RBD kernel driver do not support authentication so the following setting
+ in "/etc/ceph/ceph.conf" may be used to relax client auth. requirements:
+
+ cephx cluster require signatures = true
+ cephx service require signatures = false
+
+-------- -------- --------
+
+> How to mount CephFS using fuse client from "/etc/fstab"?
+
+ Add (and modify) the following sample to "/etc/fstab":
+
+ mount.fuse.ceph#conf=/etc/ceph/ceph.conf,id=admin /mnt/ceph fuse _netdev,noatime,allow_other 0 0
+
+ This is equivalent of running
+
+ ceph-fuse /mnt/ceph --id=admin -o noatime,allow_other
+
+ as root.
+
+-------- -------- --------
+
+ To avoid known issue with kernel FS client it is recommended to use
+ 'readdir_max_entries' mount option, for example:
+
+ mount -t ceph 1.2.3.4:/ /mnt/ceph -o readdir_max_entries=64
+
+-------- -------- --------
+
+ Beware of "mlocate" scanning of OSD file systems. To avoid problems add
+ "/var/lib/ceph" to PRUNEPATHS in the "/etc/updatedb.conf" like in the
+ following example:
+
+ PRUNEPATHS="/tmp /var/spool /media /mnt /var/lib/ceph"
+
+-------- -------- --------
diff --git a/debian/calc-max-parallel.sh b/debian/calc-max-parallel.sh
new file mode 100755
index 000000000..4fc6a3021
--- /dev/null
+++ b/debian/calc-max-parallel.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+# Simple tool to calculate max parallel jobs based on
+# memory of builder.
+#
+# MDCache.cc generally runs out of RAM in 4G of memory
+# with parallel=4
+
+total_ram=$(grep MemTotal /proc/meminfo | awk '{ print $2 }')
+
+sixteen_g=$((16*1024*1024))
+eight_g=$((8*1024*1024))
+four_g=$((4*1024*1024))
+
+if [ ${total_ram} -le ${four_g} ]; then
+ if dpkg-architecture -q DEB_BUILD_ARCH | grep -q -e arm -e mips -e powerpc -e ppc; then
+ echo "--max-parallel=1"
+ else
+ echo "--max-parallel=2"
+ fi
+elif [ ${total_ram} -le ${eight_g} ]; then
+ echo "--max-parallel=2"
+elif [ ${total_ram} -le ${sixteen_g} ]; then
+ echo "--max-parallel=3"
+else
+ echo "--max-parallel=4"
+fi
diff --git a/debian/ceph-base.ceph.init b/debian/ceph-base.ceph.init
new file mode 120000
index 000000000..b538109d2
--- /dev/null
+++ b/debian/ceph-base.ceph.init
@@ -0,0 +1 @@
+../src/init-ceph \ No newline at end of file
diff --git a/debian/ceph-base.dirs b/debian/ceph-base.dirs
index d0b8a9e10..cf605ad44 100644
--- a/debian/ceph-base.dirs
+++ b/debian/ceph-base.dirs
@@ -1,9 +1,9 @@
var/lib/ceph/bootstrap-mds
var/lib/ceph/bootstrap-mgr
var/lib/ceph/bootstrap-osd
-var/lib/ceph/bootstrap-rgw
var/lib/ceph/bootstrap-rbd
var/lib/ceph/bootstrap-rbd-mirror
-var/lib/ceph/tmp
+var/lib/ceph/bootstrap-rgw
var/lib/ceph/crash
var/lib/ceph/crash/posted
+var/lib/ceph/tmp
diff --git a/debian/ceph-base.docs b/debian/ceph-base.docs
new file mode 100644
index 000000000..b43bf86b5
--- /dev/null
+++ b/debian/ceph-base.docs
@@ -0,0 +1 @@
+README.md
diff --git a/debian/ceph-base.install b/debian/ceph-base.install
index a3d7757a5..704e7c55d 100644
--- a/debian/ceph-base.install
+++ b/debian/ceph-base.install
@@ -1,23 +1,20 @@
-etc/init.d/ceph
+## install from source tree
+etc/sudoers.d/ceph-smartctl
lib/systemd/system/ceph-crash.service
usr/bin/ceph-crash
-usr/bin/ceph-debugpack
+usr/bin/ceph-kvstore-tool
usr/bin/ceph-run
usr/bin/crushtool
usr/bin/monmaptool
usr/bin/osdmaptool
-usr/bin/ceph-kvstore-tool
-usr/libexec/ceph/ceph_common.sh
-usr/lib/ceph/erasure-code/*
-usr/lib/ceph/extblkdev/*
-usr/lib/rados-classes/*
+usr/lib/*/ceph/erasure-code/*
+usr/lib/*/rados-classes/*
+usr/lib/ceph/ceph_common.sh
usr/sbin/ceph-create-keys
usr/share/doc/ceph/sample.ceph.conf
usr/share/man/man8/ceph-create-keys.8
-usr/share/man/man8/ceph-debugpack.8
+usr/share/man/man8/ceph-kvstore-tool.8
usr/share/man/man8/ceph-run.8
usr/share/man/man8/crushtool.8
usr/share/man/man8/monmaptool.8
usr/share/man/man8/osdmaptool.8
-usr/share/man/man8/ceph-kvstore-tool.8
-etc/sudoers.d/ceph-smartctl
diff --git a/debian/ceph-base.lintian-overrides b/debian/ceph-base.lintian-overrides
deleted file mode 100644
index e436e4931..000000000
--- a/debian/ceph-base.lintian-overrides
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# the rados classes should NOT be stripped.
-#
-ceph: unstripped-binary-or-object ./usr/lib/rados-classes/libcls_rbd.so.1.0.0
-ceph: unstripped-binary-or-object ./usr/lib/rados-classes/libcls_rgw.so.1.0.0
-
diff --git a/debian/ceph-base.maintscript b/debian/ceph-base.maintscript
deleted file mode 100644
index 196dc0841..000000000
--- a/debian/ceph-base.maintscript
+++ /dev/null
@@ -1,2 +0,0 @@
-rm_conffile /etc/logrotate.d/ceph
-rm_conffile /etc/logrotate.d/ceph.logrotate
diff --git a/debian/ceph-base.postinst b/debian/ceph-base.postinst
index 75eeb59c6..23712a8b4 100644
--- a/debian/ceph-base.postinst
+++ b/debian/ceph-base.postinst
@@ -29,26 +29,28 @@ set -e
[ -z "$SERVER_GROUP" ] && SERVER_GROUP=ceph
case "$1" in
- configure)
- rm -f /etc/init/ceph.conf
- [ -x /sbin/start ] && start ceph-all || :
-
- # adjust file and directory permissions
- for DIR in /var/lib/ceph/* ; do
- if ! dpkg-statoverride --list $DIR >/dev/null
- then
- chown $SERVER_USER:$SERVER_GROUP $DIR
- fi
- done
- ;;
- abort-upgrade|abort-remove|abort-deconfigure)
- :
- ;;
-
- *)
- echo "postinst called with unknown argument \`$1'" >&2
- exit 1
- ;;
+ configure)
+ rm -f /etc/init/ceph.conf
+ for DIR in `ls -1 /var/lib/ceph` ; do
+ if ! dpkg-statoverride --list /var/lib/ceph/$DIR >/dev/null; then
+ if [ -d /run/systemd/system ] && [ $DIR = 'mon' ]; then
+ # NOTE: upgrade file permissions for mon filesystem on
+ # systemd based installs only due to automatic
+ # restarting of ceph-mon daemon
+ chown -R $SERVER_USER:$SERVER_GROUP /var/lib/ceph/$DIR
+ else
+ chown $SERVER_USER:$SERVER_GROUP /var/lib/ceph/$DIR
+ fi
+ fi
+ done
+ ;;
+ abort-upgrade|abort-remove|abort-deconfigure)
+ :
+ ;;
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
esac
# dh_installdeb will replace this with shell code automatically
@@ -57,5 +59,3 @@ esac
#DEBHELPER#
exit 0
-
-
diff --git a/debian/ceph-base.postrm b/debian/ceph-base.postrm
new file mode 100644
index 000000000..6c3768ea1
--- /dev/null
+++ b/debian/ceph-base.postrm
@@ -0,0 +1,50 @@
+#!/bin/sh
+# postrm script for ceph
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * <postrm> `remove'
+# * <postrm> `purge'
+# * <old-postrm> `upgrade' <new-version>
+# * <new-postrm> `failed-upgrade' <old-version>
+# * <new-postrm> `abort-install'
+# * <new-postrm> `abort-install' <old-version>
+# * <new-postrm> `abort-upgrade' <old-version>
+# * <disappearer's-postrm> `disappear' <overwriter>
+# <overwriter-version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ remove)
+ ;;
+
+ purge)
+ rm -rf /var/log/ceph
+ rm -rf /etc/ceph
+ ;;
+
+ upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
+ ;;
+
+ *)
+ echo "postrm called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+dpkg-maintscript-helper rm_conffile \
+ /etc/logrotate.d/ceph-base 10.2.3-0ubuntu5~ -- "$@"
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+
+
diff --git a/debian/ceph-base.preinst b/debian/ceph-base.preinst
new file mode 100644
index 000000000..08ab1c096
--- /dev/null
+++ b/debian/ceph-base.preinst
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+set -e
+
+dpkg-maintscript-helper rm_conffile \
+ /etc/logrotate.d/ceph-base 10.2.3-0ubuntu5~ -- "$@"
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/ceph-base.prerm b/debian/ceph-base.prerm
deleted file mode 100644
index bfd7d3d6f..000000000
--- a/debian/ceph-base.prerm
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-# vim: set noet ts=8:
-
-set -e
-
-case "$1" in
- remove)
- [ -x /sbin/stop ] && stop ceph-all || true
- invoke-rc.d ceph stop || {
- RESULT=$?
- if [ $RESULT != 100 ]; then
- exit $RESULT
- fi
- }
- ;;
-
- *)
- ;;
-esac
-
-#DEBHELPER#
-
-exit 0
diff --git a/debian/ceph-common.install b/debian/ceph-common.install
index fc4da0a17..d6df8dede 100755
--- a/debian/ceph-common.install
+++ b/debian/ceph-common.install
@@ -1,11 +1,11 @@
-#! /usr/bin/dh-exec --with=install
-
-etc/bash_completion.d/ceph
-etc/bash_completion.d/rados
-etc/bash_completion.d/radosgw-admin
-etc/bash_completion.d/rbd
+#!/usr/bin/dh-exec --with=install
+usr/share/bash-completion/completions/ceph
+usr/share/bash-completion/completions/rados
+usr/share/bash-completion/completions/radosgw-admin
+usr/share/bash-completion/completions/rbd
lib/systemd/system/ceph.target
lib/systemd/system/rbdmap.service
+etc/default/ceph
usr/bin/ceph
usr/bin/ceph-authtool
usr/bin/ceph-conf
@@ -18,18 +18,15 @@ usr/bin/cephfs-table-tool
usr/bin/crushdiff
usr/bin/rados
usr/bin/radosgw-admin
-usr/bin/rgw-gap-list
-usr/bin/rgw-gap-list-comparator
-usr/bin/rgw-orphan-list
-usr/bin/rgw-restore-bucket-index
usr/bin/rbd
usr/bin/rbdmap
usr/bin/rbd-replay*
usr/bin/ceph-post-file
usr/sbin/mount.ceph sbin
-usr/lib/ceph/compressor/*
-usr/lib/ceph/denc/*
-usr/lib/ceph/crypto/* [amd64]
+usr/lib/*/ceph/compressor/*
+usr/lib/*/ceph/crypto/* [amd64]
+usr/lib/*/ceph/denc/*
+usr/lib/*/ceph/extblkdev/*
usr/share/man/man8/ceph-authtool.8
usr/share/man/man8/ceph-conf.8
usr/share/man/man8/ceph-dencoder.8
@@ -41,7 +38,6 @@ usr/share/man/man8/crushdiff.8
usr/share/man/man8/mount.ceph.8
usr/share/man/man8/rados.8
usr/share/man/man8/radosgw-admin.8
-usr/share/man/man8/rgw-policy-check.8
usr/share/man/man8/rbd.8
usr/share/man/man8/rbdmap.8
usr/share/man/man8/rbd-replay*.8
diff --git a/debian/ceph-common.lintian-overrides b/debian/ceph-common.lintian-overrides
new file mode 100644
index 000000000..d4041ca8e
--- /dev/null
+++ b/debian/ceph-common.lintian-overrides
@@ -0,0 +1,2 @@
+# False-positives:
+spelling-error-in-binary * tEH the
diff --git a/debian/ceph-common.manpages b/debian/ceph-common.manpages
new file mode 100644
index 000000000..643fa2a41
--- /dev/null
+++ b/debian/ceph-common.manpages
@@ -0,0 +1 @@
+debian/man/ceph-crush-location.1
diff --git a/debian/ceph-common.postinst b/debian/ceph-common.postinst
index e058d096e..e0cbb582a 100644
--- a/debian/ceph-common.postinst
+++ b/debian/ceph-common.postinst
@@ -1,7 +1,6 @@
#!/bin/sh
-# -*- mode:sh; tab-width:8; indent-tabs-mode:nil -*-
# vim: set noet ts=8:
-# postinst script for ceph-mds
+# postinst script for ceph-common
#
# see: dh_installdeb(1)
@@ -35,73 +34,97 @@ set -e
# Groups that the user will be added to, if undefined, then none.
[ -z "$SERVER_ADDGROUP" ] && SERVER_ADDGROUP=
+# Custom dpkg-maintscript-helper type function to deal with
+# nested /etc/default/ceph/ceph
+finish_mv_ceph_defaults() {
+ rm -rf "/etc/default/ceph.dpkg-backup/ceph.dpkg-remove"
+
+ [ -e "/etc/default/ceph.dpkg-backup/ceph" ] || return 0
+
+ echo "Preserving user changes to /etc/default/ceph (renamed from /etc/default/ceph/ceph)..."
+ if [ -f "/etc/default/ceph" ]; then
+ mv -f "/etc/default/ceph" "/etc/default/ceph.dpkg-new"
+ fi
+ mv -f "/etc/default/ceph.dpkg-backup/ceph" "/etc/default/ceph"
+}
+
case "$1" in
configure)
# create user to avoid running server as root
# 1. create group if not existing
if ! getent group | grep -q "^$SERVER_GROUP:" ; then
- echo -n "Adding group $SERVER_GROUP.."
+ echo -n "Adding group $SERVER_GROUP.."
addgroup --quiet --system --gid $SERVER_GID \
- $SERVER_GROUP 2>/dev/null ||true
- echo "..done"
+ $SERVER_GROUP 2>/dev/null ||true
+ echo "..done"
fi
# 2. create user if not existing
if ! getent passwd | grep -q "^$SERVER_USER:"; then
- echo -n "Adding system user $SERVER_USER.."
+ echo -n "Adding system user $SERVER_USER.."
adduser --quiet \
--system \
--no-create-home \
--disabled-password \
- --home $SERVER_HOME \
- --uid $SERVER_UID \
- --gid $SERVER_GID \
+ --uid $SERVER_UID \
+ --gid $SERVER_GID \
$SERVER_USER 2>/dev/null || true
- echo "..done"
+ echo "..done"
fi
# 3. adjust passwd entry
- # NOTE: we should use "adduser --comment" if we don't need to
- # support adduser <3.136. "adduser --gecos" is deprecated,
- # and will be removed, so we don't use it. the first distro
- # using --comment is debian/trixie or ubuntu/mantic.
echo -n "Setting system user $SERVER_USER properties.."
- usermod --comment "$SERVER_NAME" \
- --gid $SERVER_GROUP \
+ usermod -c "$SERVER_NAME" \
+ -d $SERVER_HOME \
+ -g $SERVER_GROUP \
$SERVER_USER
+
# Unlock $SERVER_USER in case it is locked from an uninstall
if [ -f /etc/shadow ]; then
usermod -U -e '' $SERVER_USER
else
- usermod -U $SERVER_USER
+ usermod -U $SERVER_USER
fi
echo "..done"
- # 4. adjust file and directory permissions
- if ! dpkg-statoverride --list $SERVER_HOME >/dev/null; then
+ # 5. adjust file and directory permissions
+ if ! dpkg-statoverride --list $SERVER_HOME >/dev/null
+ then
chown $SERVER_USER:$SERVER_GROUP $SERVER_HOME
chmod u=rwx,g=rx,o= $SERVER_HOME
fi
- if ! dpkg-statoverride --list /var/log/ceph >/dev/null; then
- # take care not to touch cephadm log subdirs
- chown $SERVER_USER:$SERVER_GROUP /var/log/ceph
- chown $SERVER_USER:$SERVER_GROUP /var/log/ceph/*.log* || true
- # members of group ceph can log here, but cannot remove
- # others' files. non-members cannot read any logs.
+ if ! dpkg-statoverride --list /var/log/ceph >/dev/null
+ then
+ # take care not to touch cephadm log subdirs
+ chown $SERVER_USER:$SERVER_GROUP /var/log/ceph
+ chown $SERVER_USER:$SERVER_GROUP /var/log/ceph/*.log* || true
+ # members of group ceph can log here, but cannot remove
+ # others' files. non-members cannot read any logs.
chmod u=rwx,g=rwxs,o=t /var/log/ceph
fi
- # 5. fix /var/run/ceph
+ # 6. fix /var/run/ceph
if [ -d /var/run/ceph ]; then
- echo -n "Fixing /var/run/ceph ownership.."
- chown $SERVER_USER:$SERVER_GROUP /var/run/ceph
- echo "..done"
+ echo -n "Fixing /var/run/ceph ownership.."
+ chown $SERVER_USER:$SERVER_GROUP /var/run/ceph
+ echo "..done"
fi
# create /run/ceph. fail softly if systemd isn't present or
# something.
[ -x /bin/systemd-tmpfiles ] && systemd-tmpfiles --create || true
+
+ # Complete renames of /etc/default/ceph
+ if [ -n "$2" ] &&
+ dpkg --compare-versions -- "$2" le-nl 10.2.1-0ubuntu1; then
+ finish_mv_ceph_defaults
+ # Preserve dpkg-backup directory if it still contains
+ # any file
+ if ! ls -1qA "/etc/default/ceph.dpkg-backup" | grep -q . ; then
+ rm -rf "/etc/default/ceph.dpkg-backup"
+ fi
+ fi
;;
abort-upgrade|abort-remove|abort-deconfigure)
- :
+ :
;;
*)
diff --git a/debian/ceph-common.postrm b/debian/ceph-common.postrm
index e6a97543a..e4051180d 100644
--- a/debian/ceph-common.postrm
+++ b/debian/ceph-common.postrm
@@ -19,6 +19,16 @@ set -e
# the debian-policy package
+# Custom dpkg-maintscript-helper type function to deal with
+# nested /etc/default/ceph/ceph
+abort_mv_ceph_defaults() {
+ if [ -e "/etc/default/ceph.dpkg-backup/ceph.dpkg-remove" ]; then
+ echo "Reinstalling /etc/default/ceph/ceph that was moved away"
+ mv "/etc/default/ceph.dpkg-backup" "/etc/default/ceph"
+ mv "/etc/default/ceph/ceph.dpkg-remove" "/etc/default/ceph/ceph"
+ fi
+}
+
case "$1" in
remove)
;;
@@ -27,17 +37,25 @@ case "$1" in
[ -f "/etc/default/ceph" ] && . /etc/default/ceph
[ -z "$SERVER_USER" ] && SERVER_USER=ceph
- rm -rf /var/log/ceph
- rm -rf /etc/ceph
+ rm -rf /var/log/ceph
+ rm -rf /etc/ceph
if [ -f /etc/shadow ]; then
usermod -L -e 1 $SERVER_USER
else
usermod -L $SERVER_USER
fi
+
+ ;;
+
+ abort-install|abort-upgrade)
+ if [ -n "$2" ] &&
+ dpkg --compare-versions -- "$2" le-nl 10.2.1-0ubuntu1; then
+ abort_mv_ceph_defaults
+ fi
;;
- upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
+ upgrade|failed-upgrade|disappear)
;;
*)
diff --git a/debian/ceph-common.preinst b/debian/ceph-common.preinst
new file mode 100644
index 000000000..ef14f1eb1
--- /dev/null
+++ b/debian/ceph-common.preinst
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+set -e
+
+# Custom dpkg-maintscript-helper type function to deal with
+# nested /etc/default/ceph/ceph
+prepare_mv_ceph_defaults() {
+ local md5sum old_md5sum
+ md5sum="$(md5sum "/etc/default/ceph/ceph" | sed -e 's/ .*//')"
+ old_md5sum="$(dpkg-query -W -f='${Conffiles}' "ceph-common" | \
+ sed -n -e "\'^ /etc/default/ceph/ceph ' { s/ obsolete$//; s/.* //; p }")"
+ if [ "$md5sum" = "$old_md5sum" ]; then
+ mv -f "/etc/default/ceph/ceph" "/etc/default/ceph/ceph.dpkg-remove"
+ mv -f "/etc/default/ceph" "/etc/default/ceph.dpkg-backup"
+ fi
+}
+
+case "$1" in
+ upgrade|install)
+ if [ -d /etc/default/ceph ] && [ -n "$2" ] &&
+ dpkg --compare-versions -- "$2" le-nl 10.2.1-0ubuntu1; then
+ prepare_mv_ceph_defaults
+ fi
+ ;;
+esac
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/ceph-common.rbdmap.init b/debian/ceph-common.rbdmap.init
new file mode 120000
index 000000000..b2de0ce8b
--- /dev/null
+++ b/debian/ceph-common.rbdmap.init
@@ -0,0 +1 @@
+../src/init-rbdmap \ No newline at end of file
diff --git a/debian/ceph-exporter.install b/debian/ceph-exporter.install
new file mode 100644
index 000000000..1ac0edcd2
--- /dev/null
+++ b/debian/ceph-exporter.install
@@ -0,0 +1,2 @@
+lib/systemd/system/ceph-exporter*
+usr/bin/ceph-exporter
diff --git a/debian/ceph-fs-common.install b/debian/ceph-fs-common.install
new file mode 100644
index 000000000..a4f0bab50
--- /dev/null
+++ b/debian/ceph-fs-common.install
@@ -0,0 +1,4 @@
+usr/bin/cephfs
+usr/sbin/mount.ceph sbin
+usr/share/man/man8/cephfs.8
+usr/share/man/man8/mount.ceph.8
diff --git a/debian/ceph-fuse.install b/debian/ceph-fuse.install
index 565ef25dd..e132b7957 100644
--- a/debian/ceph-fuse.install
+++ b/debian/ceph-fuse.install
@@ -2,4 +2,3 @@ lib/systemd/system/ceph-fuse*
usr/bin/ceph-fuse
usr/sbin/mount.fuse.ceph sbin
usr/share/man/man8/ceph-fuse.8
-usr/share/man/man8/mount.fuse.ceph.8
diff --git a/debian/ceph-fuse.lintian-overrides b/debian/ceph-fuse.lintian-overrides
new file mode 100644
index 000000000..d4041ca8e
--- /dev/null
+++ b/debian/ceph-fuse.lintian-overrides
@@ -0,0 +1,2 @@
+# False-positives:
+spelling-error-in-binary * tEH the
diff --git a/debian/ceph-fuse.manpages b/debian/ceph-fuse.manpages
new file mode 100644
index 000000000..e4c9c231e
--- /dev/null
+++ b/debian/ceph-fuse.manpages
@@ -0,0 +1 @@
+debian/man/mount.fuse.ceph.8
diff --git a/debian/ceph-mds.lintian-overrides b/debian/ceph-mds.lintian-overrides
new file mode 100644
index 000000000..c88395441
--- /dev/null
+++ b/debian/ceph-mds.lintian-overrides
@@ -0,0 +1,13 @@
+# False-positives:
+spelling-error-in-binary * tEH the
+
+# Ceph upstart configuration don't have equivalent init scripts
+ceph-mds: init.d-script-not-marked-as-conffile etc/init.d/ceph-mds-all
+ceph-mds: init.d-script-not-included-in-package etc/init.d/ceph-mds-all
+ceph-mds: init.d-script-not-marked-as-conffile etc/init.d/ceph-mds
+ceph-mds: init.d-script-not-included-in-package etc/init.d/ceph-mds
+ceph-mds: init.d-script-not-marked-as-conffile etc/init.d/ceph-mds-all-starter
+ceph-mds: init.d-script-not-included-in-package etc/init.d/ceph-mds-all-starter
+ceph-mds: postrm-does-not-call-updaterc.d-for-init.d-script etc/init.d/ceph-mds-all
+ceph-mds: postrm-does-not-call-updaterc.d-for-init.d-script etc/init.d/ceph-mds
+ceph-mds: postrm-does-not-call-updaterc.d-for-init.d-script etc/init.d/ceph-mds-all-starter
diff --git a/debian/ceph-mds.postinst b/debian/ceph-mds.postinst
index b69efedaa..3ae908a99 100644
--- a/debian/ceph-mds.postinst
+++ b/debian/ceph-mds.postinst
@@ -23,22 +23,20 @@ set -e
[ -z "$SERVER_GROUP" ] && SERVER_GROUP=ceph
case "$1" in
- configure)
- [ -x /sbin/start ] && start ceph-mds-all || :
-
- if ! dpkg-statoverride --list /var/lib/ceph/mds >/dev/null
- then
- chown $SERVER_USER:$SERVER_GROUP /var/lib/ceph/mds
- fi
- ;;
- abort-upgrade|abort-remove|abort-deconfigure)
- :
- ;;
-
- *)
- echo "postinst called with unknown argument \`$1'" >&2
- exit 1
- ;;
+ configure)
+ if ! dpkg-statoverride --list /var/lib/ceph/mds >/dev/null;
+ then
+ chown $SERVER_USER:$SERVER_GROUP /var/lib/ceph/mds
+ fi
+ ;;
+ abort-upgrade|abort-remove|abort-deconfigure)
+ :
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
esac
# dh_installdeb will replace this with shell code automatically
@@ -47,5 +45,3 @@ esac
#DEBHELPER#
exit 0
-
-
diff --git a/debian/ceph-mds.prerm b/debian/ceph-mds.prerm
deleted file mode 100644
index 654518a7d..000000000
--- a/debian/ceph-mds.prerm
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-# vim: set noet ts=8:
-
-set -e
-
-case "$1" in
- remove)
- [ -x /sbin/stop ] && stop ceph-mds-all || :
- invoke-rc.d ceph stop mds || {
- RESULT=$?
- if [ $RESULT != 100 ]; then
- exit $RESULT
- fi
- }
- ;;
-
- *)
- ;;
-esac
-
-#DEBHELPER#
-
-exit 0
diff --git a/debian/ceph-mgr-cephadm.requires b/debian/ceph-mgr-cephadm.requires
deleted file mode 100644
index ec2e22b83..000000000
--- a/debian/ceph-mgr-cephadm.requires
+++ /dev/null
@@ -1,4 +0,0 @@
-CherryPy
-asyncssh
-cryptography
-Jinja2
diff --git a/debian/ceph-mgr-dashboard.prerm b/debian/ceph-mgr-dashboard.prerm
deleted file mode 100644
index e8e9959b1..000000000
--- a/debian/ceph-mgr-dashboard.prerm
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-# vim: set noet ts=8:
-
-set -e
-
-#DEBHELPER#
-
-exit 0
diff --git a/debian/ceph-mgr-dashboard.requires b/debian/ceph-mgr-dashboard.requires
deleted file mode 100644
index 8af793518..000000000
--- a/debian/ceph-mgr-dashboard.requires
+++ /dev/null
@@ -1,11 +0,0 @@
-bcrypt
-CherryPy
-more-itertools
-PyJWT
-pyopenssl
-requests
-Routes
-pkg-resources
-prettytable
-pyyaml
-ceph-common
diff --git a/debian/ceph-mgr-diskprediction-cloud.prerm b/debian/ceph-mgr-diskprediction-cloud.prerm
deleted file mode 100644
index e8e9959b1..000000000
--- a/debian/ceph-mgr-diskprediction-cloud.prerm
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-# vim: set noet ts=8:
-
-set -e
-
-#DEBHELPER#
-
-exit 0
diff --git a/debian/ceph-mgr-diskprediction-local.prerm b/debian/ceph-mgr-diskprediction-local.prerm
deleted file mode 100644
index e8e9959b1..000000000
--- a/debian/ceph-mgr-diskprediction-local.prerm
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-# vim: set noet ts=8:
-
-set -e
-
-#DEBHELPER#
-
-exit 0
diff --git a/debian/ceph-mgr-diskprediction-local.requires b/debian/ceph-mgr-diskprediction-local.requires
deleted file mode 100644
index cb5777a57..000000000
--- a/debian/ceph-mgr-diskprediction-local.requires
+++ /dev/null
@@ -1,3 +0,0 @@
-numpy
-scipy
-scikit-learn
diff --git a/debian/ceph-mgr-k8sevents.install b/debian/ceph-mgr-k8sevents.install
new file mode 100644
index 000000000..734da94ca
--- /dev/null
+++ b/debian/ceph-mgr-k8sevents.install
@@ -0,0 +1 @@
+usr/share/ceph/mgr/k8sevents
diff --git a/debian/ceph-mgr-k8sevents.postinst b/debian/ceph-mgr-k8sevents.postinst
new file mode 100644
index 000000000..4ab578fd1
--- /dev/null
+++ b/debian/ceph-mgr-k8sevents.postinst
@@ -0,0 +1,43 @@
+#!/bin/sh
+# vim: set noet ts=8:
+# postinst script for ceph-mgr-k8sevents
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+#
+# postinst configure <most-recently-configured-version>
+# old-postinst abort-upgrade <new-version>
+# conflictor's-postinst abort-remove in-favour <package> <new-version>
+# postinst abort-remove
+# deconfigured's-postinst abort-deconfigure in-favour <failed-install-package> <version> [<removing conflicting-package> <version>]
+#
+
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+case "$1" in
+ configure)
+ # attempt to load the plugin if the mgr is running
+ deb-systemd-invoke try-restart ceph-mgr.target
+ ;;
+ abort-upgrade|abort-remove|abort-deconfigure)
+ :
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+
+
diff --git a/debian/ceph-mgr-k8sevents.requires b/debian/ceph-mgr-k8sevents.requires
deleted file mode 100644
index ba8497137..000000000
--- a/debian/ceph-mgr-k8sevents.requires
+++ /dev/null
@@ -1,2 +0,0 @@
-pyyaml
-kubernetes
diff --git a/debian/ceph-mgr-modules-core.requires b/debian/ceph-mgr-modules-core.requires
deleted file mode 100644
index b5d37b3a9..000000000
--- a/debian/ceph-mgr-modules-core.requires
+++ /dev/null
@@ -1,8 +0,0 @@
-natsort
-CherryPy
-packaging
-pecan
-werkzeug
-requests
-pkg-resources
-python-dateutil
diff --git a/debian/ceph-mgr-rook.prerm b/debian/ceph-mgr-rook.prerm
deleted file mode 100644
index e8e9959b1..000000000
--- a/debian/ceph-mgr-rook.prerm
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-# vim: set noet ts=8:
-
-set -e
-
-#DEBHELPER#
-
-exit 0
diff --git a/debian/ceph-mgr-rook.requires b/debian/ceph-mgr-rook.requires
deleted file mode 100644
index 48ae25ba0..000000000
--- a/debian/ceph-mgr-rook.requires
+++ /dev/null
@@ -1,2 +0,0 @@
-kubernetes
-jsonpatch
diff --git a/debian/ceph-mgr-ssh.install b/debian/ceph-mgr-ssh.install
new file mode 100644
index 000000000..4023e4ead
--- /dev/null
+++ b/debian/ceph-mgr-ssh.install
@@ -0,0 +1 @@
+usr/share/ceph/mgr/ssh
diff --git a/debian/ceph-mgr-ssh.postinst b/debian/ceph-mgr-ssh.postinst
new file mode 100644
index 000000000..c0e3b13c5
--- /dev/null
+++ b/debian/ceph-mgr-ssh.postinst
@@ -0,0 +1,43 @@
+#!/bin/sh
+# vim: set noet ts=8:
+# postinst script for ceph-mgr-ssh
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+#
+# postinst configure <most-recently-configured-version>
+# old-postinst abort-upgrade <new-version>
+# conflictor's-postinst abort-remove in-favour <package> <new-version>
+# postinst abort-remove
+# deconfigured's-postinst abort-deconfigure in-favour <failed-install-package> <version> [<removing conflicting-package> <version>]
+#
+
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+case "$1" in
+ configure)
+ # attempt to load the plugin if the mgr is running
+ deb-systemd-invoke try-restart ceph-mgr.target
+ ;;
+ abort-upgrade|abort-remove|abort-deconfigure)
+ :
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+
+
diff --git a/debian/ceph-mgr.prerm b/debian/ceph-mgr.prerm
deleted file mode 100644
index 6fb7b245a..000000000
--- a/debian/ceph-mgr.prerm
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-# vim: set noet ts=8:
-
-set -e
-
-case "$1" in
- remove)
- [ -x /sbin/stop ] && stop ceph-mgr-all || :
- invoke-rc.d ceph stop mgr || {
- RESULT=$?
- if [ $RESULT != 100 ]; then
- exit $RESULT
- fi
- }
- ;;
-
- *)
- ;;
-esac
-
-#DEBHELPER#
-
-exit 0
diff --git a/debian/ceph-mgr.requires b/debian/ceph-mgr.requires
deleted file mode 100644
index 39336330c..000000000
--- a/debian/ceph-mgr.requires
+++ /dev/null
@@ -1,6 +0,0 @@
-bcrypt
-pyOpenSSL
-cephfs
-ceph-argparse
-pyyaml
-distutils
diff --git a/debian/ceph-mon.postinst b/debian/ceph-mon.postinst
index 688d8141d..56c3d04e4 100644
--- a/debian/ceph-mon.postinst
+++ b/debian/ceph-mon.postinst
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
# vim: set noet ts=8:
# postinst script for ceph-mon
#
@@ -24,7 +24,16 @@ set -e
case "$1" in
configure)
- [ -x /sbin/start ] && start ceph-mon-all || :
+ if ! dpkg-statoverride --list /var/lib/ceph/mon >/dev/null; then
+ if [ -d /run/systemd/system ]; then
+ # NOTE: upgrade file permissions for mon filesystem on
+ # systemd based installs only due to automatic
+ # restarting of ceph-mon daemon
+ chown -R $SERVER_USER:$SERVER_GROUP /var/lib/ceph/mon
+ else
+ chown $SERVER_USER:$SERVER_GROUP /var/lib/ceph/mon
+ fi
+ fi
;;
abort-upgrade|abort-remove|abort-deconfigure)
:
diff --git a/debian/ceph-mon.prerm b/debian/ceph-mon.prerm
deleted file mode 100644
index 5f64058a5..000000000
--- a/debian/ceph-mon.prerm
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-# vim: set noet ts=8:
-
-set -e
-
-case "$1" in
- remove)
- [ -x /sbin/stop ] && stop ceph-mon-all || true
- invoke-rc.d ceph stop mon || {
- RESULT=$?
- if [ $RESULT != 100 ]; then
- exit $RESULT
- fi
- }
- ;;
-
- *)
- ;;
-esac
-
-#DEBHELPER#
-
-exit 0
diff --git a/debian/ceph-osd.install b/debian/ceph-osd.install
index 2a8ac8863..c751c1c59 100755..100644
--- a/debian/ceph-osd.install
+++ b/debian/ceph-osd.install
@@ -1,18 +1,13 @@
-#! /usr/bin/dh-exec
-
+debian/udev/* lib/udev/rules.d
+etc/sysctl.d/30-ceph-osd.conf
lib/systemd/system/ceph-osd*
usr/bin/ceph-bluestore-tool
usr/bin/ceph-clsinfo
usr/bin/ceph-erasure-code-tool
usr/bin/ceph-objectstore-tool
+usr/bin/ceph-osd
usr/bin/ceph-osdomap-tool
-<pkg.ceph.crimson> usr/bin/crimson-store-nbd
-usr/bin/${CEPH_OSD_BASENAME} => /usr/bin/ceph-osd
-usr/bin/ceph_objectstore_bench
-usr/libexec/ceph/ceph-osd-prestart.sh
-usr/lib/libos_tp.so*
-usr/lib/libosd_tp.so*
+usr/lib/ceph/ceph-osd-prestart.sh
+usr/share/man/man8/ceph-bluestore-tool.8
usr/share/man/man8/ceph-clsinfo.8
usr/share/man/man8/ceph-osd.8
-usr/share/man/man8/ceph-bluestore-tool.8
-etc/sysctl.d/30-ceph-osd.conf
diff --git a/debian/ceph-osd.postinst b/debian/ceph-osd.postinst
index 04e33b860..291b7cb7d 100644
--- a/debian/ceph-osd.postinst
+++ b/debian/ceph-osd.postinst
@@ -24,8 +24,12 @@ set -e
case "$1" in
configure)
- [ -x /etc/init.d/procps ] && invoke-rc.d procps restart || :
- [ -x /sbin/start ] && start ceph-osd-all || :
+ if [ -x /lib/systemd/systemd-sysctl ] ; then
+ /lib/systemd/systemd-sysctl 30-ceph-osd.conf || true
+ fi
+ if ! dpkg-statoverride --list /var/lib/ceph/osd >/dev/null; then
+ chown $SERVER_USER:$SERVER_GROUP /var/lib/ceph/osd
+ fi
;;
abort-upgrade|abort-remove|abort-deconfigure)
:
diff --git a/debian/ceph-osd.prerm b/debian/ceph-osd.prerm
deleted file mode 100644
index 40f07b621..000000000
--- a/debian/ceph-osd.prerm
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-# vim: set noet ts=8:
-
-set -e
-
-case "$1" in
- remove)
- [ -x /sbin/stop ] && stop ceph-osd-all || true
- invoke-rc.d ceph stop osd || {
- RESULT=$?
- if [ $RESULT != 100 ]; then
- exit $RESULT
- fi
- }
- ;;
-
- *)
- ;;
-esac
-
-#DEBHELPER#
-
-exit 0
diff --git a/debian/ceph-test.install b/debian/ceph-test.install
deleted file mode 100644
index aeab6fac3..000000000
--- a/debian/ceph-test.install
+++ /dev/null
@@ -1,20 +0,0 @@
-usr/bin/ceph-client-debug
-usr/bin/ceph-coverage
-usr/bin/ceph_bench_log
-usr/bin/ceph_erasure_code_benchmark
-usr/bin/ceph_multi_stress_watch
-usr/bin/ceph_omapbench
-usr/bin/ceph_perf_local
-usr/bin/ceph_perf_msgr_client
-usr/bin/ceph_perf_msgr_server
-usr/bin/ceph_perf_objectstore
-usr/bin/ceph_psim
-usr/bin/ceph_radosacl
-usr/bin/ceph_rgw_jsonparser
-usr/bin/ceph_rgw_multiparser
-usr/bin/ceph_scratchtool
-usr/bin/ceph_scratchtoolpp
-usr/bin/ceph_test_*
-usr/bin/ceph-dedup-tool
-usr/lib/ceph/ceph-monstore-update-crush.sh
-usr/share/java/libcephfs-test.jar
diff --git a/debian/ceph-volume.install b/debian/ceph-volume.install
index b43f08ae8..79d93f612 100644
--- a/debian/ceph-volume.install
+++ b/debian/ceph-volume.install
@@ -1,7 +1,7 @@
lib/systemd/system/ceph-volume@.service
-usr/lib/python*/dist-packages/ceph_volume/*
usr/lib/python*/dist-packages/ceph_volume-*
+usr/lib/python*/dist-packages/ceph_volume/*
usr/sbin/ceph-volume
usr/sbin/ceph-volume-systemd
-usr/share/man/man8/ceph-volume.8
usr/share/man/man8/ceph-volume-systemd.8
+usr/share/man/man8/ceph-volume.8
diff --git a/debian/ceph.NEWS b/debian/ceph.NEWS
new file mode 100644
index 000000000..ee9db2f22
--- /dev/null
+++ b/debian/ceph.NEWS
@@ -0,0 +1,180 @@
+ceph (10.2.5-1) unstable; urgency=medium
+
+ ## Upgrades from Debian Jessie
+
+ Online upgrades from Ceph versions prior to Hammer (0.94.x) are not
+ supported by upstream. As Debian Jessie has Ceph Firefly (0.80.x) an
+ online upgrade from Jessie to Stretch is not possible. You have to first
+ shutdown all Ceph daemons on all nodes, upgrade everything to the new
+ version and start all daemons again.
+
+ Ceph daemons are not automatically restarted on upgrade to minimize
+ disruption. You have to manually restart them after the upgrade.
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Sun, 08 Jan 2017 14:57:35 +0100
+
+ceph (9.2.0-1) experimental; urgency=medium
+
+ ## systemd Enablement
+
+ For all distributions that support systemd (Debian Jessie 8.x,
+ Ubuntu >= 16.04), Ceph daemons are now managed using upstream provided
+ systemd files instead of the legacy sysvinit scripts or distro provided
+ systemd files. For example:
+
+ systemctl start ceph.target # start all daemons
+ systemctl status ceph-osd@12 # check status of osd.12
+
+ To upgrade existing deployments that use the older systemd service
+ configurations (Ubuntu >= 15.04, Debian >= Jessie), you need to switch
+ to using the new ceph-mon@ service:
+
+ systemctl stop ceph-mon
+ systemctl disable ceph-mon
+
+ systemctl start ceph-mon@`hostname`
+ systemctl enable ceph-mon@`hostname`
+
+ and also enable the ceph target post upgrade:
+
+ systemctl enable ceph.target
+
+ The main notable distro that is *not* using systemd is Ubuntu 14.04
+ (The next Ubuntu LTS, 16.04, will use systemd instead of upstart).
+
+ ## Ceph daemons no longer run as root
+
+ Ceph daemons now run as user and group 'ceph' by default. The
+ ceph user has a static UID assigned by Debian to ensure consistency
+ across servers within a Ceph deployment.
+
+ If your systems already have a ceph user, upgrading the package will cause
+ problems. We suggest you first remove or rename the existing 'ceph' user
+ and 'ceph' group before upgrading.
+
+ When upgrading, administrators have two options:
+
+ 1. Add the following line to 'ceph.conf' on all hosts:
+
+ setuser match path = /var/lib/ceph/$type/$cluster-$id
+
+ This will make the Ceph daemons run as root (i.e., not drop
+ privileges and switch to user ceph) if the daemon's data
+ directory is still owned by root. Newly deployed daemons will
+ be created with data owned by user ceph and will run with
+ reduced privileges, but upgraded daemons will continue to run as
+ root.
+
+ 2. Fix the data ownership during the upgrade. This is the
+ preferred option, but it is more work and can be very time
+ consuming. The process for each host is to:
+
+ 1. Upgrade the ceph package. This creates the ceph user and group. For
+ example:
+
+ apt-get install ceph
+
+ NOTE: the permissions on /var/lib/ceph/mon will be set to ceph:ceph
+ as part of the package upgrade process on existing *systemd*
+ based installations; the ceph-mon systemd service will be
+ automatically restarted as part of the upgrade. All other
+ filesystem permissions on systemd based installs will
+ remain unmodified by the upgrade.
+
+ 2. Stop the daemon(s):
+
+ systemctl stop ceph-osd@* # debian, ubuntu >= 15.04
+ stop ceph-all # ubuntu 14.04
+
+ 3. Fix the ownership:
+
+ chown -R ceph:ceph /var/lib/ceph
+
+ 4. Restart the daemon(s):
+
+ start ceph-all # ubuntu 14.04
+ systemctl start ceph.target # debian, ubuntu >= 15.04
+
+ Alternatively, the same process can be done with a single daemon
+ type, for example by stopping only monitors and chowning only
+ '/var/lib/ceph/osd'.
+
+ ## KeyValueStore OSD on-disk format changes
+
+ The on-disk format for the experimental KeyValueStore OSD backend has
+ changed. You will need to remove any OSDs using that backend before you
+ upgrade any test clusters that use it.
+
+ ## Deprecated commands
+
+ 'ceph scrub', 'ceph compact' and 'ceph sync force' are now DEPRECATED.
+ Users should instead use 'ceph mon scrub', 'ceph mon compact' and
+ 'ceph mon sync force'.
+
+ ## Full pool behaviour
+
+ When a pool quota is reached, librados operations now block indefinitely,
+ the same way they do when the cluster fills up. (Previously they would
+ return -ENOSPC). By default, a full cluster or pool will now block. If
+ your librados application can handle ENOSPC or EDQUOT errors gracefully,
+ you can get error returns instead by using the new librados
+ OPERATION_FULL_TRY flag.
+
+ -- James Page <james.page@ubuntu.com> Mon, 30 Nov 2015 09:23:09 +0000
+
+ceph (0.80.9-2) unstable; urgency=medium
+
+ ## CRUSH fixes in 0.80.9
+
+ The 0.80.9 point release fixes several issues with CRUSH that trigger excessive
+ data migration when adjusting OSD weights. These are most obvious when a very
+ small weight change (e.g., a change from 0 to .01) triggers a large amount of
+ movement, but the same set of bugs can also lead to excessive (though less
+ noticeable) movement in other cases.
+
+ However, because the bug may already have affected your cluster, fixing it
+ may trigger movement back to the more correct location. For this reason, you
+ must manually opt-in to the fixed behavior.
+
+ In order to set the new tunable to correct the behavior:
+
+ ceph osd crush set-tunable straw_calc_version 1
+
+ Note that this change will have no immediate effect. However, from this
+ point forward, any ‘straw’ bucket in your CRUSH map that is adjusted will get
+ non-buggy internal weights, and that transition may trigger some rebalancing.
+
+ You can estimate how much rebalancing will eventually be necessary on your
+ cluster with:
+
+ ceph osd getcrushmap -o /tmp/cm
+ crushtool -i /tmp/cm --num-rep 3 --test --show-mappings > /tmp/a 2>&1
+ crushtool -i /tmp/cm --set-straw-calc-version 1 -o /tmp/cm2
+ crushtool -i /tmp/cm2 --reweight -o /tmp/cm2
+ crushtool -i /tmp/cm2 --num-rep 3 --test --show-mappings > /tmp/b 2>&1
+ wc -l /tmp/a # num total mappings
+ diff -u /tmp/a /tmp/b | grep -c ^+ # num changed mappings
+
+ Divide the total number of lines in /tmp/a with the number of lines
+ changed. We've found that most clusters are under 10%.
+
+ You can force all of this rebalancing to happen at once with:
+
+ ceph osd crush reweight-all
+
+ Otherwise, it will happen at some unknown point in the future when
+ CRUSH weights are next adjusted.
+
+ ## Mapping rbd devices with rbdmap on systemd systems
+
+ If you have setup rbd mappings in /etc/ceph/rbdmap and corresponding mounts
+ in /etc/fstab things might break with systemd because systemd waits for the
+ rbd device to appear before the legacy rbdmap init file has a chance to run
+ and drops into emergency mode if it times out.
+
+ This can be fixed by adding the nofail option in /etc/fstab to all rbd
+ backed mount points. With this systemd does not wait for the device and
+ proceeds with the boot process. After rbdmap mapped the device, systemd
+ detects the new device and mounts the file system.
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Mon, 04 May 2015 22:49:48 +0200
diff --git a/debian/ceph.lintian-overrides b/debian/ceph.lintian-overrides
new file mode 100644
index 000000000..99b3db84b
--- /dev/null
+++ b/debian/ceph.lintian-overrides
@@ -0,0 +1 @@
+empty-binary-package
diff --git a/debian/ceph.postinst b/debian/ceph.postinst
new file mode 100644
index 000000000..290ca14ee
--- /dev/null
+++ b/debian/ceph.postinst
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+set -e
+
+dpkg-maintscript-helper rm_conffile \
+ /etc/logrotate.d/ceph 10.2.3-0ubuntu5~ -- "$@"
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/ceph.postrm b/debian/ceph.postrm
new file mode 100644
index 000000000..290ca14ee
--- /dev/null
+++ b/debian/ceph.postrm
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+set -e
+
+dpkg-maintscript-helper rm_conffile \
+ /etc/logrotate.d/ceph 10.2.3-0ubuntu5~ -- "$@"
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/ceph.preinst b/debian/ceph.preinst
new file mode 100644
index 000000000..290ca14ee
--- /dev/null
+++ b/debian/ceph.preinst
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+set -e
+
+dpkg-maintscript-helper rm_conffile \
+ /etc/logrotate.d/ceph 10.2.3-0ubuntu5~ -- "$@"
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/cephadm.install b/debian/cephadm.install
index f30ed9c5f..f9f66efab 100644
--- a/debian/cephadm.install
+++ b/debian/cephadm.install
@@ -1,2 +1,3 @@
+usr/lib/python3*/dist-packages/cephadmlib
usr/sbin/cephadm
usr/share/man/man8/cephadm.8
diff --git a/debian/cephadm.postinst b/debian/cephadm.postinst
index 50aa6f8dd..fdac2f068 100644
--- a/debian/cephadm.postinst
+++ b/debian/cephadm.postinst
@@ -25,12 +25,7 @@ case "$1" in
# 1. create user if not existing
if ! getent passwd | grep -q "^cephadm:"; then
echo -n "Adding system user cephadm.."
- adduser --quiet \
- --system \
- --disabled-password \
- --home /home/cephadm \
- --shell /bin/bash cephadm 2>/dev/null || true
- usermod --comment "cephadm user for mgr/cephadm" cephadm
+ adduser --quiet --system --disabled-password --home /var/lib/cephadm --gecos 'Ceph-dameon user for cephadm' --shell /bin/bash cephadm 2>/dev/null || true
echo "..done"
fi
@@ -42,20 +37,20 @@ case "$1" in
fi
# set up (initially empty) .ssh/authorized_keys file
- if ! test -d /home/cephadm/.ssh; then
- mkdir /home/cephadm/.ssh
- chown --reference /home/cephadm /home/cephadm/.ssh
- chmod 0700 /home/cephadm/.ssh
+ if ! test -d /var/lib/cephadm/.ssh; then
+ mkdir /var/lib/cephadm/.ssh
+ chown --reference /var/lib/cephadm /var/lib/cephadm/.ssh
+ chmod 0700 /var/lib/cephadm/.ssh
fi
- if ! test -e /home/cephadm/.ssh/authorized_keys; then
- touch /home/cephadm/.ssh/authorized_keys
- chown --reference /home/cephadm /home/cephadm/.ssh/authorized_keys
- chmod 0600 /home/cephadm/.ssh/authorized_keys
+ if ! test -e /var/lib/cephadm/.ssh/authorized_keys; then
+ touch /var/lib/cephadm/.ssh/authorized_keys
+ chown --reference /var/lib/cephadm /var/lib/cephadm/.ssh/authorized_keys
+ chmod 0600 /var/lib/cephadm/.ssh/authorized_keys
fi
;;
abort-upgrade|abort-remove|abort-deconfigure)
- :
+ :
;;
*)
diff --git a/debian/cephfs-mirror.install b/debian/cephfs-mirror.install
index ca0807e27..19d2e483d 100644
--- a/debian/cephfs-mirror.install
+++ b/debian/cephfs-mirror.install
@@ -1,3 +1 @@
-lib/systemd/system/cephfs-mirror*
usr/bin/cephfs-mirror
-usr/share/man/man8/cephfs-mirror.8
diff --git a/debian/cephfs-shell.install b/debian/cephfs-shell.install
index ee9e1399f..15c72387d 100644
--- a/debian/cephfs-shell.install
+++ b/debian/cephfs-shell.install
@@ -1,3 +1,3 @@
-usr/bin/cephfs-shell
+src/tools/cephfs/shell/cephfs-shell /usr/bin
usr/lib/python3*/dist-packages/cephfs_shell-*.egg-info
usr/share/man/man8/cephfs-shell.8
diff --git a/debian/cephfs-top.install b/debian/cephfs-top.install
deleted file mode 100644
index 930396b0c..000000000
--- a/debian/cephfs-top.install
+++ /dev/null
@@ -1,2 +0,0 @@
-usr/bin/cephfs-top
-usr/lib/python3*/dist-packages/cephfs_top-*.egg-info
diff --git a/debian/changelog b/debian/changelog
index 858ee176f..d16396884 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,780 +1,2710 @@
-ceph (19.2.0-1) stable; urgency=medium
+ceph (19.2.0-0ubuntu2) oracular; urgency=medium
- * New upstream release
+ * d/p/pass-build-flags.patch: Pass buildflags to Python extensions
+ (LP: #2078244).
- -- Ceph Release Team <ceph-maintainers@ceph.io> Wed, 18 Sep 2024 16:27:48 +0000
+ -- Graham Inggs <ginggs@ubuntu.com> Wed, 02 Oct 2024 15:16:31 +0000
-ceph (19.1.1-1) rc; urgency=medium
+ceph (19.2.0-0ubuntu1) oracular; urgency=medium
- * New upstream release
+ * New upstream stable release (LP: #2081781).
- -- Ceph Release Team <ceph-maintainers@ceph.io> Tue, 20 Aug 2024 12:51:10 -0400
+ -- Luciano Lo Giudice <luciano.logiudice@canonical.com> Sat, 28 Sep 2024 08:23:29 +0100
-ceph (19.1.0-1) rc; urgency=medium
+ceph (19.2.0~rc2-0ubuntu2) oracular; urgency=medium
- * New upstream release
+ * d/p/lp2080208.patch: Cherry pick proposed fix for compatibility with
+ newer versions of importlib-metadata (LP: #2080208).
- -- Ceph Release Team <ceph-maintainers@ceph.io> Wed, 03 Jul 2024 16:02:00 -0400
+ -- James Page <james.page@ubuntu.com> Thu, 12 Sep 2024 10:22:36 +0100
-ceph (15.2.0-1) stable; urgency=medium
+ceph (19.2.0~rc2-0ubuntu1) oracular; urgency=medium
- * New upstream release
+ * New upstream release candidate for Ceph Squid (LP: #2065515).
+ * d/p/qat-supported-archs.patch: Drop, equivalent upstream.
+ * d/p/snapmapper-c++23-compat.patch: Drop, included in release.
+ * d/p/*: Refresh.
+ * d/control: pkg-config -> pkgconf.
+ * d/control: Add missing misc:Depends to cephadm package.
+ * d/s/lintian-overrides: Update pattern match for license problem.
+ * d/copyright: Fix misc formatting issues.
+ * d/p/patch-out-exporter.patch: Remove, not used.
+ * d/control,compat: Use modern debhelper-compat.
- -- Ceph Release Team <ceph-maintainers@ceph.com> Mon, 23 Mar 2020 17:47:44 +0000
+ -- James Page <james.page@ubuntu.com> Tue, 03 Sep 2024 09:29:21 +0100
-ceph (15.1.1-1) stable; urgency=medium
+ceph (19.2.0~is.really.19.1.0-0ubuntu2) oracular; urgency=medium
- * New upstream release
+ * d/p/dout-fix.patch: Fix build issues with gcc-14.
- -- Ceph Release Team <ceph-maintainers@ceph.com> Fri, 13 Mar 2020 17:05:36 +0000
+ -- Luciano Lo Giudice <luciano.logiudice@canonical.com> Fri, 26 Jul 2024 13:55:13 +0000
-ceph (15.1.0-1) stable; urgency=medium
+ceph (19.2.0~is.really.19.1.0-0ubuntu1) oracular; urgency=medium
- * New upstream release
+ * New upstream release candidate (LP: #2065515):
+ - d/p/patch-out-exporter.patch: Drop, enable exporter.
+ - d/p/fix-qat-build.patch: Drop, equivalent upstream.
+ - d/p/*: Refresh.
+ - d/p/boost-url.patch,control: Fix compatibility with Boost >= 1.83.
+ - d/p/qat-supported-archs.patch: Only enable QAT on amd64
+ architecture.
+ - d/p/*: Drop patches no longer in-use.
+ - d/control,ceph-exporter.install: Enable ceph-exporter binary
+ package.
+ - d/p/ceph-exporter-systemd.patch: Cherry pick commit for ceph-
+ exporter systemd configuration.
+ - d/p/{snapmapper,logentry}-c++23-compat.patch: Cherry pick fixes for
+ C++23 compatibility.
- -- Ceph Release Team <ceph-maintainers@ceph.com> Wed, 29 Jan 2020 22:10:22 +0000
+ -- James Page <james.page@ubuntu.com> Wed, 24 Jul 2024 05:15:39 +0100
-ceph (14.2.0-1) stable; urgency=medium
+ceph (19.2.0~git20240301.4c76c50-0ubuntu7) oracular; urgency=medium
- * New upstream release
+ [ Luciano Lo Giudice]
+ * d/control: Add python3-{packaging,ceph-common} to (Build-)Depends
+ as these are undocumented/detected runtime dependencies in
+ ceph-volume (LP: #2064717).
- -- Ceph Release Team <ceph-maintainers@ceph.com> Mon, 18 Mar 2019 10:08:27 +0000
+ [ James Page ]
+ * d/cephadm.install: Install cephadmlib Python module which the
+ cephadm script uses (LP: #2063456).
+ * d/control: cephadm linux-any -> all.
+ * d/gbp.conf: Update for ubuntu/oracular packaging branch.
+ * d/control: Update Vcs-* to point to Launchpad for Ubuntu packaging.
+ * d/p/mgr-distutils.patch: Directly use vendored distutils from
+ setuptools for Python that runs in the mgr daemon (LP: #2065867).
-ceph (14.1.1-1) stable; urgency=medium
+ -- James Page <james.page@ubuntu.com> Thu, 23 May 2024 16:30:19 +0100
- * New upstream release
+ceph (19.2.0~git20240301.4c76c50-0ubuntu6) noble; urgency=medium
- -- Ceph Release Team <ceph-maintainers@ceph.com> Mon, 11 Mar 2019 16:42:54 +0000
+ * Drop dependency on python3-distutils again (it appears the change from
+ 19.2.0~git20240301.4c76c50-0ubuntu2 was accidentally dropped in 0ubuntu5).
-ceph (14.1.0-1) stable; urgency=medium
+ -- Michael Hudson-Doyle <michael.hudson@ubuntu.com> Fri, 19 Apr 2024 14:47:00 +1200
- * New upstream release
+ceph (19.2.0~git20240301.4c76c50-0ubuntu5) noble; urgency=medium
- -- Ceph Release Team <ceph-maintainers@ceph.com> Fri, 22 Feb 2019 18:07:06 +0000
+ * Drop support for anything other than 64 bit architectures (LP: #2061815):
+ - d/control: Add BD on architecture-is-64-bit.
+ - d/control: Remove direct references to 32 bit architectures and
+ use linux-any where appropriate.
+ - d/p/32bit-fixes.patch,debian-armel-armhf-buildflags.patch: Drop, no
+ longer needed.
-ceph (13.1.0-1) stable; urgency=medium
+ -- James Page <james.page@ubuntu.com> Wed, 17 Apr 2024 05:28:54 +0100
- * New upstream release
+ceph (19.2.0~git20240301.4c76c50-0ubuntu4) noble; urgency=medium
- -- Ceph Release Team <ceph-maintainers@ceph.com> Thu, 03 May 2018 17:57:32 +0000
+ * No-change rebuild for CVE-2024-3094
-ceph (12.1.2-1) stable; urgency=medium
+ -- Steve Langasek <steve.langasek@ubuntu.com> Sun, 31 Mar 2024 00:27:39 +0000
- * New upstream release
+ceph (19.2.0~git20240301.4c76c50-0ubuntu3) noble; urgency=medium
- -- Ceph Release Team <ceph-maintainers@ceph.com> Tue, 01 Aug 2017 17:55:37 +0000
+ * No-change rebuild against libcurl3t64-gnutls
-ceph (12.1.1-1) stable; urgency=medium
+ -- Steve Langasek <steve.langasek@ubuntu.com> Sat, 16 Mar 2024 06:44:30 +0000
- * New upstream release
+ceph (19.2.0~git20240301.4c76c50-0ubuntu2) noble; urgency=medium
- -- Ceph Release Team <ceph-maintainers@ceph.com> Mon, 17 Jul 2017 16:55:59 +0000
+ * Drop dependency on python3-distutils.
-ceph (12.1.0-1) stable; urgency=medium
+ -- Matthias Klose <doko@ubuntu.com> Sat, 09 Mar 2024 11:41:46 +0100
- * New upstream release
+ceph (19.2.0~git20240301.4c76c50-0ubuntu1) noble; urgency=medium
- -- Ceph Release Team <ceph-maintainers@ceph.com> Thu, 22 Jun 2017 15:43:47 +0000
+ * d/rules: Add helper for generating snapshots.
+ * New upstream snapshot for Ceph Squid.
+ * d/rules: Re-enable SPDK support.
+ * d/control: Bump versioned boost depends to >= 1.82.0.
+ * d/p/py310-py-ssize-t-compat.patch: Drop, no longer used.
+ * d/p/disable-crypto.patch: Drop, no longer required.
-ceph (12.0.3-1) stable; urgency=medium
+ -- James Page <james.page@ubuntu.com> Mon, 04 Mar 2024 11:03:31 +0000
- * New upstream release
+ceph (19.2.0~git20240228.cb81931-0ubuntu1) noble; urgency=medium
- -- Ceph Release Team <ceph-maintainers@ceph.com> Tue, 16 May 2017 12:42:53 +0000
+ [ Luciano Lo Giudice ]
+ * New snapshot in preparation for Ceph Squid release.
+ * d/p/enable-python311.patch: Removed, no longer needed.
+ * d/p/cmake-allow-empty-submodules.patch: Removed, no longer needed.
+ * d/p/CVE-2023-43040.patch: Removed, included in snapshot.
+ * d/p/32bit-fixes.patch: Refresh.
+ * d/p/patch-out-exporter.patch: Refresh.
+ * d/p/fix-mantic-misc.patch: Refresh.
+ * d/p/bug1914584.patch: Refresh.
+ * d/p/fix-fmt-check.patch: Fix CMake check for libfmt.
+ * d/p/fix-cephadm-build.patch: Fix build and install for cephadm.
+ * d/p/fix-qat-build.patch: Only build QAT libs on AMD64.
+ * d/rules: Temporarily disable SPDK support.
-ceph (12.0.2-1) stable; urgency=medium
+ [ James Page ]
+ * d/p/*: Refresh.
+ * d/p/ppc64el-fix-linking.patch: Tweak linking to resolve build
+ failure on ppc64el.
- * New upstream release
+ -- Luciano Lo Giudice <luciano.logiudice@canonical.com> Thu, 29 Feb 2024 20:09:32 +0000
- -- Ceph Release Team <ceph-maintainers@ceph.com> Thu, 20 Apr 2017 19:59:57 +0000
+ceph (18.2.0-0ubuntu7) noble; urgency=medium
-ceph (12.0.1-1) stable; urgency=medium
+ * d/rules, d/patches: Use java_compat_level to set --release (LP: #2054332)
- * New upstream release
+ -- Pushkar Kulkarni <pushkar.kulkarni@canonical.com> Mon, 19 Feb 2024 22:28:18 +0530
- -- Ceph Release Team <ceph-maintainers@ceph.com> Fri, 24 Mar 2017 15:47:57 +0000
+ceph (18.2.0-0ubuntu6) noble; urgency=medium
-ceph (12.0.0-1) stable; urgency=medium
+ * SECURITY UPDATE: Improper bucket validation in POST requests
+ - debian/patches/CVE-2023-43040.patch: rgw: Fix bucket validation
+ against POST policies
+ - CVE-2023-43040
- * New upstream release
+ -- Nick Galanis <nick.galanis@canonical.com> Wed, 24 Jan 2024 17:57:40 +0000
- -- Ceph Release Team <ceph-maintainers@ceph.com> Wed, 08 Feb 2017 13:57:30 +0000
+ceph (18.2.0-0ubuntu5) noble; urgency=medium
-ceph (11.1.0-1) stable; urgency=medium
+ * d/control: depend on resource-agents-common. The transitional
+ resource-agents package has been removed.
+ * d/p/cmake-allow-empty-submodules.patch: use quotes to allow empty
+ submodules variable during the cmake build configuration. This is
+ a FTBFS fix for noble.
+ * d/control: switch to cython3-legacy. Thanks to Bas Couwenberg.
+ (Closes: #1056793)
+ * d/p/fix-boost-reef.patch: drop boost 1.74 changes.
+ * d/p/fix-boost-1.82-build.patch: fix build for boost >= 1.82.
- * New upstream release
+ -- Athos Ribeiro <athos.ribeiro@canonical.com> Fri, 19 Jan 2024 16:36:49 -0300
- -- Alfredo Deza <adeza@redhat.com> Mon, 12 Dec 2016 18:27:51 +0000
+ceph (18.2.0-0ubuntu4) noble; urgency=medium
-ceph (11.0.2-1) stable; urgency=medium
+ * No-change rebuild for ICU soname change.
- * New upstream release
+ -- Matthias Klose <doko@ubuntu.com> Tue, 19 Dec 2023 11:59:43 +0100
- -- Alfredo Deza <adeza@redhat.com> Mon, 17 Oct 2016 11:16:49 +0000
+ceph (18.2.0-0ubuntu3) mantic; urgency=medium
-ceph (11.0.1-1) stable; urgency=medium
+ * d/control: Upgrade lua build dependency to 5.4
- * New upstream release
+ -- Lena Voytek <lena.voytek@canonical.com> Tue, 26 Sep 2023 11:00:39 -0700
- -- Alfredo Deza <adeza@redhat.com> Tue, 11 Oct 2016 16:27:56 +0000
+ceph (18.2.0-0ubuntu2) mantic; urgency=medium
-ceph (11.0.0-1) stable; urgency=low
+ * d/control,rules: Disable Jaeger support to avoid dependency on Thrift
+ which is not in Ubuntu main.
+ * d/cephadm.postinst: Switch back to default location for system user
+ cephadm and update all references to /home -> /var/lib.
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Tue, 26 Sep 2023 16:25:14 +0100
- -- Sage Weil <sage@newdream.net> Tue, 28 Jun 2016 11:41:16 -0400
+ceph (18.2.0-0ubuntu1) mantic; urgency=medium
-ceph (10.2.0-1) stable; urgency=medium
+ * New upstream release (LP: #2033428).
+ * d/p/32bit-fixes.patch: Refresh.
+ * d/p/bug1914584.patch: Refresh.
+ * d/p/patch-out-exporter.patch: Refresh.
+ * d/p/compress-common-depends.patch: Removed, no longer needed.
+ * d/p/fix-boost-reef.patch: Fixes to build with Boost on Reef.
+ * d/p/fix-mantic-misc.patch: Fix build on Mantic.
+ * d/p/fix-kinetic-*: Removed, no longer needed.
- * New upstream release
+ -- Luciano Lo Giudice <luciano.logiudice@canonical.com> Thu, 21 Sep 2023 09:47:04 +0100
- -- Alfredo Deza <adeza@redhat.com> Wed, 20 Apr 2016 11:29:47 +0000
+ceph (17.2.6-0ubuntu1) mantic; urgency=medium
-ceph (10.1.2-1) stable; urgency=medium
+ [ Luciano Lo Giudice ]
+ * New upstream point release (LP: #2018929).
+ * d/p/*: Refresh.
- * New upstream release
+ [ James Page ]
+ * d/p/32bit-fixes.patch: rework size_t usage to avoid FTBFS on 32 bit
+ architectures.
- -- Alfredo Deza <adeza@redhat.com> Tue, 12 Apr 2016 17:42:55 +0000
+ -- Luciano Lo Giudice <luciano.logiudice@canonical.com> Fri, 26 May 2023 15:39:37 +0100
-ceph (10.1.1-1) stable; urgency=medium
+ceph (17.2.5-0ubuntu2) lunar; urgency=medium
- * New upstream release
+ * d/ceph-mgr.install: Add object_format.py to mgr install.
- -- Alfredo Deza <adeza@redhat.com> Wed, 06 Apr 2016 00:45:18 +0000
+ -- Chris MacNaughton <chris.macnaughton@ubuntu.com> Mon, 13 Mar 2023 20:56:53 +0000
-ceph (10.1.0-1) stable; urgency=medium
+ceph (17.2.5-0ubuntu1) lunar; urgency=medium
- * New upstream release
+ * New upstream point release (LP: #1998958).
+ * d/p/py310-py-ssize-t-compat.patch,
+ d/p/dc69033763cc116c6ccdf1f97149a74248691042.patch,
+ d/p/a124f6c47b119a8741f347ea5a809f3fb48d6679.patch:
+ Dropped, included upstream.
+ * d/p/patch-out-exporter.patch: Don't build the node exporter as it
+ fails on Jammy.
- -- Alfredo Deza <adeza@redhat.com> Thu, 24 Mar 2016 10:53:47 +0000
+ -- Luciano Lo Giudice <luciano.logiudice@canonical.com> Tue, 21 Feb 2023 16:36:30 +0000
-ceph (10.0.5) stable; urgency=low
+ceph (17.2.0-0ubuntu9) lunar; urgency=medium
- * New upstream release (just fixing changelog)
+ [ Peter Sabaini ]
+ * Create package for the cephfs-mirror tool (LP: #2003704)
+ * Fix: add the mgr.nfs package to the core modules (LP: #2003530).
- -- Sage Weil <sage@newdream.net> Fri, 11 Mar 2016 12:04:26 -0500
+ [ Chris MacNaughton ]
+ * d/p/enable-python311.patch: Cherry-pick upstream change to
+ enable Python 3.11 support (LP: #2004038).
-ceph (10.0.4) stable; urgency=low
+ [ James Page ]
+ * d/gbp.conf: Update default-branch to lunar.
- * New upstream release
+ -- Peter Sabaini <peter.sabaini@canonical.com> Fri, 10 Feb 2023 15:39:01 +0000
- -- Sage Weil <sage@newdream.net> Thu, 03 Mar 2016 13:34:18 -0500
+ceph (17.2.0-0ubuntu8) lunar; urgency=medium
-ceph (10.0.3) stable; urgency=low
+ * Rebuild against latest icu
- * New upstream release
+ -- Jeremy Bicha <jbicha@ubuntu.com> Sun, 05 Feb 2023 21:40:55 -0500
- -- Sage Weil <sage@newdream.net> Mon, 08 Feb 2016 17:10:25 -0500
+ceph (17.2.0-0ubuntu7) lunar; urgency=medium
-ceph (10.0.2-1) stable; urgency=low
+ * debian/patches/dc69033763cc116c6ccdf1f97149a74248691042.patch:
+ * debian/patches/a124f6c47b119a8741f347ea5a809f3fb48d6679.patch:
+ - cherry-pick upstream cephfs-shell fixes.
+ * Fix cephfs-shell install file, taken from Debian 16.2.11+ds-1
+ * Add fix-CheckCxxAtomic-riscv64.patch from Debian 16.2.10+ds-3
- * New upstream release
+ -- Gianfranco Costamagna <locutusofborg@debian.org> Mon, 30 Jan 2023 17:17:28 +0100
- -- Alfredo Deza <adeza@redhat.com> Wed, 13 Jan 2016 16:22:26 +0000
+ceph (17.2.0-0ubuntu6) lunar; urgency=medium
-ceph (10.0.1-1) stable; urgency=low
+ * No-change rebuild with Python 3.11 as default
- * New upstream release
+ -- Graham Inggs <ginggs@ubuntu.com> Mon, 26 Dec 2022 09:49:49 +0000
- -- Alfredo Deza <adeza@redhat.com> Mon, 14 Dec 2015 23:48:54 +0000
+ceph (17.2.0-0ubuntu5) lunar; urgency=medium
-ceph (10.0.0-1) stable; urgency=low
+ * No-change rebuild against libldap-2
- * New upstream release
+ -- Steve Langasek <steve.langasek@ubuntu.com> Thu, 15 Dec 2022 19:43:54 +0000
- -- Alfredo Deza <adeza@redhat.com> Mon, 16 Nov 2015 21:41:53 +0000
+ceph (17.2.0-0ubuntu4) kinetic; urgency=medium
-ceph (9.2.0-1) stable; urgency=low
+ * d/p/fix-kinetic-libfmt.patch: Apply fixes for libfmt > 8.
+ * d/p/fix-kinetic-misc.patch: Misc fixes for Ubuntu Kinetic.
- * New upstream release
+ -- Luciano Lo Giudice <luciano.logiudice@canonical.com> Thu, 22 Sep 2022 17:00:12 +0100
- -- Jenkins Build Slave User <jenkins-build@jenkins-slave-wheezy.localdomain> Tue, 03 Nov 2015 16:58:32 +0000
+ceph (17.2.0-0ubuntu3) kinetic; urgency=medium
-ceph (9.1.0-1) stable; urgency=low
+ * No-change rebuild to pick up fixed libboost-python dependencies
- * New upstream release
+ -- Graham Inggs <ginggs@ubuntu.com> Sat, 03 Sep 2022 13:07:13 +0000
- -- Alfredo Deza <adeza@redhat.com> Tue, 13 Oct 2015 05:56:36 -0700
+ceph (17.2.0-0ubuntu2) kinetic; urgency=medium
-ceph (9.0.3-1) stable; urgency=low
+ * d/p/lp1986747-fix-osd-class-dir.patch: Fix rados-classes
+ search path (LP: #1986747).
- * New upstream release
+ -- Chris MacNaughton <chris.macnaughton@ubuntu.com> Thu, 01 Sep 2022 16:33:54 +0100
- -- Alfredo Deza <adeza@redhat.com> Fri, 21 Aug 2015 12:46:31 -0700
+ceph (17.2.0-0ubuntu1) kinetic; urgency=medium
-ceph (9.0.2-1) stable; urgency=low
+ * New upstream release for Ceph Quincy (LP: #1968318):
+ - d/p/*: Refresh.
+ - d/rules: Disable RADOS Gateway Parquet Object support to avoid
+ pulling new dependencies into Ubuntu main.
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Sun, 01 May 2022 12:00:42 +0100
- -- Alfredo Deza <adeza@redhat.com> Tue, 14 Jul 2015 13:10:31 -0700
+ceph (17.1.0-0ubuntu3) jammy; urgency=medium
-ceph (9.0.1-1) stable; urgency=low
+ * d/p/py310-py-ssize-t-compat.patch: Cherry pick fix to resolve
+ compatibility issues with Python 3.10 (LP: #1964322).
+ * d/ceph-osd.postinst: apply sysctl tuning for ceph-osd daemons
+ on installation (LP: #1903221).
+ * d/control: Drop use of google-perftools on armhf (LP: #1812179).
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Tue, 22 Mar 2022 10:22:37 +0000
- -- Alfredo Deza <adeza@redhat.com> Fri, 05 Jun 2015 10:59:02 -0700
+ceph (17.1.0-0ubuntu2) jammy; urgency=medium
-ceph (9.0.0-1) stable; urgency=low
+ * d/rules: Re-enable SPDK support on supported architectures
+ (LP: #1965109).
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Wed, 16 Mar 2022 09:43:16 +0000
- -- Alfredo Deza <adeza@redhat.com> Mon, 04 May 2015 12:32:58 -0700
+ceph (17.1.0-0ubuntu1) jammy; urgency=medium
-ceph (0.94-1) stable; urgency=low
+ * d/control: Correct Depends: python3-cherrypy -> python3-cherrypy3.
+ * New upstream release candidate for Quincy release.
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Tue, 01 Mar 2022 08:21:39 +0100
- -- Alfredo Deza <adeza@redhat.com> Tue, 07 Apr 2015 10:05:40 -0700
+ceph (17.0.0~git20220222.60fd24-0ubuntu1) jammy; urgency=medium
-ceph (0.93-1) stable; urgency=low
+ * New snapshot from Quincy branch.
+ * d/p/civetweb*: Drop all civetweb related patches as support dropped
+ in Ceph.
+ * d/p/*: Refresh.
+ * d/rules: Tweak install location for Prometheus alerts configuration.
+ * d/rules: Switch to using SYSTEMD_SYSTEM_UNIT_DIR fpr systemd
+ configuration file installation.
+ * d/control: Add Suggests: python3-onelogin-saml2 for mgr-dashboard
+ package for SSO integration.
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Wed, 23 Feb 2022 10:20:11 +0000
- -- Alfredo Deza <adeza@redhat.com> Fri, 27 Feb 2015 09:52:53 -0800
+ceph (17.0.0~git20220204.g77865-0ubuntu1) jammy; urgency=medium
-ceph (0.92-1) stable; urgency=low
+ [ James Page ]
+ * New snapshot from Quincy branch.
+ * d/p/*: Refresh
+ * d/p/bug1917414.patch: Drop, included in snapshot.
+ * d/control: Switch build to use fuse3 (LP: #1959744).
+ * d/ceph-common.install: Add crushdiff binary and manpage.
+ * d/control,ceph-{osd,volume}.install: Split ceph-volume into separate
+ package.
+ * d/rules: Exclude ceph_crypto modules from dh_shlibdeps.
+ * d/p/disable-log-slow-requests.patch: Drop, equivalent fix in
+ upstream snapshot.
+ * d/p/compress-common-depends.patch: Add dependency from compressor-
+ >common.
+ * d/*.symbols: Refresh for new snapshot.
+ * d/p/spdk-fix-make-exe.patch: Fix SPDK build for compat with newer
+ cmake.
+ * d/rules: Disable MAX_PARALLEL calculation for pkg.ceph.unleashed
+ build profile.
+ * d/rules: Disable SPDK feature due to build system issues.
- * New upstream release
+ [ Luciano Lo Giudice ]
+ * d/p/32bit-fixes.patch: Add more 32 bit fixes.
- -- Alfredo Deza <adeza@redhat.com> Mon, 02 Feb 2015 10:35:27 -0800
+ -- James Page <james.page@ubuntu.com> Tue, 22 Feb 2022 09:01:27 +0000
-ceph (0.91-1) stable; urgency=low
+ceph (16.2.7-0ubuntu1) jammy; urgency=medium
- * New upstream release
+ * New upstream release (LP: #1953599).
+ * d/control,ceph-{osd,base}.install,rules: Update name of smartctl
+ sudoers file and move to ceph-base package to allow use from both
+ mon and osd services.
- -- Alfredo Deza <adeza@redhat.com> Tue, 13 Jan 2015 12:10:22 -0800
+ -- James Page <james.page@ubuntu.com> Mon, 13 Dec 2021 14:05:19 +0000
-ceph (0.90-1) stable; urgency=low
+ceph (16.2.6-0ubuntu3) jammy; urgency=medium
- * New upstream release
+ * d/p/patch-spdk-no-literal.patch -> spdk_top-string-format.patch
+ Refresh patch with upstream proposed approach to fix.
+ * d/*: wrap-and-sort -bast.
- -- Alfredo Deza <adeza@redhat.com> Fri, 19 Dec 2014 06:56:22 -0800
+ -- James Page <james.page@ubuntu.com> Fri, 26 Nov 2021 09:26:59 +0000
-ceph (0.89-1) stable; urgency=low
+ceph (16.2.6-0ubuntu2) jammy; urgency=medium
- * New upstream release
+ [ James Page ]
+ * d/ceph-{mon,osd}.postinst: Ensure permissions on
+ /var/lib/ceph/{osd,mon} are correct irrespective of package
+ installation order (LP: #1948986).
- -- Alfredo Deza <adeza@redhat.com> Wed, 03 Dec 2014 08:18:33 -0800
+ [ Chris MacNaughton ]
+ * d/p/patch-spdk-no-literal.patch: Disable warning->error for specific
+ function calls in spdk.
-ceph (0.88-1) stable; urgency=low
+ -- Chris MacNaughton <chris.macnaughton@ubuntu.com> Thu, 11 Nov 2021 13:52:52 +0000
- * New upstream release
+ceph (16.2.6-0ubuntu1) impish; urgency=medium
- -- Alfredo Deza <adeza@redhat.com> Tue, 11 Nov 2014 09:33:12 -0800
+ * New upstream stable release (LP: #1943932).
+ * d/p/*: Refresh.
-ceph (0.87-1) stable; urgency=low
+ -- James Page <james.page@ubuntu.com> Sat, 18 Sep 2021 13:03:53 +0100
- * New upstream release
+ceph (16.2.5-0ubuntu4) impish; urgency=medium
- -- Alfredo Deza <alfredo.deza@inktank.com> Wed, 29 Oct 2014 11:03:55 -0700
+ * d/control: The ISA-L EC plugin changed its build dependency from yasm to
+ nasm 2.13.03 or newer (LP: #1940697).
-ceph (0.86-1) stable; urgency=low
+ -- Frode Nordahl <frode.nordahl@canonical.com> Fri, 10 Sep 2021 14:56:29 +0100
- * New upstream release
+ceph (16.2.5-0ubuntu3) impish; urgency=medium
- -- Alfredo Deza <alfredo.deza@inktank.com> Tue, 07 Oct 2014 06:20:21 -0700
+ * d/librbd1.install: Install any built extensions to librbd.
-ceph (0.85-1) stable; urgency=low
+ -- James Page <james.page@ubuntu.com> Mon, 06 Sep 2021 09:35:44 +0100
- * Development release
+ceph (16.2.5-0ubuntu2) impish; urgency=medium
- -- Alfredo Deza <alfredo.deza@inktank.com> Mon, 08 Sep 2014 06:31:31 -0700
+ * d/rule: Ensure prometheus alerts are installed correctly, resolving
+ FTBFS.
-ceph (0.84-1) stable; urgency=low
+ -- James Page <james.page@ubuntu.com> Wed, 14 Jul 2021 14:08:48 +0100
- * Development release
+ceph (16.2.5-0ubuntu1) impish; urgency=medium
- -- Alfredo Deza <alfredo.deza@inktank.com> Mon, 18 Aug 2014 09:02:20 -0700
+ * New upstream point release (LP: #1935817).
+ * d/control,ceph-grafana-dashboards.install: Add new binary package
+ for Ceph Grafana dashboards.
+ * d/control,ceph-prometheus-alerts.install: Add new binary package
+ for Ceph Prometheus alerts.
-ceph (0.83-1) stable; urgency=low
+ -- James Page <james.page@ubuntu.com> Mon, 12 Jul 2021 10:23:08 +0100
- * Development release
+ceph (16.2.4-0ubuntu2) impish; urgency=medium
- -- Alfredo Deza <alfredo.deza@inktank.com> Tue, 29 Jul 2014 13:42:53 -0700
+ * No-change rebuild due to OpenLDAP soname bump.
-ceph (0.82-1) stable; urgency=low
+ -- Sergio Durigan Junior <sergio.durigan@canonical.com> Mon, 21 Jun 2021 17:44:40 -0400
- * Development release
+ceph (16.2.4-0ubuntu1) impish; urgency=medium
- -- Alfredo Deza <alfredo.deza@inktank.com> Wed, 25 Jun 2014 16:47:51 +0000
+ * d/rules,control: Enable new crimson-osd package and provide
+ seastar based crimson-osd binary.
+ * SECURITY UPDATE: New upstream release (LP: #1928645):
+ - CVE-2021-3509: Dashboard XSS via token cookie.
+ - CVE-2021-3531: Swift API denial of service.
+ - CVE-2021-3531: HTTP header injects via CORS in RGW.
+ - d/p/bug1925347.patch: Drop, included in release.
-ceph (0.81-1) stable; urgency=low
+ -- James Page <james.page@ubuntu.com> Tue, 25 May 2021 09:14:52 +0100
- * Development release
+ceph (16.2.1-0ubuntu1) impish; urgency=medium
- -- Alfredo Deza <alfredo.deza@inktank.com> Mon, 02 Jun 2014 18:37:27 +0000
+ [ Chris MacNaughton ]
+ * d/ceph-base.install: Remove ceph-deploy man page installation
+ (LP: #1892448).
-ceph (0.80-1) stable; urgency=low
+ [ James Page ]
+ * SECURITY UPDATE: New upstream point release (LP: #1925322):
+ - CVE-2021-20288
+ * d/rules: remove temporary build objects after install to avoid
+ running out of disk space during package builds.
+ * d/p/bug1925347.patch: Cherry pick fix to revert ProtectClock
+ permissions change in systemd configurations which prevents the
+ ceph-osd process from starting (LP: #1925347).
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Tue, 04 May 2021 19:21:24 +0100
- -- Alfredo Deza <alfredo.deza@inktank.com> Tue, 06 May 2014 14:03:27 +0000
+ceph (16.2.0-0ubuntu1) hirsute; urgency=medium
-ceph (0.80-rc1-1) stable; urgency=low
+ [ Chris MacNaughton ]
+ * d/p/bug1914584.patch: Improve rgw diagnostic when reusing email
+ (LP: #1914584).
- * New upstream release
+ [ James Page ]
+ * New stable release for Ceph Pacific (LP: #1922883):
+ - d/control: Add BD's on libicu-dev and libsqlite3-dev.
+ - d/control,libsqlite3-mod-ceph*: Add new binary packages
+ for sqlite3 extension module for Ceph.
+ - d/rules: Enable RBD RWL and SSD Cache features.
+ - d/radosgw.install: Add new rgw-gap* binaries.
+ - d/python3-cephfs.install: Restore ceph_volume_client.py
+ for use in OpenStack Manila deployments.
+ - d/control,rules: Add BD's on libpmem{obj}-dev and enable use
+ of system libraries.
+ * Dropped patches, all included in release:
+ - d/p/fix-ftbfs-c++17.patch
+ - d/p/fix-boost-1.74-build.patch
+ - d/p/issue49494.patch
+ * d/p/*: Refresh.
+ * d/p/32bit-fixes.patch: Additional updates for armhf compilation
+ failures.
+ * d/rules: Disable LTO.
- -- Alfredo Deza <alfredo.deza@inktank.com> Tue, 22 Apr 2014 21:21:44 +0000
+ -- James Page <james.page@ubuntu.com> Sat, 10 Apr 2021 08:14:20 +0100
-ceph (0.79-1) stable; urgency=low
+ceph (16.1.0-0ubuntu3) hirsute; urgency=medium
- * New upstream release
+ * d/p/issue49494.patch: Cherry pick fix for issue with preprocessor
+ logic which causes backport failures to focal.
+ * d/p/bug1917414.patch: Cherry pick fix to isa-l to remove use of text
+ relocation calls which cause ceph-osd and ceph-mon daemons to fail
+ to start (LP: #1917414).
- -- Alfredo Deza <alfredo.deza@inktank.com> Mon, 07 Apr 2014 16:48:36 +0000
+ -- James Page <james.page@ubuntu.com> Mon, 15 Mar 2021 08:26:01 +0000
-ceph (0.78-1) stable; urgency=low
+ceph (16.1.0-0ubuntu2) hirsute; urgency=medium
- * New upstream release
+ * No change rebuild with fixed ownership.
- -- Alfredo Deza <alfredo.deza@inktank.com> Fri, 21 Mar 2014 22:05:12 +0000
+ -- Dimitri John Ledkov <xnox@ubuntu.com> Tue, 16 Feb 2021 15:12:17 +0000
-ceph (0.77-1) stable; urgency=low
+ceph (16.1.0-0ubuntu1) hirsute; urgency=medium
- * New upstream release
+ * New interim release in preparation for Ceph Pacific.
+ * d/p/*: Refresh, drop any patches included upstream.
+ * d/control,ceph-mgr-diskprediction-cloud.*: Drop ceph-mgr-
+ diskprediction-cloud package, feature dropped upstream.
+ * d/ceph-mgr-modules-core.install: Include new snap_schedule and stats
+ modules.
+ * d/ceph-osd.install: Include ceph-erasure-code-tool binary.
+ * d/control: Add libcryptsetup-dev to BD's.
+ * d/control: Add liblua5.3-dev and luarocks to BD's.
+ * d/control: Drop use of python3-six.
+ * d/control: Add python3-jinja2 to Depends of ceph-mgr-cephadm.
+ * d/libcephfs-dev.install: Add new Types.h header.
+ * d/librgw{2,-dev}.install: Drop header and so for librgw_admin_user.
+ * d/python3-cephfs.install: Drop install of ceph_volume_client.py.
+ * New upstream snapshot for Pacific release.
+ * d/control: Add libboost-filesystem-dev to BD's, bump boost minimum
+ version to 1.74.0.
+ * d/rules: Install grafana dashboards.
+ * d/p/fix-boost-1.74-build.patch: Resolve build failure with boost
+ 1.74/c++ 17.
+ * d/rules: Drop install of cephadm sudoers configuration.
+ * d/cephadm.install: Drop sudoers file, include manpage.
+ * d/*.symbols: Update for new release.
+ * d/control,rules: Enable use of boost context for riscv64 as its no
+ longer an optional dependency.
+ * d/p/32bit-fixes.patch: Fix issues with mismatched size_t max
+ comparision on armhf.
+ * d/p/disable-log-slow-requests.patch: Remove logging every slow request
+ details to monitors LP: #1909162).
+
+ -- James Page <james.page@ubuntu.com> Mon, 08 Feb 2021 08:10:12 +0000
+
+ceph (15.2.7-0ubuntu4) hirsute; urgency=medium
+
+ * Try to clean up obj build-dir on riscv64 to not run out of disk space
+ during build.
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com> Mon, 18 Jan 2021 12:06:58 +0000
+
+ceph (15.2.7-0ubuntu3) hirsute; urgency=medium
+
+ * Fix ftbfs in hirsute, due to missing atomic include.
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com> Mon, 04 Jan 2021 14:47:39 +0000
+
+ceph (15.2.7-0ubuntu2) hirsute; urgency=medium
+
+ * No-change rebuild for boost soname change.
+
+ -- Matthias Klose <doko@ubuntu.com> Sat, 12 Dec 2020 13:04:13 +0100
+
+ceph (15.2.7-0ubuntu1) hirsute; urgency=medium
+
+ [ Corey Bryant ]
+ * d/p/python3.9.patch: Renamed from patch3.9.diff as Vcs .gitignore
+ will otherwise ignore.
+
+ [ James Page ]
+ * New upstream release.
+
+ -- James Page <james.page@ubuntu.com> Fri, 04 Dec 2020 09:23:59 +0000
+
+ceph (15.2.5-0ubuntu4) hirsute; urgency=medium
+
+ * Make Python 3.9 a known Python3 version.
+
+ -- Matthias Klose <doko@ubuntu.com> Tue, 24 Nov 2020 09:20:31 +0100
+
+ceph (15.2.5-0ubuntu3) hirsute; urgency=medium
+
+ * No-change rebuild to build with python3.9 as default.
+
+ -- Matthias Klose <doko@ubuntu.com> Thu, 19 Nov 2020 20:18:25 +0100
+
+ceph (15.2.5-0ubuntu2) hirsute; urgency=medium
+
+ * Also install ceph_ll_client.h needed by libcephfs.h header file
+
+ -- Gianfranco Costamagna <locutusofborg@debian.org> Sun, 01 Nov 2020 09:51:15 +0100
+
+ceph (15.2.5-0ubuntu1) groovy; urgency=medium
+
+ [ Corey Bryant ]
+ * d/control: Remove Breaks/Replaces that are older than Focal (LP: #1878419).
+ * d/p/enable-strsignal.patch: Enable HAVE_REENTRANT_STRSIGNAL for groovy
+ to fix FTBFS with glibc 2.32.
+ * d/p/rules: Enable RelWithDebInfo (LP: #1894453).
+
+ [ James Page ]
+ * New upstream point release (LP: #1898200).
+ * d/p/fix-crash-in-committed-osd-maps.patch: Drop, included upstream.
+ * d/p/*: Refresh.
+ * d/libcephfs-dev.install: Drop ceph_statx.h.
+
+ [ Dimitri John Ledkov ]
+ * d/rules,control: Enable boost context usage on s390x (LP: #1694926).
+
+ -- James Page <james.page@ubuntu.com> Tue, 06 Oct 2020 12:01:52 +0100
- -- Ken Dreyer <ken.dreyer@inktank.com> Wed, 19 Feb 2014 22:54:06 +0000
+ceph (15.2.3-0ubuntu3) groovy; urgency=medium
-ceph (0.76-1) stable; urgency=low
+ * d/control: Drop BD on obsolete cython (LP: #1891820).
- * New upstream release
+ -- Corey Bryant <corey.bryant@canonical.com> Mon, 17 Aug 2020 13:46:06 -0400
- -- Ken Dreyer <kdreyer@jenkins.front.sepia.ceph.com> Mon, 03 Feb 2014 18:14:59 +0000
+ceph (15.2.3-0ubuntu2) groovy; urgency=medium
-ceph (0.75-1) stable; urgency=low
+ * d/p/fix-crash-in-committed-osd-maps.patch: Fix ceph-osd crash
+ when processing osd map updates (LP: #1891567).
- * New upstream release
+ -- Corey Bryant <corey.bryant@canonical.com> Fri, 14 Aug 2020 11:30:12 -0400
- -- Ken Dreyer <kdreyer@jenkins.front.sepia.ceph.com> Mon, 13 Jan 2014 21:05:07 +0000
+ceph (15.2.3-0ubuntu1) groovy; urgency=medium
-ceph (0.74-1) stable; urgency=low
+ [ Chris MacNaughton ]
+ * d/control: Add python3-yaml to the Ceph dashboard depends (LP: #1876325)
- * New upstream release
+ [ James Page ]
+ * New upstream release (LP: #1880084).
+ * d/p/revert-rgw-move-frontends-initial-init-to-after-glob.patch:
+ Dropped, fix upstream.
+ * d/p/32bit-fixes.patch: Misc updates for 32bit arch build failures.
+ * d/p/*: Refresh.
- -- Gary Lowell <glowell@jenkins.front.sepia.ceph.com> Mon, 30 Dec 2013 21:02:35 +0000
+ -- James Page <james.page@ubuntu.com> Mon, 08 Jun 2020 09:20:21 +0100
-ceph (0.73-1) precise; urgency=low
+ceph (15.2.1-0ubuntu2) focal; urgency=medium
- * New upstream release
+ * Link with -pthread to fix FTBFS on riscv64.
- -- Gary Lowell <gary.lowell@inktank.com> Tue, 10 Dec 2013 04:55:06 +0000
+ -- William Grant <wgrant@ubuntu.com> Sun, 19 Apr 2020 13:58:15 +1000
-ceph (0.72-1) stable; urgency=low
+ceph (15.2.1-0ubuntu1) focal; urgency=high
- * New upstream release
+ * New upstream point release for Octopus (LP: #1873193):
+ - CVE-2020-1759: Fixed nonce reuse in msgr V2 secure mode.
+ - CVE-2020-1760: Fixed XSS due to RGW GetObject header-splitting.
+ * d/copyright: Restore excluded files.
- -- Gary Lowell <gary.lowell@inktank.com> Thu, 07 Nov 2013 20:25:18 +0000
+ -- James Page <james.page@ubuntu.com> Fri, 17 Apr 2020 20:08:37 +0100
-ceph (0.72-rc1-1) stable; urgency=low
+ceph (15.2.0-0ubuntu2) focal; urgency=high
- * New upstream release
+ * d/p/revert-rgw-move-frontends-initial-init-to-after-glob.patch:
+ Revert change to initialize global ceph context before determination
+ of the frontend in use, ensuring that privs are not dropped before
+ any frontend port binding to ports < 1024 has been completed
+ (LP: #1869324).
- -- Gary Lowell <gary.lowell@inktank.com> Wed, 30 Oct 2013 00:44:25 +0000
+ -- James Page <james.page@ubuntu.com> Wed, 08 Apr 2020 10:39:39 +0100
-ceph (0.71-1) stable; urgency=low
+ceph (15.2.0-0ubuntu1) focal; urgency=medium
- * New upstream release
+ * New upstream release for Ceph Octopus.
+ * d/control: Fix dependencies for ceph-mds package to avoid issues
+ with missing C++ symbols (LP: #1862850).
- -- Gary Lowell <gary.lowell@inktank.com> Thu, 17 Oct 2013 09:19:02 +0000
+ -- James Page <james.page@ubuntu.com> Wed, 25 Mar 2020 08:29:08 +0000
-ceph (0.70-1) stable; urgency=low
+ceph (15.1.1-0ubuntu1) focal; urgency=medium
- * New upstream release
+ * New upstream release candidate for Octopus.
+ * d/p/*: Refresh
+ * d/ceph-mgr.install: Drop ansible module.
+ * d/ceph-mgr.install: Drop deepsea module.
+ * d/control: Make cephadm Recommend (but not require) docker.io.
+ * d/control: Add python3-jsonpatch to ceph-mgr-rook Depends.
+ * d/ceph-mgr.install: Rename orchestrator_cli to orchestrator.
+ * d/ceph-mgr.install: Add osd_support module.
+ * d/control,ceph-mgr-modules-core.install: Add new arch:all package
+ for mgr modules, rename plugin->module as needed.
+ * d/ceph-mgr.install: Drop modules that have moved to
+ ceph-mgr-modules-core.
+ * d/control: fix upgrade path for move of modules to -core package.
+ * d/control: Move python3-openssl Depends to -modules-core package.
+ * d/control: Add missing Depends on python3-dateutil to
+ ceph-mgr-modules-core.
+ * d/*.symbols: Refresh for new RC.
- -- Gary Lowell <gary.lowell@inktank.com> Fri, 04 Oct 2013 20:11:51 +0000
+ -- James Page <james.page@ubuntu.com> Mon, 23 Mar 2020 11:19:04 +0000
-ceph (0.69-1) precise; urgency=low
+ceph (15.1.0-0ubuntu3) focal; urgency=medium
- * New upstream release
+ * d/*.symbols: Update symbols files for new release.
- -- Gary Lowell <gary.lowell@inktank.com> Wed, 18 Sep 2013 01:39:47 +0000
+ -- James Page <james.page@ubuntu.com> Fri, 21 Feb 2020 08:51:34 +0000
-ceph (0.68-1) precise; urgency=low
+ceph (15.1.0-0ubuntu2) focal; urgency=medium
- * New upstream release
+ * d/rules,control: Disable Kafka endpoint support for RGW.
- -- Gary Lowell <gary.lowell@inktank.com> Tue, 03 Sep 2013 16:10:11 -0700
+ -- James Page <james.page@ubuntu.com> Mon, 10 Feb 2020 11:53:47 +0000
-ceph (0.67-1) precise; urgency=low
+ceph (15.1.0-0ubuntu1) focal; urgency=medium
- * New upstream release
+ * SECURITY UPDATE: New upstream release (LP: #1861789) including
+ fixes for:
+ - CVE-2020-1699
+ - CVE-2020-1700
+ * d/p/32466.patch-*: Drop, included in release.
+ * New upstream release candidate for Octopus.
+ * d/p/32bit-avoid-overloading.patch,32bit-avoid-size_t.patch,bluefs-
+ use-uint64_t-for-len.patch,fix-clang-build.patch: Drop, no longer
+ needed.
+ * Sync packaging changes with upstream:
+ - d/control,rules,ceph-mgr-ssh.*: Drop ceph-mgr-ssh package.
+ - d/control,rules,{ceph-mgr-}cephadm.*: Add new ceph-mgr-cephadm
+ and cephadm packages, install sudoers file.
+ - d/control,ceph-immutable-object-cache.*: Add new
+ ceph-immutable-object-cache package.
+ - d/control,python3-ceph-common.install: Add new python3-ceph-common
+ package.
+ * d/*: wrap-and-sort -bast.
+ * d/control: Add librdkafka-dev to BD's.
+ * d/p/32bit-fixes.patch: Misc fixes for compilation failures on 32 bit
+ architectures.
+
+ -- James Page <james.page@ubuntu.com> Fri, 07 Feb 2020 11:24:29 +0000
+
+ceph (14.2.5-3ubuntu5) focal; urgency=medium
+
+ * No change rebuild against new boost1.71 ABI
- -- Gary Lowell <gary.lowell@inktank.com> Tue, 13 Aug 2013 10:44:30 -0700
+ -- Dimitri John Ledkov <xnox@ubuntu.com> Mon, 03 Feb 2020 20:03:18 +0000
-ceph (0.67-rc3-1) precise; urgency=low
+ceph (14.2.5-3ubuntu4) focal; urgency=medium
+
+ * d/rules: Don't switch to using clang for armhf on Ubuntu as g++
+ is just fine and does not produce an over linked set of binaries.
+
+ -- James Page <james.page@ubuntu.com> Mon, 27 Jan 2020 09:20:28 +0000
+
+ceph (14.2.5-3ubuntu3) focal; urgency=medium
+
+ * No-change rebuild to build with python3.8.
+
+ -- Matthias Klose <doko@ubuntu.com> Sat, 25 Jan 2020 05:46:31 +0000
+
+ceph (14.2.5-3ubuntu2) focal; urgency=medium
+
+ * d/control: Recommends->Suggests on ceph-fuse for ceph-mds
+ package to avoid main inclusion.
+ * d/rules: Skip radosgw, ceph-common and rbd-mirror packages on i386.
+
+ -- James Page <james.page@ubuntu.com> Tue, 14 Jan 2020 09:27:03 +0000
+
+ceph (14.2.5-3ubuntu1) focal; urgency=medium
+
+ * Merge from Debian unstable, remaining changes:
+ - d/control: Add missing Depends on python3-{distutils,routes} to
+ ceph-mgr-dashboard package (LP: #1858304).
+ * All other changes merged into Debian packaging (Thanks Bernd).
+ * d/control: Fix misnamed package Recommends brbd1 -> librbd1.
+ * d/control: Add missing debhelper misc:Depends for python3-ceph.
+
+ -- James Page <james.page@ubuntu.com> Fri, 10 Jan 2020 09:22:49 +0000
+
+ceph (14.2.5-3) unstable; urgency=medium
+
+ * Uploading to unstable
+
+ * [010db9a] Fix ceph-mgr - indefinite queue growth hangs.
+ Applying the backport for the fix
+ https://github.com/ceph/ceph/pull/32466
+ Thanks to Milan Kupcevic (Closes: #947969)
+ * [b01de37] Merge branch 'debian/unstable' into debian/experimental
+ * [c8f35e5] Add breaks/replaces for ceph-common - ceph mds.
+ * [ee905cb] Revert "Configure gbp for experimental"
+ This reverts commit 3bcd5ac5f416b902a868036c243d7f19752c82f8.
+ * [6303513] Revert "CI: build in experimental"
+ This reverts commit d481122833e611c69c28e2b381e1cc1c8f689385.
+ * [f1a9482] Snapshot changelog
+ * [6e955c8] Removing automatic Ubuntu header
+ * [b90d95a] Mark patch as forwarded
+
+ -- Bernd Zeimetz <bzed@debian.org> Tue, 07 Jan 2020 20:50:28 +0100
+
+ceph (14.2.5-2) experimental; urgency=medium
+
+ * [8c74414] lower --max-parallel for >=16GB
+ g++ loves to eat ram
+ * [b15dcdd] Build-dep. on python3-dev instead python3-all-dev.
+ Thanks to Graham Inggs (Closes: #948021)
+ * [d481122] CI: build in experimental
+ * [4303a75] 32bit: fix more size_t vs uint64_t issues.
+ * [c98ea07] Install bash-completion in /usr again.
+ This change went missing somewhere during the import of the
+ changes done in Ubuntu between 12.2.11 and 14.2.4.
+ Thanks to Andreas Beckmann (Closes: #948165)
+ * [c7d90b9] Move manpages to ceph-common again.
+ This also went missing during the import.
+ * [3e5a680] Use a better way to check if we are on 32bit.
+ * [c03cd06] rm d/p/boost-py37-compat.patch.
+ Upstream renamed assert.h to ceph_assert.h, so this patch should not be
+ necessary anymore.
+
+ -- Bernd Zeimetz <bzed@debian.org> Sun, 05 Jan 2020 00:04:23 +0100
+
+ceph (14.2.5-1) experimental; urgency=medium
+
+ [ Bernd Zeimetz ]
+ * [3bcd5ac] Configure gbp for experimental
+ * [bd0b051] New upstream version 14.2.5
+ * [46cbe61] Merge upstream changes for 14.2.5
+ * [4dfd819] Refreshing patches
+ * [da26f25] Fix copy&paste errors in build-deps.
+ * [7ff43a2] Mark build-deps needed for make check.
+ And remove the need to install them.
+ * [5ef8ac3] Remove left over patch file
+ * [91ab5b9] */lib_tp.so files are not built, don't install them.
+ * [44591e4] Don't try to install files we don't build
+ * [db0994e] librbd1.symbols: add new symbols.
+ * [d53724e] Add install/postinstall files for ceph-mgr-k8sevents
+ * [acada37] Add lintian override for .chm file.
+ Source and build info is shipped.
+ * [bbb0bd6] copy the radosgw init file in override_dh_installinit.
+ * [a5958d5] Avoid duplicate files.
+ etc/bash_completion.d/ceph was accidentally shipped in ceph-base again.
+ * [fbc33a3] Add missing > in Dependency.
+
+ -- Bernd Zeimetz <bzed@debian.org> Thu, 02 Jan 2020 10:52:50 +0100
+
+ceph (14.2.4-9) unstable; urgency=medium
+
+ * [8c74414] lower --max-parallel for >=16GB
+ g++ loves to eat ram
+ * [b15dcdd] Build-dep. on python3-dev instead python3-all-dev.
+ Thanks to Graham Inggs (Closes: #948021)
+ * [c98ea07] Install bash-completion in /usr again.
+ This change went missing somewhere during the import of the
+ changes done in Ubuntu between 12.2.11 and 14.2.4.
+ Thanks to Andreas Beckmann (Closes: #948165)
+ * [c7d90b9] Move manpages to ceph-common again.
+ This also went missing during the import.
+
+ -- Bernd Zeimetz <bzed@debian.org> Sun, 05 Jan 2020 00:22:21 +0100
+
+ceph (14.2.4-8) unstable; urgency=medium
+
+ * [e187e6a] Use WITH_CCACHE from cmake to build with ccache.
+ * [8cbe25e] Hack CMakeCache.txt to disable HAVE_ARM_NEON on armel.
+ after trying to patch the various places where HAVE_ARM_NEON is used
+ the easiest way to get rid of it on armel seems to be to patch the cmake
+ cache file.
+ * [424ea9b] Don't build ceph on mipsel.
+ No compiler is able to build the code without running into oom-issues.
+
+ -- Bernd Zeimetz <bzed@debian.org> Wed, 01 Jan 2020 19:29:48 +0100
+
+ceph (14.2.4-7) unstable; urgency=medium
+
+ * [9b97753] Make sure we use ccache if needed.
+ * [3dbd1ac] d/rules: Remove the armel fpu options.
+ Hopefully properly patched now.
+ * [da253e4] m68k, sh4: build with clang to avoid gcc OOM.
+
+ -- Bernd Zeimetz <bzed@debian.org> Tue, 31 Dec 2019 00:13:23 +0100
+
+ceph (14.2.4-6) unstable; urgency=medium
+
+ * [b1c9b5d] Try to reduce memory usage even further if needed.
+ gcc loves to eat too much memory on armhf mipsel armel.
+ * [d695778] Remove softfp patch in favour of build flags.
+ This hopefully avoids the need to update and debug the patch.
+ * [6eddb32] Build with clang(++) on armhf mipsel armel.
+ Reports seem to suggest that clang does not need as much memory as gcc.
+ * [b9420ba] Fix unsigned/size_t issue for sh4 & m86k.
+ * [0027181] Updating changelog
+ * [6502f60] Fix another 32bit size_t/uint64_t issue.
+ In src/common/options.cc line 192.
+ * [4a0b044] Fix another 32bit size_t/uint64_t issue.
+ This time: powerpc.
+
+ -- Bernd Zeimetz <bzed@debian.org> Sun, 29 Dec 2019 17:38:10 +0100
+
+ceph (14.2.4-5) unstable; urgency=medium
+
+ [ Bernd Zeimetz ]
+ * [453eaa4] Avoid using make -j 32 on powerpc.
+ A lot of CPU do not always help.
+
+ [ Milan Kupcevic ]
+ * [c6ec924] cherry pick critical bluestore data corruption fix
+ (Closes: #947457)
+
+ [ Bernd Zeimetz ]
+ * [e88fc21] Set -DWITH_BOOST_CONTEXT=OFF where necessary.
+ [!s390x !mips64el !ia64 !m68k !ppc64 !riscv64 !sh4 !sparc64 !x32]
+
+ -- Bernd Zeimetz <bzed@debian.org> Sat, 28 Dec 2019 15:54:51 +0100
+
+ceph (14.2.4-4) unstable; urgency=medium
+
+ * [b70efb1] Create missing directories for arch:all build.
+ * [3e4530f] try to save even more memory on armhf.
+ Don't build debug flags at all.
+ * [b478ee5] Avoid overloading on mipsel.
+ Add mipsel to debian/patches/32bit-avoid-overloading.patch
+ * [85eb6e9] Also build jerasure with softfp on armel.
+
+ -- Bernd Zeimetz <bzed@debian.org> Thu, 26 Dec 2019 16:03:51 +0100
+
+ceph (14.2.4-3) unstable; urgency=medium
+
+ [ Bernd Zeimetz ]
+ * [f3f47f5] CI: disable extra-long running tests.
+
+ [ Steve Langasek ]
+ * [9794fc4] Drop uninstallable and unneeded server binaries on i386.
+ (Closes: #947156)
+
+ [ Bernd Zeimetz ]
+ * [6c2993f] Merge tag 'debian/14.2.4-0ubuntu3' into debian/unstable
+ * [0c5b41f] Use a tracker.d.o list instead of a closed one. (Closes: #760538)
+ * [d95db97] Try to build with --max-parallel=1 on slow arches.
+ We run into out-of-memory errors again.
+ * [e8d9e63] Use -mfloat-abi=softfp on armel for NEON instructions.
+ And again, that patch went missing somewhere.
+ Taken from
+ https://salsa.debian.org/ceph-team/ceph/commit/fa7d0d84f736d0b8450572f3192a43ff7b3252c4
+
+ -- Bernd Zeimetz <bzed@debian.org> Tue, 24 Dec 2019 13:03:45 +0100
+
+ceph (14.2.4-2) unstable; urgency=medium
+
+ [ Thomas Goirand ]
+ * [4b2327d] Add a python3-ceph metapackage.
+
+ [ Bernd Zeimetz ]
+ * [dbc7d2f] Add lintian override for empty python3-ceph package.
+ * [5381390] Remove -en from description.
+ We actually want to have a description in the changes file...
+ * [4a57f31] Make python3-ceph dependencies binNMU safe
+
+ -- Bernd Zeimetz <bzed@debian.org> Thu, 28 Nov 2019 09:43:37 +0100
+
+ceph (14.2.4-1) unstable; urgency=medium
+
+ * Uploading 14.2.4 to Debian.
+ (Closes: #936282, #943961, #940854, #942733)
+ * Adding missing sources (two.js, bootstrap 3.3.4)
+ * ceph-mon.postinst missed the interpreter
+ * Add missing dependency on python3
+ * ignore lintian errors about minified js with shipped sources
+ * Radowgw uses a systemd template, override lintian.
+ * libcephfs-jni: rpath to java libraries needed.
+ Add lintian override.
+ * Remove .pc folder from debian folder.
+ * Adding myself to Uploaders
+ * Merging the work done in Ubuntu.
+
+ [ Dariusz Gadomski ]
+ * d/p/issue37490.patch: Cherry pick fix to optimize LVM queries in
+ ceph-volume, resolving performance issues in systems under heavy load
+ or with large numbers of disks (LP: #1850754).
+
+ [ James Page ]
+ * d/p/issue40114.patch: Cherry pick endian fixes to resolve issues
+ using Ceph on big-endian architectures such as s390x (LP: #1851290).
+ * New upstream release (LP: #1850901):
+ - d/p/more-py3-compat.patch,ceph-volume-wait-for-lvs.patch,
+ ceph-volume-wait-for-lvs.patch: Drop, included upstream.
+ - d/p/bluefs-use-uint64_t-for-len.patch: Cherry pick fix to resolve
+ FTBFS on 32 bit architectures.
+ * d/rules: Disable SPDK support as this generates a build which
+ has a minimum CPU baseline of 'corei7' on x86_64 which is not
+ compatible with older CPU's (LP: #1842020).
+ * d/p/issue40781.patch: Cherry pick fix for py3 compatibility in ceph-
+ crash.
+
+ [ Eric Desrochers ]
+ * Ensure that daemons are not automatically restarted during package
+ upgrades (LP: #1840347):
+ - d/rules: Use "--no-restart-after-upgrade" and "--no-stop-on-upgrade"
+ instead of "--no-restart-on-upgrade".
+ - d/rules: Drop exclusion for ceph-[osd,mon,mds] for restarts.
+
+ [ Jesse Williamson ]
+ * d/p/civetweb-755-1.8-somaxconn-configurable*.patch: Backport changes
+ to civetweb to allow tuning of SOMAXCONN in Ceph RADOS Gateway
+ deployments (LP: #1838109).
+
+ [ James Page ]
+ * d/p/ceph-volume-wait-for-lvs.patch: Cherry pick inflight fix to
+ ensure that required wal and db devices are present before
+ activating OSD's (LP: #1828617).
+
+ [ Steve Beattie ]
+ * SECURITY UPDATE: RADOS gateway remote denial of service
+ - d/p/CVE-2019-10222.patch: rgw: asio: check the remote endpoint
+ before processing requests.
+ - CVE-2019-10222
+ - Closes: #936015
+
+ [ James Page ]
+ * New upstream release.
+ * d/p/fix-py3-encoding-fsid.patch: Drop, no longer required.
+ * d/p/pybind-auto-encode-decode-cstr.patch: Drop, reverted upstream.
+ * d/p/fix-py3-encoding-fsid.patch: Cherry pick correct fix to resolve
+ FSID encoding issues under Python 3 (LP: #1833079).
+ * d/p/pybind-auto-encode-decode-cstr.patch: Cherry pick fix to ensure
+ that encoding/decoding of strings is correctly performed under
+ Python 3 (LP: #1833079).
+
+ * New upstream release.
+ * d/p/misc-32-bit-fixes.patch: Drop, included upstream.
+ * d/p/py37-compat.patch: Drop, included upstream.
+ * d/p/collections.abc-compat.patch: Drop, included in release.
+ * d/p/*: Refresh.
+ * d/*: Re-sync packaging with upstream for Nautilus release.
+ * d/control,ceph-test.*,rules: Disable build of test binaries, drop
+ ceph-test binary package (reduce build size).
+ * d/control,rules: Use system boost libraries (reduce build time).
+ * d/control: Add dependency on smartmontools, suggest use of nvme-cli
+ for ceph-osd package.
+ * d/p/32bit-*.patch: Fix misc 32 bit related issues which cause
+ compilation failures on armhf and i386 architectures.
+ * d/control: Add Breaks/Replaces on ceph-common for ceph-argparse to
+ deal with move of Python module.
+
+ * New upstream release (LP: #1810766).
+ * d/p/*: Refresh.
+
+ * d/p/more-py3-compat.patch: Add more py3 fixes.
+
+ * d/p/more-py3-compat.patch: Misc Python 3 fixes in ceph-create-keys.
+
+ * d/tests/python-ceph: Fix python3 test support resolving
+ autopkgtest failure.
+
+ * New upstream point release.
+ * d/p/*: Refresh.
+ * d/control,python-*.install,rules: Drop Python 2 support.
+ * d/tests: Update for Python 2 removal.
+ * d/p/misc-32-bit-fixes.patch: Update type of rgw_max_attr_name_len,
+ resolving SIGABRT in radosgw (LP: #1805145).
+ * d/p/boost-py37-compat.patch: Fix compilation issue with boost
+ imports conflicting with ceph's assert.h header.
+ * d/p/collections.abc-compat.patch: Selective cherry-pick of upstream
+ fix for future compatibility with Python 3.8, avoiding deprecation
+ warnings under Python 3.7.
+
+ * d/ceph-mds.install: Install missing systemd configuration
+ (LP: #1789927).
+
+ * Re-instate 32bit architectures.
+ - d/control: Switch back to linux-any
+ - d/p/misc-32-bit-fixes.patch: Misc fixes for compilation
+ failures under 32 bit architectures.
+ - d/rules: Disable SPDK integration under i386.
+ * Repack upstream tarball, excluding non-DFSG sources (LP: #1750848):
+ - d/copyright: Purge upstream tarball of minified js files, which
+ are neither shipped in binaries or required for package build.
+ - d/watch: Add dversionmangle for +dfsg\d version suffix.
+ * d/control,rules: Drop requirement for gcc-7 for arm64.
+ * d/ceph-osd.udev: Add udev rules for sample LVM layout for OSD's,
+ ensuring that LV's have ceph:ceph ownership (LP: #1767087).
+
+ * d/copyright,source.lintian-overrides: Exclude jsonchecker component
+ of rapidjson avoiding license-problem-json-evil non-free issue.
+ * New upstream point release.
+ * d/control: Remove obsolete X{S}-* fields.
+
+ * New upstream release.
+ * Sync with changes in upstream packaging:
+ - d/*.install,rules: Use generated systemd unit files for install
+ - d/ceph-test.install: Drop binaries removed upstream.
+ * d/p/*: Refresh and drop as needed.
+ * d/*.symbols: Refresh for new release.
+ * d/rules,calc-max-parallel.sh: Automatically calculate the maximum
+ number of parallel compilation units based on total memory.
+ * d/control: Drop support for 32 bit architectures.
+ * d/control: Update Vcs-* fields for Ubuntu.
+ * d/control: Drop min python version field.
+
+ -- Bernd Zeimetz <bzed@debian.org> Mon, 18 Nov 2019 14:18:10 +0100
+
+ceph (14.2.4-0ubuntu3) focal; urgency=medium
+
+ * Drop uninstallable and unneeded server binaries on i386.
+
+ -- Steve Langasek <steve.langasek@ubuntu.com> Sat, 21 Dec 2019 17:05:10 -0600
+
+ceph (14.2.4-0ubuntu2) focal; urgency=medium
+
+ [ Dariusz Gadomski ]
+ * d/p/issue37490.patch: Cherry pick fix to optimize LVM queries in
+ ceph-volume, resolving performance issues in systems under heavy load
+ or with large numbers of disks (LP: #1850754).
+
+ [ James Page ]
+ * d/p/issue40114.patch: Cherry pick endian fixes to resolve issues
+ using Ceph on big-endian architectures such as s390x (LP: #1851290).
+
+ -- Dariusz Gadomski <dariusz.gadomski@canonical.com> Wed, 06 Nov 2019 11:08:53 +0100
+
+ceph (14.2.4-0ubuntu1) focal; urgency=medium
+
+ * New upstream release (LP: #1850901):
+ - d/p/more-py3-compat.patch,ceph-volume-wait-for-lvs.patch,
+ ceph-volume-wait-for-lvs.patch: Drop, included upstream.
+ - d/p/bluefs-use-uint64_t-for-len.patch: Cherry pick fix to resolve
+ FTBFS on 32 bit architectures.
+
+ -- James Page <james.page@ubuntu.com> Mon, 04 Nov 2019 14:10:20 +0000
+
+ceph (14.2.2-0ubuntu4) focal; urgency=medium
+
+ * No-change rebuild to build with python3.8.
+
+ -- Matthias Klose <doko@ubuntu.com> Fri, 18 Oct 2019 18:38:16 +0000
+
+ceph (14.2.2-0ubuntu3) eoan; urgency=medium
+
+ * d/rules: Disable SPDK support as this generates a build which
+ has a minimum CPU baseline of 'corei7' on x86_64 which is not
+ compatible with older CPU's (LP: #1842020).
+ * d/p/issue40781.patch: Cherry pick fix for py3 compatibility in ceph-
+ crash.
+
+ -- James Page <james.page@ubuntu.com> Tue, 03 Sep 2019 14:52:38 +0100
+
+ceph (14.2.2-0ubuntu2) eoan; urgency=medium
+
+ [ Eric Desrochers ]
+ * Ensure that daemons are not automatically restarted during package
+ upgrades (LP: #1840347):
+ - d/rules: Use "--no-restart-after-upgrade" and "--no-stop-on-upgrade"
+ instead of "--no-restart-on-upgrade".
+ - d/rules: Drop exclusion for ceph-[osd,mon,mds] for restarts.
+
+ [ Jesse Williamson ]
+ * d/p/civetweb-755-1.8-somaxconn-configurable*.patch: Backport changes
+ to civetweb to allow tuning of SOMAXCONN in Ceph RADOS Gateway
+ deployments (LP: #1838109).
+
+ [ James Page ]
+ * d/p/ceph-volume-wait-for-lvs.patch: Cherry pick inflight fix to
+ ensure that required wal and db devices are present before
+ activating OSD's (LP: #1828617).
+
+ [ Steve Beattie ]
+ * SECURITY UPDATE: RADOS gateway remote denial of service
+ - d/p/CVE-2019-10222.patch: rgw: asio: check the remote endpoint
+ before processing requests.
+ - CVE-2019-10222
+
+ -- James Page <james.page@ubuntu.com> Thu, 29 Aug 2019 13:54:25 +0100
- * New upstream release
+ceph (14.2.2-0ubuntu1) eoan; urgency=medium
- -- Gary Lowell <gary.lowell@inktank.com> Tue, 30 Jul 2013 14:37:40 -0700
+ * New upstream release.
+ * d/p/fix-py3-encoding-fsid.patch: Drop, no longer required.
+
+ -- James Page <james.page@ubuntu.com> Wed, 28 Aug 2019 08:42:02 +0100
-ceph (0.67-rc2-1) precise; urgency=low
+ceph (14.2.1-0ubuntu3) eoan; urgency=medium
- * New upstream release
+ * d/p/pybind-auto-encode-decode-cstr.patch: Drop, reverted upstream.
+ * d/p/fix-py3-encoding-fsid.patch: Cherry pick correct fix to resolve
+ FSID encoding issues under Python 3 (LP: #1833079).
- -- Gary Lowell <gary.lowell@inktank.com> Wed, 24 Jul 2013 16:18:33 -0700
+ -- James Page <james.page@ubuntu.com> Tue, 25 Jun 2019 08:02:09 +0100
-ceph (0.67-rc1-1) precise; urgency=low
+ceph (14.2.1-0ubuntu2) eoan; urgency=medium
- * New upstream release
+ * d/p/pybind-auto-encode-decode-cstr.patch: Cherry pick fix to ensure
+ that encoding/decoding of strings is correctly performed under
+ Python 3 (LP: #1833079).
- -- Gary Lowell <gary.lowell@inktank.com> Mon, 22 Jul 2013 11:57:01 -0700
+ -- James Page <james.page@ubuntu.com> Fri, 21 Jun 2019 07:08:20 +0100
-ceph (0.66-1) precise; urgency=low
+ceph (14.2.1-0ubuntu1) eoan; urgency=medium
+
+ * New upstream release.
+ * d/p/misc-32-bit-fixes.patch: Drop, included upstream.
+ * d/p/py37-compat.patch: Drop, included upstream.
+ * d/p/collections.abc-compat.patch: Drop, included in release.
+ * d/p/*: Refresh.
+ * d/*: Re-sync packaging with upstream for Nautilus release.
+ * d/control,ceph-test.*,rules: Disable build of test binaries, drop
+ ceph-test binary package (reduce build size).
+ * d/control,rules: Use system boost libraries (reduce build time).
+ * d/control: Add dependency on smartmontools, suggest use of nvme-cli
+ for ceph-osd package.
+ * d/p/32bit-*.patch: Fix misc 32 bit related issues which cause
+ compilation failures on armhf and i386 architectures.
+ * d/control: Add Breaks/Replaces on ceph-common for ceph-argparse to
+ deal with move of Python module.
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Wed, 29 May 2019 05:25:27 +0100
- -- Gary Lowell <gary.lowell@inktank.com> Mon, 08 Jul 2013 15:44:45 -0700
+ceph (13.2.4+dfsg1-0ubuntu2) disco; urgency=medium
-ceph (0.65-1) precise; urgency=low
+ * Rebuild for libleveldb1v5 -> libleveldb1d transition.
- * New upstream release
+ -- Adam Conrad <adconrad@ubuntu.com> Fri, 12 Apr 2019 12:37:05 -0600
- -- Gary Lowell <gary.lowell@inktank.com> Tue, 25 Jun 2013 09:19:14 -0700
+ceph (13.2.4+dfsg1-0ubuntu1) disco; urgency=medium
-ceph (0.64-1) precise; urgency=low
+ * New upstream release (LP: #1810766).
+ * d/p/*: Refresh.
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Tue, 08 Jan 2019 11:40:47 +0000
- -- Gary Lowell <gary.lowell@inktank.com> Wed, 12 Jun 2013 09:53:54 -0700
+ceph (13.2.2+dfsg1-0ubuntu4) disco; urgency=medium
-ceph (0.63-1) precise; urgency=low
+ * d/p/more-py3-compat.patch: Add more py3 fixes.
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Fri, 07 Dec 2018 10:31:26 +0000
- -- Gary Lowell <gary.lowell@inktank.com> Tue, 28 May 2013 13:57:53 -0700
+ceph (13.2.2+dfsg1-0ubuntu3) disco; urgency=medium
-ceph (0.62) precise; urgency=low
+ * d/p/more-py3-compat.patch: Misc Python 3 fixes in ceph-create-keys.
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Wed, 05 Dec 2018 16:37:07 +0000
- -- Gary Lowell <gary.lowell@inktank.com> Tue, 14 May 2013 09:08:21 -0700
+ceph (13.2.2+dfsg1-0ubuntu2) disco; urgency=medium
-ceph (0.61-1) precise; urgency=low
+ * d/tests/python-ceph: Fix python3 test support resolving
+ autopkgtest failure.
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Fri, 30 Nov 2018 13:00:55 +0000
- -- Gary Lowell <gary.lowell@inktank.com> Mon, 06 May 2013 13:18:43 -0700
+ceph (13.2.2+dfsg1-0ubuntu1) disco; urgency=medium
-ceph (0.60-1) precise; urgency=low
+ * New upstream point release.
+ * d/p/*: Refresh.
+ * d/control,python-*.install,rules: Drop Python 2 support.
+ * d/tests: Update for Python 2 removal.
+ * d/p/misc-32-bit-fixes.patch: Update type of rgw_max_attr_name_len,
+ resolving SIGABRT in radosgw (LP: #1805145).
+ * d/p/boost-py37-compat.patch: Fix compilation issue with boost
+ imports conflicting with ceph's assert.h header.
+ * d/p/collections.abc-compat.patch: Selective cherry-pick of upstream
+ fix for future compatibility with Python 3.8, avoiding deprecation
+ warnings under Python 3.7.
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Thu, 29 Nov 2018 09:34:25 +0000
- -- Gary Lowell <gary.lowell@inktank.com> Mon, 01 Apr 2013 12:22:30 -0700
+ceph (13.2.1+dfsg1-0ubuntu3) disco; urgency=medium
-ceph (0.59-1) precise; urgency=low
+ * No-change rebuild for python3.7 as the default python3.
- * New upstream release
+ -- Matthias Klose <doko@ubuntu.com> Tue, 30 Oct 2018 19:25:09 +0100
- -- Gary Lowell <gary.lowell@inktank.com> Tue, 19 Mar 2013 22:26:37 -0700
+ceph (13.2.1+dfsg1-0ubuntu2) cosmic; urgency=medium
-ceph (0.58-1) precise; urgency=low
+ * d/ceph-mds.install: Install missing systemd configuration
+ (LP: #1789927).
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Thu, 30 Aug 2018 16:07:10 +0100
- -- Gary Lowell <gary.lowell@inktank.com> Mon, 04 Mar 2013 15:17:58 -0800
+ceph (13.2.1+dfsg1-0ubuntu1) cosmic; urgency=medium
-ceph (0.57-1) quantal; urgency=low
+ * Re-instate 32bit architectures.
+ - d/control: Switch back to linux-any
+ - d/p/misc-32-bit-fixes.patch: Misc fixes for compilation
+ failures under 32 bit architectures.
+ - d/rules: Disable SPDK integration under i386.
+ * Repack upstream tarball, excluding non-DFSG sources (LP: #1750848):
+ - d/copyright: Purge upstream tarball of minified js files, which
+ are neither shipped in binaries or required for package build.
+ - d/watch: Add dversionmangle for +dfsg\d version suffix.
+ * d/control,rules: Drop requirement for gcc-7 for arm64.
+ * d/ceph-osd.udev: Add udev rules for sample LVM layout for OSD's,
+ ensuring that LV's have ceph:ceph ownership (LP: #1767087).
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Thu, 09 Aug 2018 14:20:08 +0100
- -- Gary Lowell <gary.lowell@inktank.com> Tue, 19 Feb 2013 10:06:39 -0800
+ceph (13.2.1-0ubuntu1) cosmic; urgency=medium
-ceph (0.56-1) quantal; urgency=low
+ * d/copyright,source.lintian-overrides: Exclude jsonchecker component
+ of rapidjson avoiding license-problem-json-evil non-free issue.
+ * New upstream point release.
+ * d/control: Remove obsolete X{S}-* fields.
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Wed, 01 Aug 2018 11:13:12 +0100
- -- Gary Lowell <gary.lowell@inktank.com> Mon, 31 Dec 2012 17:08:45 -0800
+ceph (13.2.0-0ubuntu1) cosmic; urgency=medium
-ceph (0.55.1-1) precise; urgency=low
+ * New upstream release.
+ * Sync with changes in upstream packaging:
+ - d/*.install,rules: Use generated systemd unit files for install
+ - d/ceph-test.install: Drop binaries removed upstream.
+ * d/p/*: Refresh and drop as needed.
+ * d/*.symbols: Refresh for new release.
+ * d/rules,calc-max-parallel.sh: Automatically calculate the maximum
+ number of parallel compilation units based on total memory.
+ * d/control: Drop support for 32 bit architectures.
+ * d/control: Update Vcs-* fields for Ubuntu.
+ * d/control: Drop min python version field.
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Tue, 24 Jul 2018 11:01:39 +0100
- -- Gary Lowell <gary.lowell@inktank.com> Wed, 12 Dec 2012 16:24:13 -0800
+ceph (12.2.11+dfsg1-2.1) unstable; urgency=medium
-ceph (0.55-1) precise; urgency=low
+ * Non-maintainer upload.
+ * [3194010] Install ceph-volume@.service into ceph-osd.
+ (Closes: #924061)
+
+ -- Bernd Zeimetz <bzed@debian.org> Fri, 05 Apr 2019 15:12:52 +0200
+
+ceph (12.2.11+dfsg1-2) unstable; urgency=medium
+
+ * [27a321] Fix builds on 32bit architectures
+ * [346bfa] Fix linking radosgw without BEAST frontend
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Tue, 19 Feb 2019 08:50:12 +0100
+
+ceph (12.2.11+dfsg1-1) unstable; urgency=medium
+
+ * [8b6f70] Build depend on cmake >= 3.13.2
+ * [98ed84] New upstream version 12.2.11+dfsg1
+ - Fixes CVE-2018-14662, CVE-2018-16889, CVE-2018-16846
+ (Closes: #921948, #918969, #921947)
+ * [4d5c86] Mark all LTTng tracepoints symbols as optional
+ * [b92a2f] Build depend on debhelper >= 11.5.4~
+ * [5781cc] Add Breaks/Replaces ceph-base (<< 12.2.10+dfsg1-1~) to ceph-common
+ (Closes: #919898)
+ * [658bd3] Fixup Breaks/Replaces for files moved between binary packages
+ * [c24137] Install systemd units for Ceph MGR service
+ (Closes: #920176, #919871)
+ * [091e14] Remove no longer needed dpkg-maintscript-helper calls in radosgw
+ * [567dde] Temp changelog commit
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Tue, 12 Feb 2019 10:55:02 +0100
+
+ceph (12.2.10+dfsg1-1) unstable; urgency=medium
+
+ * [22146e] ceph-base: create directory for bootstrap-rbd key
+ * [8c0362] Move ceph bash completion to ceph-common
+ * [b9e790] Make ceph binary package Suggests binNMU safe
+ * [fc83f1] Install ceph-fuse systemd service file
+ * [e70c29] Enable LTTng
+ * [234e9b] New upstream version 12.2.10+dfsg1
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Sat, 29 Dec 2018 22:08:52 +0100
+
+ceph (12.2.8+dfsg1-5) unstable; urgency=medium
+
+ * [66e03b] Fix linking on archs which require libatomic
+ * [5236f3] Fix Python 3 autopkgtest
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Fri, 30 Nov 2018 16:49:02 +0100
+
+ceph (12.2.8+dfsg1-4) unstable; urgency=medium
+
+ * [97dfb6] Fix detection of armel for NEON instructions (Closes: #913599)
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Thu, 22 Nov 2018 22:33:21 +0100
+
+ceph (12.2.8+dfsg1-3) unstable; urgency=medium
+
+ * [168bb9] Build depend on pythonX-dev instead of pythonX-all-dev
+ (Closes: #912905)
+ * [38d140] Patch to check for atomic support during build (Closes: #913601)
+ * [9cc0a5] Disable libboost-context on unsupported archs (Closes: #913600)
+ * [238143] Fix building with -g1 on 32 bit architectures
+ * [3b48d5] Use -mfloat-abi=softfp on armel for NEON instructions
+ (Closes: #913599)
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Thu, 22 Nov 2018 09:38:09 +0100
+
+ceph (12.2.8+dfsg1-2) unstable; urgency=medium
+
+ * [5c4b36] Add architecture specific symbols for librados2
+ * [38bc1b] Build depend on libatomic1 on armel, m68k, mips, mipsel, powerpc,
+ powerpcspe and sh4
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Wed, 31 Oct 2018 23:38:05 +0100
+
+ceph (12.2.8+dfsg1-1) unstable; urgency=medium
+
+ [ James Page ]
+ * [9c55f6] Ensure that systemd targets are enabled and started
+ * [17ca38] Support optional runtime loading of openssl in radosgw
+ * [8927f6] Fix build on i386
+ * [774281] Ensure all ceph modules are included in the binary package.
+ * [00ca38] Cherry pick upstream fix to resolve FTBFS on armhf
+ * [5d118c] Add ceph-volume tools to ceph-osd package
+
+ [ Gaudenz Steinlin ]
+ * [ba768b] New upstream version 12.2.8+dfsg1
+ (Closes: #852999, #864535, #893149)
+ * [96eba0] Exclude jsonchecker from upstream source
+ * [7dd73b] Exclude Windows help file from orig tarball
+ * [9d1740] Move ceph initscript and systemd target to ceph-base
+ * [8ae049] Drop obsolete patches (either upstreamed or because of switch to
+ cmake)
+ * [cfd095] Create directory for Ceph Manager bootstrap keys
+ * [858194] Shell scripts moved out of architecture specific directory
+ * [f3f387] Merge ceph-fs-common package into ceph-common
+ * [1789fe] Move radosgw-admin to ceph-common
+ * [6f51fc] Add compressor plugins to ceph-common
+ * [5bd0d1] Add crypto plugins to ceph-common on amd64
+ * [7724f7] New binary package ceph-mgr
+ * [804be6] Remove librgw_file* from ceph-test. These are unit tests for rgw.
+ * [fef87a] Upstream changed the build system to cmake
+ * [134e34] Build Python 3 versions of Python modules (Closes: #883148)
+ * [52a969] Package RADOS gateway Python bindings (python-rgw)
+ * [a48700] Add rados-objclass-dev binary package
+ * [30306f] Update dependencies for new upstream release
+ * [4d07af] libcephfs1 -> libcephfs2 soname bumped upstream
+ * [c4022d] Remove ceph-disk-udev no longer shipped upstream
+ * [9aad82] Remove sample.fetch_config no longer shipped upstream
+ * [fc163d] Update copyright for new upstream release
+ * [21c408] Add /usr/bin/radosgw-es to radosgw package
+ * [f63b2a] ceph-osd: sysctl config to increase the maximum number of AIO
+ requests
+ * [5f1f30] Remove static libraries from -dev packages (removed upstream)
+ * [1db168] Install ceph-detect-init into /usr/bin instead of /usr/sbin
+ * [1fb625] Move ceph-*-tool from ceph-test into daemon packages
+ * [6a5628] Remove obsolete X-Python-Version
+ * [c6fc4d] Update to Debian Policy version 4.2.1
+ * [5821f2] Set multiarch triplet in debian/rules
+ * [9bdce0] Remove override of dh_auto_install
+ * [b71c87] Add libceph-common to librados2 and librados-dev pkgs
+ * [c746ce] Override JSON license lintian warning (false positive, code
+ removed)
+ * [17d65c] Use dh_missing instead of dh_install --list-missing
+ * [cba40a] Remove obsolete ceph-create-keys@.service from ceph-base
+ * [252d62] Update watch file for https and repacking
+ * [ef84cf] Install ceph SysV init script with dh_install
+ * [0c2c84] Add missing source for jquery.flot.js (actually
+ jquery.colorhelpers.js)
+ * [0f1e2e] Add missing sources for JQuery in civetweb
+ * [8010cc] Add missing sources from AdminLTE
+ * [7c425a] Add lintian overrides for source-is-missing false positives
+ * [75f7d2] Update symbols files
+ * [aa7295] Patch to fix build failures with Boost 1.67
+ * [872887] Build with Debian packaged Boost 1.67 instead of bundled Boost 1.66
+ * [abf215] Use google-perftools on all supported architectures
+ * [44dd74] Add missing sources for the mgr dashboard plugin
+ * [39f9d6] Depend on ceph-common for pythonX-cephfs (Closes: #896400)
+ * [7a10f0] Improve autopkgtests
+ * [7515ca] Add Python dependency for ceph-fuse
+ * [d91a92] Make the ceph binary package a pure metapackage
+ * [df1dc8] Add Lintian overrides for systemd targets
+ * [bc7cd4] Install upstream rbdmap systemd service file
+ * [dd44ea] Remove RUNPATH from JNI libraries
+ * [7e9bce] Add dependency on junit4 and libcephfs-java for ceph-test
+ * [dfbe7c] Remove unnecessary ceph-base postrm script (Closes: #867465)
+ * [bad29d] Fix permissions on /var/run/ceph in SysV init script
+ (Closes: #869142)
+ * [6edc7a] Mark libraries as Multi-Arch compatible (Closes: #822740)
+
+ [ Thomas Goirand ]
+ * [46be6f] Change VCS links to point to Salsa
+
+ [ Shengjing Zhu ]
+ * [bfcf95] Don't treat rados-classes and ceph/compressor as shared libraries
+ * [0ef4f9] Add missing interpreter in ceph-{osd,mon}.postinst
+ (Closes: #862684, #862685)
+ * [f75bfc] Change section of libcephfs-jni from libs to java
+ * [f4b5d4] Add patch to fix various spelling errors
+ * [f60d21] Patch to remove link to ceph.com for dashboard favicon
+ * [116028] Backport test build fix from upstream
+ * [b83166] Change architecture of ceph-fuse to linux-any (from amd64)
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Sun, 28 Oct 2018 23:43:10 +0100
+
+ceph (12.2.4-0ubuntu1.1) bionic; urgency=medium
+
+ * d/p/update-java-source-target-flags.patch: Use --release instead
+ of -source/-target and set release to 7 as that is the minimum
+ required for OpenJDK 11 (LP: #1766998).
+ * d/p/replace-javah-usage.patch: call -h during compilation time to
+ generate native header files and remove the javah call as the binary
+ is no longer part of openjdk-10 - javah has been deprecated since
+ openjdk-9 (LP: #1766995).
+
+ -- Tiago Stürmer Daitx <tiago.daitx@ubuntu.com> Wed, 25 Apr 2018 01:45:34 +0000
+
+ceph (12.2.4-0ubuntu1) bionic; urgency=medium
+
+ [ James Page ]
+ * New upstream point release (LP: #1750826, #1731819, #1718134).
+ * d/ceph-osd.install: Add ceph-volume tools (LP: #1750376).
+ * d/*: wrap-and-sort -bast.
+ * d/control,compat: Bump debhelper compat level to 10.
+ * d/control: Switch to using python3-sphinx.
+ * d/rules: Switch to using WITH_BOOST_CONTEXT for rgw beast frontend
+ enablement.
+ * d/rules,control: Switch to using vendored boost as 1.66 is required.
+ * d/control: Add python-jinja2 to Depends of ceph-mgr (LP: #1752308).
+
+ [ Tiago Stürmer Daitx ]
+ * Update java source and target flags from 1.5 to 1.8. Allows it to run
+ using OpenJDK 8 or earlier and to be build with OpenJDK 9, 10, and 11
+ (LP: #1756854).
+
+ [ James Page ]
+ * d/ceph*.prerm: Drop, no longer needed as only use for removed upstart
+ and init.d methods of managing ceph daemons (LP: #1754585).
+
+ -- James Page <james.page@ubuntu.com> Tue, 20 Mar 2018 09:28:22 +0000
+
+ceph (12.2.2-0ubuntu2) bionic; urgency=medium
+
+ * d/control: Re-order Recommends to prefer chrony over time-daemon
+ (chrony/openntp) and ntp for Ubuntu (LP: #1744072).
+
+ -- Christian Ehrhardt <christian.ehrhardt@canonical.com> Fri, 16 Feb 2018 09:19:21 +0100
+
+ceph (12.2.2-0ubuntu1) bionic; urgency=medium
+
+ * New upstream point release (LP: #1739002).
+ - d/p/armhf-ftbfs.patch: Cherry pick upstream fix to resolve
+ FTBFS on armhf.
+
+ -- James Page <james.page@ubuntu.com> Wed, 20 Dec 2017 08:44:40 +0000
+
+ceph (12.2.1-0ubuntu1) bionic; urgency=medium
+
+ * New upstream point release (LP: #1728576).
+
+ -- James Page <james.page@ubuntu.com> Tue, 31 Oct 2017 09:13:22 +0000
+
+ceph (12.2.0-0ubuntu2) bionic; urgency=medium
+
+ * No-change rebuild for boost soname change.
+
+ -- Matthias Klose <doko@ubuntu.com> Thu, 26 Oct 2017 17:10:59 +0000
+
+ceph (12.2.0-0ubuntu1) artful; urgency=medium
+
+ * New upstream stable release.
+ * d/p/32bit-compat-service-daemon.patch: Dropped, accepted upstream.
+ * d/rules: Install ceph-volume systemd configuration.
+ * d/*.symbols: Refresh for new release.
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Wed, 30 Aug 2017 17:27:07 +0100
- -- Gary Lowell <gary.lowell@inktank.com> Mon, 03 Dec 2012 19:08:14 -0800
+ceph (12.1.2-0ubuntu2) artful; urgency=medium
-ceph (0.54-1) precise; urgency=low
+ * d/p/rocksdb-fallthrough-i386.patch: Mark intentional fallthroughs
+ for compatibility with gcc-7.
+ * d/p/32bit-compat-service-daemon.patch: Fix implicit type conversion
+ for Boost variant types on 32 bit architectures (LP: #1709396).
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Wed, 09 Aug 2017 16:43:46 +0100
- -- Gary Lowell <gary.lowell@inktank.com> Tue, 13 Nov 2012 13:17:19 -0800
+ceph (12.1.2-0ubuntu1) artful; urgency=medium
-ceph (0.53-1) precise; urgency=low
+ * New release candidate for next stable release.
+ * d/ceph-base.install: Increase scope of install wildcards to ensure
+ that all ceph modules are included in the binary package.
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Mon, 07 Aug 2017 14:23:59 +0100
- -- Gary Lowell <gary.lowell@inktank.com> Tue, 16 Oct 2012 17:40:46 +0000
+ceph (12.1.1-0ubuntu1) artful; urgency=medium
-ceph (0.52-1) precise; urgency=low
+ * New release candidate for next stable release.
+ * d/p/ec-isa-module.patch: Drop, included upstream.
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Wed, 26 Jul 2017 10:43:04 +0100
- -- Ubuntu <gary.lowell@inktank.com> Thu, 27 Sep 2012 16:16:52 +0000
+ceph (12.1.0-0ubuntu1) artful; urgency=medium
-ceph (0.51-1) experimental; urgency=low
+ * New release candidate for next stable release.
+ * Sync packaging changes with upstream:
+ - d/control,python3-*,rules: Add Python 3 support
+ - d/control,python-rgw.*: Add Python rgw module.
+ - d/control,ceph-mgr.*,rules: Add ceph-mgr binary packages.
+ - d/*.symbols: Update for new release.
+ - d/control,rules,*.install: Switch buildsystem to cmake.
+ - d/control,rados-objclass-dev.*: Add rados-objclass-dev
+ binary package.
+ - d/control,ceph-fs-common.install: Drop ceph-fs-common, fold
+ binaries into ceph-common.
+ - d/control,ceph-common.install: Move radosgw-admin to
+ ceph-common package.
+ - d/ceph-common.install: Install crypto modules on amd64 only.
+ - d/*: wrap-and-sort.
+ - d/p/*: Drop existing patches, either upstream or obsolete due
+ to switch to cmake build.
+ - d/control,rules: Drop use of dh-autoreconf.
+ * Use distro provided boost libraries:
+ - d/rules: Enable use of system boost instead of vendored copy.
+ - d/control: Add required boost dependencies >= 1.61.
+ * Support build on s390x:
+ - d/rules: Disable RGW Beast frontend on s390x architecture.
+ - d/control: Scope libboost-{context,coroutine}-dev to exclude
+ s390x.
+ * Support build on i386:
+ - d/p/0001-CoreLocalArray-class.patch,
+ d/p/0002-core-local-array-type-conversions.patch,
+ d/p/0003-Core-local-statistics.patch: Cherry pick rocksdb commits
+ to resolve compatibility with gcc-6 on i386.
+ * d/p/ec-isa-module.patch: Drop versioning of libec_isa.so to ensure
+ that it gets installed as part of the package.
+ * d/control,rules: Workaround arm64 compilation segfault by forcing
+ use of gcc-7 toolchain for this architecture.
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Fri, 07 Jul 2017 08:02:02 +0000
- -- Sage Weil <sage@newdream.net> Sat, 25 Aug 2012 15:58:23 -0700
+ceph (10.2.7-0ubuntu1) artful; urgency=medium
-ceph (0.50-1) experimental; urgency=low
+ * New upstream point release (LP: #1684527):
+ - d/p/disable-openssl-linking.patch: Dropped, no longer required.
+ - d/control: Add BD on libssl-dev to support optional runtime
+ loading of openssl in the radosgw.
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Fri, 21 Apr 2017 09:20:08 +0100
- -- Sage Weil <sage@newdream.net> Mon, 13 Aug 2012 09:44:40 -0700
+ceph (10.2.6-0ubuntu1) zesty; urgency=medium
-ceph (0.49-1) experimental; urgency=low
+ * New upstream stable point release (LP: #1671117):
+ - d/p/osd-limit-omap-data-in-push-op.patch,rgw_rados-creation_time.patch:
+ Dropped, included upstream.
+ - d/p/*: Refresh.
- * New upstream release
+ -- James Page <james.page@ubuntu.com> Thu, 09 Mar 2017 09:23:49 +0000
- -- Sage Weil <sage@newdream.net> Fri, 20 Jul 2012 23:26:43 -0700
+ceph (10.2.5-7.2) unstable; urgency=medium
-ceph (0.48argonaut-1) experimental; urgency=low
+ * Non-maintainer upload.
+ * Build with -g1 instead of -g on 32bit architectures to fix
+ FTBFS due to the 2GB/3GB address space limits.
- * New upstream release
+ -- Adrian Bunk <bunk@debian.org> Wed, 07 Jun 2017 11:39:39 +0300
+
+ceph (10.2.5-7.1) unstable; urgency=medium
+
+ * Non-maintainer upload.
+ * ceph-mon: Add Breaks+Replaces: ceph-common (<< 10) for taking over
+ /usr/bin/ceph-rest-api. (Closes: #864161)
+
+ -- Andreas Beckmann <anbe@debian.org> Tue, 06 Jun 2017 09:08:30 +0200
+
+ceph (10.2.5-7) unstable; urgency=medium
+
+ * [a12798] Add fix-init-system-detection.patch.
+ This replaces the static init system detection by more appropriate
+ runtime detection which also works if a Debian system is running with
+ sysvinit. (Closes: #862075)
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Fri, 12 May 2017 12:12:00 +0200
+
+ceph (10.2.5-6) unstable; urgency=medium
+
+ * [e44a30] Disable running dh_auto_install with parallel jobs
+ (Closes: #850906)
+ * [b7e926] Link with libatomic and --as-needed on all archs (Closes: #850831)
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Wed, 11 Jan 2017 12:02:24 +0100
+
+ceph (10.2.5-5) unstable; urgency=medium
+
+ * [f4675d] Set _FILE_OFFSET_BITS=64 via DEB_CPPFLAGS_MAINT_APPEND
+ * [f60392] Install systemd targets for ceph services (Closes: #850509)
+ * [d3baba] Link with -latomic on mips/mipsel
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Tue, 10 Jan 2017 09:04:48 +0100
+
+ceph (10.2.5-4) unstable; urgency=medium
+
+ * [88034c] Build with ggc-min-expand=5 on mips/el (Closes: #849657)
+ * [c31e79] Add patch to build rocksdb with -latomic on mips/el
+ * [182dd8] NEWS entry about upgrades from Debian Jessie
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Sun, 08 Jan 2017 21:34:21 +0100
+
+ceph (10.2.5-3) unstable; urgency=medium
+
+ * [eeff8d] Use -mfloat-abi=softfp on armel for NEON plugin (Closes: #849660)
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Thu, 05 Jan 2017 09:18:41 +0100
+
+ceph (10.2.5-2) unstable; urgency=medium
+
+ * [3859ca] Only list missing files instead of failing (Closes: #849031)
+ * [47aef7] Remove chrony from recommends (provides time-daemon)
+ (Closes: #827673)
+ * [3e96e6] Upstream fix for CVE-2016-9579 (short CORS request)
+ (Closes: #849048)
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Sat, 24 Dec 2016 13:14:28 +0100
+
+ceph (10.2.5-1) unstable; urgency=medium
+
+ [ James Page ]
+ * [754935] Imported Upstream version 9.2.0
+ - [df85c3] Resync relevant packaging changes with upstream.
+ - [be5f82] Refresh patches.
+ - [d1f3fe] Add python-setuptools to BD's for ceph-detect-init.
+ - [b2f926] Add lsb-release to BD's to ensure that python modules are
+ installed to correct locations.
+ - [e4d702] Add python-sphinx to BD's to ensure man pages get generated
+ and installed.
+ - [3ead6e] Correct install location for ceph-monstore-update tool.
+ - [269754] [177b7a] Update symbols for new release.
+ * [4c45629] Update NEWS file for infernalis changes.
+ * [940491e] Limit number of parallel builds to 2 to reduce memory footprint
+ on builders.
+ * [a2bed4] New upstream version 10.2.5
+ * [cbfb6b] Sync upstream changes around rbdmap install and conf files.
+ * [5c52b2] Drop patches include upstream, refresh remaining patches
+ * [8f9820] Resync further packaging changes from upstream.
+ * [27d010] Re-add bz2-dev BD.
+ * [e94aa2] Add python-dev to BD's.
+ * [e201c1] d/p/pybind-flags.patch: Ensure that cython *FLAGS are correctly
+ set.
+ * [14cd12] d/p/fix-systemd-escaping.patch: Ensure that leading '/' is stripped
+ from block device paths when escaping for use in systemd unit
+ names.
+ * [33b3aa] Add pull request for systemd fixes
+ * [d781a2] d/ceph-mds.postinst: Fix syntax error.
+ * [ce55ec] Ensure that python flags are correct set for cython rbd build.
+ * [f9e35b] Switch rbd python binding to cython
+ * [8ccae0] Drop ceph_volume_client until its actually in the codebase.
+ * [0a11cc] Install to relative, not absolute /etc/ceph.
+ * [e2415a] Drop ceph-bluefs-tool from ceph package.
+ * [b16966] d/ceph-mds.dirs: Actually create /var/lib/ceph/mds prior to
+ changing permissions (LP: #1544647).
+ * [0c1201] d/ceph.init: Restore link to init-ceph, resolving un-install
+ failures due to missing init script (LP: #1546112).
+
+ [ Gaudenz Steinlin ]
+ * [e3cb86] Remove no longer needed check for dh-autoreconf>=6
+ * [9157b3] Install ceph-brag tool into ceph-common
+ * [74e9f3] Install ceph-client-debug into ceph-test
+ * [476449] Use jh_installlib to install Java libraries
+ * [643f6e] Don't remove configure script on dh_clean
+ * [4bb203] Remove *.la files to binary packages
+ * [b76c6a] Add build dependency on libboost-iostreams-dev
+ * [b0506f] Add build dependency on libldap2-dev
+ * [526ce1] Refresh patches for upstream version 10.2.2
+ * [cf539b] Remove patches applied upstream in 10.2.2
+
+ [ James Page ]
+ * [646b48] Add librgw2 binary packages.
+ * [ae3cda] Drop virtualenv from BD's.
+ * [7ebd7c] Re-enable rocksdb build for bluestore support
+ * [e393e5] Add rbd-mirror package
+ * [00d06d] Add patch to set g++ flags correctly for rocksdb
+ * [3b029a] Enable gperftools on arm64 architecture.
+ * [e88620] Add ceph-bluefs-tool to install.
+ * [4f40a1] Add s390x to list of rocksdb flags
+ * [858334] d/p/skip-setup.py-makefiles.patch,rules: Avoid use of virtualenv to
+ install ceph-disk and ceph-detect-init python modules.
+ * [40c3b7] Update watch file to scan for gz files.
+ * [49b716] Install librgw_file* as part of ceph-test package.
+
+ [ Gaudenz Steinlin ]
+ * [2e156d] d/rules: Install upstart and systemd configurations for rbd-mirror.
+
+ [ James Page ]
+ * [ca0b07] d/copyright: Ensure that jerasure and gf-complete are not stripped
+ from the upstream release tarball.
+ * [eee861] d/p/disable-openssl-linking.patch: Disable build time linking with
+ OpenSSL due to licensing incompatibilities.
+ * [07d7a6] d/*.symbols: Add new symbols for RC.
+ * [2416f1] Fix multiarch paths for librgw
+ * [2da01d] d/rules: Ensure that dh_systemd_start does not insert maintainer
+ script snippets for ceph-mon and ceph-create-keys - service restart
+ should be handled outside of the packaging as it is under upstart
+ and for all other systemd unit files installed (LP: #1563330).
+ * [76ec3b] d/ceph-common.postinst: Silence output of usermod call
+ (LP: #1569249).
+ * [63d60f] d/rules,ceph-common.install: Ensure that /etc/default/ceph is a
+ file and not a directory (LP: #1587516).
+ * [a866ca] d/control: Bumped Standards-Version to 3.9.8, no changes.
+ * [e0811e] d/ceph.install: Drop install of 60-ceph-partuuid-workaround.rules
+ as no longer part of upstream codebase.
+ * [25954f] * d/*: Split ceph-osd and ceph-mon into separate binary packages
+ and add new ceph-base binary package inline with upstream packaging
+ changes (LP: #1596063).
+ * [f1287b] Add missing misc depends
+ * [afeb18] d/rules,control: Drop -dbg packages and let Ubuntu builds take care
+ of ddeb generation instead.
+
+ [ Gaudenz Steinlin ]
+ * [e133b2] Install rbdmap manpage into ceph-common
+ * [b5ed64] Install radosgw-token command into radosgw package
+ * [0a27e1] Adapt installation of Python files to latest Jewel release
+ * [ef2544] Drop rocksdb-flags patch applied upstream
+ * [07aef4] Add patch osd-limit-omap-data-in-push-op
+ * [32f14d] Refresh patches
+
+ [ James Page ]
+ * [f4e95c] Fix install location for mount.ceph
+ * [6a9efc] Update install location for mount.ceph.fuse
+ * [7624f0] d/control: Add Pre-Depends on ceph-common to ceph-osd to ensure
+ that ceph user and group are created prior to unpacking of udev
+ rules (LP: #1631328).
+
+ [ Frode Nordahl ]
+ * [022ee3] Add rgw_rados-creation_time patch
+
+ [ Gaudenz Steinlin ]
+ * [05225f] Remove old ceph logrotate configuration
+
+ [ James Page ]
+ * [cfa82f] Refresh patches
+
+ [ Gaudenz Steinlin ]
+ * [fdec5d] Remove upstart support
+ * [5966f0] Use new RSA key for ceph-post-file
+ * [3748b6] Only install ChangeLog as upstream changelog
+ * [aa1393] Install bash-completions to /usr
+ * [ab0a88] Dependency on lsb-base for initscripts
+ * [4d78b0] Disable radosgw SysV init script on systemd
+ * [ff4c87] Don't install python bytecode
+ * [3cbf5e] Add missing dependencies on python (ceph-osd, ceph-mon)
+ * [8c70df] Update symbols files (librados2 and librbd1)
+ * [e4f0c5] Add ${shlibs:Depends} on Python C extensions
+ * [936838] Allow setting the number of parallel jobs
+ * [e5aa0f] Remove Laszlo and add myself to uploaders
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Sat, 17 Dec 2016 22:40:22 +0100
+
+ceph (10.2.5-0ubuntu2) zesty; urgency=medium
+
+ * d/rules: Install upstream provided systemd targets and ensure they
+ are enabled and started on install to ensure that integrations aligned
+ to upstream packaging work with Ubuntu packages (LP: #1646583).
+ * d/rules,d/p/powerpc_libatomic.patch: Ensure linking with -latomic,
+ resolving FTBFS on powerpc architecture.
+
+ -- James Page <james.page@ubuntu.com> Tue, 17 Jan 2017 11:10:40 +0000
+
+ceph (10.2.5-0ubuntu1) zesty; urgency=medium
+
+ * New upstream stable release (LP: #1649856).
+ - d/p/32bit-ftbfs.patch: Drop, no longer needed.
+ - d/p/*: Refresh.
+ - d/ceph-common.install: Switch to RSA keys for drop.ceph.com.
+
+ -- James Page <james.page@ubuntu.com> Thu, 15 Dec 2016 07:51:11 +0000
+
+ceph (10.2.3-0ubuntu5) zesty; urgency=medium
+
+ * d/ceph.{postinst,preinst,postrm}: Ensure that ceph logrotate
+ configuration is purged on upgrade from pre-yakkety installs
+ (LP: #1635844).
+ * d/ceph-base.*,d/*.logrotate: Install logrotate configuration
+ in ceph-common, ensuring that all daemons get log rotation on
+ log files, deal with removal of logrotate configuration in
+ ceph-base for upgrades (LP: #1609866).
- -- Sage Weil <sage@newdream.net> Sat, 30 Jun 2012 14:49:30 -0700
+ -- James Page <james.page@ubuntu.com> Thu, 01 Dec 2016 08:54:21 +0000
-ceph (0.47.3-1) experimental; urgency=low
+ceph (10.2.3-0ubuntu4) zesty; urgency=high
- * New upstream release
+ * No change rebuild against boost1.62.
- -- Sage Weil <sage@newdream.net> Wed, 20 Jun 2012 10:57:03 -0700
+ -- Dimitri John Ledkov <xnox@ubuntu.com> Tue, 01 Nov 2016 16:12:26 +0000
-ceph (0.47.2-1) experimental; urgency=low
+ceph (10.2.3-0ubuntu3) zesty; urgency=medium
- * New upstream release
+ * rgw: Fixes for creation times for buckets (LP: #1587261).
+ - d/p/rgw_rados-creation_time.patch: Backport fix from upstream master.
+ - Fix logic error that leads to creation time being 0 instead of current
+ time when creating buckets.
- -- Sage Weil <sage@newdream.net> Wed, 23 May 2012 09:00:43 -0700
+ -- Frode Nordahl <frode.nordahl@canonical.com> Wed, 26 Oct 2016 14:39:55 +0200
-ceph (0.47.1-1) experimental; urgency=low
+ceph (10.2.3-0ubuntu2) yakkety; urgency=medium
- * New upstream release
+ * d/control: Add Pre-Depends on ceph-common to ceph-osd to ensure
+ that ceph user and group are created prior to unpacking of udev
+ rules (LP: #1631328).
+ * d/control: Drop surplus Recommends on ceph-common for ceph-mon, as
+ it already has a in-direct Depends via ceph-base.
- -- Sage Weil <sage@newdream.net> Mon, 21 May 2012 14:28:30 -0700
+ -- James Page <james.page@ubuntu.com> Sat, 08 Oct 2016 16:16:00 +0100
-ceph (0.47-1) experimental; urgency=low
+ceph (10.2.3-0ubuntu1) yakkety; urgency=medium
- * New upstream release
+ * New upstream point release (LP: #1628809):
+ - d/p/rocksdb-flags.patch: Dropped, included upstream.
+ - d/p/*: Refreshed.
+ - d/p/32bit-ftbfs.patch: Cherry pick fix for 32bit arch compat.
+ - d/ceph-{fs-common,fuse}.install: Fix install locations
+ for mount{.fuse}.ceph.
+ * Limit the amount of data per chunk in omap push operations to 64k,
+ ensuring that OSD threads don't hit timeouts during recovery
+ operations (LP: #1628750):
+ - d/p/osd-limit-omap-data-in-push-op.patch: Cherry pick fix from
+ upstream master branch.
- -- Sage Weil <sage@newdream.net> Sun, 20 May 2012 15:16:03 -0700
+ -- James Page <james.page@ubuntu.com> Thu, 29 Sep 2016 21:44:33 +0100
-ceph (0.46-1) experimental; urgency=low
+ceph (10.2.2-0ubuntu5) yakkety; urgency=medium
- * New upstream release
+ * No-change rebuild for boost soname change.
- -- Sage Weil <sage@newdream.net> Sun, 29 Apr 2012 21:21:01 -0700
+ -- Matthias Klose <doko@ubuntu.com> Thu, 04 Aug 2016 08:13:41 +0000
-ceph (0.45-1) experimental; urgency=low
+ceph (10.2.2-0ubuntu4) yakkety; urgency=medium
- * New upstream release
+ * d/rules: Drop override_dh_strip from .PHONY to ensure files actually
+ get stripped.
- -- Sage Weil <sage@newdream.net> Tue, 10 Apr 2012 10:41:57 -0700
+ -- James Page <james.page@ubuntu.com> Wed, 20 Jul 2016 09:26:41 +0100
-ceph (0.44.2-1) experimental; urgency=low
+ceph (10.2.2-0ubuntu3) yakkety; urgency=medium
- * New upstream release
+ * d/rules,control: Drop -dbg packages and let Ubuntu builds take care of
+ ddeb generation instead.
+ * d/ceph-mon.install: Only install .py files for ceph_rest_api module.
- -- Sage Weil <sage@newdream.net> Thu, 05 Apr 2012 14:54:17 -0700
+ -- James Page <james.page@ubuntu.com> Tue, 19 Jul 2016 10:36:32 +0100
-ceph (0.44.1-1) experimental; urgency=low
+ceph (10.2.2-0ubuntu2) yakkety; urgency=medium
- * New upstream release
+ * d/ceph.install,d/etc/*: Drop pm based power management scripts as they
+ are not used under systemd (LP: #1455097).
+ * d/*: Split ceph-osd and ceph-mon into separate binary packages and add
+ new ceph-base binary package inline with upstream packaging changes
+ (LP: #1596063).
+ * d/rules,*.{postinst,prerm}: Drop install and management of upstart
+ configuration files; this package version onwards will only ever
+ target >= Xenial, which is a systemd baseline.
- -- Sage Weil <sage@newdream.net> Tue, 27 Mar 2012 13:02:00 -0700
+ -- James Page <james.page@ubuntu.com> Thu, 14 Jul 2016 10:51:10 +0100
-ceph (0.44-1) experimental; urgency=low
+ceph (10.2.2-0ubuntu1) yakkety; urgency=medium
- * New upstream release
+ * New upstream version (LP: #1585660):
+ - d/ceph.install: Drop install of 60-ceph-partuuid-workaround.rules
+ as no longer part of upstream codebase.
+ * d/control: Bumped Standards-Version to 3.9.8, no changes.
- -- Sage Weil <sage@newdream.net> Sun, 18 Mar 2012 12:03:38 -0700
+ -- James Page <james.page@ubuntu.com> Thu, 16 Jun 2016 17:40:04 +0100
-ceph (0.43-1) experimental; urgency=low
+ceph (10.2.1-0ubuntu2) yakkety; urgency=medium
- * New upstream release
+ * d/ceph-common.{preinst,postinst,postrm}: Ensure that rename of
+ /etc/default/ceph/ceph -> /etc/default/ceph is handled correctly
+ and that any end-user changes are preserved (LP: #1587516).
- -- Sage Weil <sage@newdream.net> Fri, 02 Mar 2012 08:53:10 -0800
+ -- James Page <james.page@ubuntu.com> Mon, 13 Jun 2016 20:53:52 +0100
-ceph (0.42.2-1) experimental; urgency=low
+ceph (10.2.1-0ubuntu1) yakkety; urgency=medium
- * New upstream release
+ * New upstream version (LP: #1585660).
+ - d/p/drop-user-group-osd-prestart.patch: Dropped, included upstream.
+ * d/rules,ceph-common.install: Ensure that /etc/default/ceph is a file
+ and not a directory (LP: #1587516).
- -- Sage Weil <sage@newdream.net> Fri, 24 Feb 2012 12:59:38 -0800
+ -- James Page <james.page@ubuntu.com> Mon, 06 Jun 2016 09:23:35 +0100
-ceph (0.42.1-1) experimental; urgency=low
+ceph (10.2.0-0ubuntu1) yakkety; urgency=medium
- * New upstream release
+ * Ceph Jewel stable release (LP: #1569249).
- -- Sage Weil <sage@newdream.net> Thu, 23 Feb 2012 18:46:23 -0800
+ -- James Page <james.page@ubuntu.com> Thu, 21 Apr 2016 19:54:54 +0100
-ceph (0.42-1) experimental; urgency=low
+ceph (10.1.2-0ubuntu1) xenial; urgency=medium
- * New upstream release
+ * New upstream release candidate for Ceph Jewel:
+ - FFe: http://pad.lv/1563714.
+ - d/p/32bit-compat.patch,tasksmax-infinity.patch: Dropped,
+ included upstream.
+ * d/ceph-common.postinst: Silence output of usermod call (LP: #1569249).
- -- Sage Weil <sage@newdream.net> Sun, 19 Feb 2012 15:30:20 -0800
+ -- James Page <james.page@ubuntu.com> Thu, 14 Apr 2016 14:46:58 +0100
-ceph (0.41-1) experimental; urgency=low
+ceph (10.1.1-0ubuntu1) xenial; urgency=medium
- * New upstream release
+ * New upstream release candidate for Ceph Jewel:
+ - FFe: http://pad.lv/1563714.
+ - d/p/*: Refresh.
- -- Sage Weil <sage@newdream.net> Fri, 27 Jan 2012 10:42:11 -0800
+ -- James Page <james.page@ubuntu.com> Fri, 08 Apr 2016 16:30:43 +0100
-ceph (0.40-1) experimental; urgency=low
+ceph (10.1.0-0ubuntu1) xenial; urgency=medium
- * New upstream release
+ * New upstream release candidate for Ceph Jewel
+ (see http://pad.lv/1563714 for FFe):
+ - d/control,rules,librgw*: Add new binary packages for librgw2.
+ - d/p/fix-systemd-escaping.patch,pybind-flags.patch: Dropped,
+ included upstream.
+ - d/p/*: Refresh remaining patches.
+ - d/control: Add BD on libldap2-dev for rados gateway.
+ - d/p/disable-openssl-linking.patch: Disable build time linking
+ with OpenSSL due to licensing incompatibilities.
+ - d/*.symbols: Add new symbols for RC.
+ - d/python-*.install: Correct wildcards for python module install.
+ - d/p/32bit-compat.patch: Cherry pick upstream fix for 32 bit
+ compatibility, resolving FTBFS on armhf/i386.
+ * d/rules: Strip rbd-mirror package correctly.
+ * d/rules: Install upstart and systemd configurations for rbd-mirror.
+ * d/copyright: Ensure that jerasure and gf-complete are not stripped
+ from the upstream release tarball.
+ * d/p/drop-user-group-osd-prestart.patch: Drop --setuser/--setgroup
+ arguments from call to ceph-osd-prestart.sh; they are not supported
+ and generate spurious non-fatal warning messages (LP: #1557461).
+ * d/p/tasksmax-infinity.patch: Drop systemd limitation of number of
+ processes and threads to long running ceph processes; the default
+ of 512 tasks is way to low for even a modest Ceph cluster
+ (LP: #1564917).
+ * d/rules: Ensure that dh_systemd_start does not insert maintainer
+ script snippets for ceph-mon and ceph-create-keys - service restart
+ should be handled outside of the packaging as it is under upstart
+ and for all other systemd unit files installed (LP: #1563330).
- -- Sage Weil <sage@newdream.net> Fri, 13 Jan 2012 08:36:02 -0800
+ -- James Page <james.page@ubuntu.com> Wed, 06 Apr 2016 09:17:59 +0100
-ceph (0.39-1) experimental; urgency=low
+ceph (10.0.5-0ubuntu1) xenial; urgency=medium
- * New upstream release
+ * New upstream point release, in preparation for Ceph Jewel.
+ - d/p/*: Refresh patches
+ - d/control: Enable rbd-mirror(-dbg) packages.
+ - d/control: Add BD on libboost-iostreams-dev.
+ - d/p/skip-setup.py-makefiles.patch,rules: Avoid use of virtualenv
+ to install ceph-disk and ceph-detect-init python modules.
- -- Sage Weil <sage@newdream.net> Fri, 02 Dec 2011 09:01:20 -0800
+ -- James Page <james.page@ubuntu.com> Wed, 23 Mar 2016 14:07:58 +0000
-ceph (0.38-1) experimental; urgency=low
+ceph (10.0.3-0ubuntu1) xenial; urgency=medium
- * New upstream release
+ * New upstream point release, in preparation for Ceph Jewel.
+ - d/p/*: Refresh patches
+ - d/rules,d/p/rocksdb-flags.patch: Enable rocksdb build for
+ experimental bluestore support, add patch to set g++ flags
+ correctly across all Ubuntu archs.
+ - d/rules: Enable gperftools use on arm64 architecture.
+ - d/ceph.install: Add ceph-bluefs-tool to install.
+ * d/*: wrap-and-sort.
- -- Sage Weil <sage@newdream.net> Thu, 10 Nov 2011 15:06:44 -0800
+ -- James Page <james.page@ubuntu.com> Fri, 18 Mar 2016 10:41:37 +0000
-ceph (0.37-1) experimental; urgency=low
+ceph (10.0.2-0ubuntu1) xenial; urgency=medium
- * New upstream release
+ * New upstream release, in preparation for Ceph Jewel stable release:
+ - d/control: Add python-dev to BD's.
+ - d/p/pybind-flags.patch: Ensure that python flags are correct
+ set for cython rbd build.
+ - d/python-rbd.install: Switch rbd python binding to cython.
+ - d/p/modules.patch: Dropped, no longer required as upstream.
+ - d/control,rbd-nbd.*,rules: Add rbd-nbd package.
+ - d/p/*: Tidy old redundant patches.
- -- Sage Weil <sage@newdream.net> Mon, 17 Oct 2011 08:35:42 -0700
+ -- James Page <james.page@ubuntu.com> Thu, 18 Feb 2016 08:07:30 +0000
-ceph (0.36-1) experimental; urgency=low
+ceph (9.2.0-0ubuntu6) xenial; urgency=medium
- * New upstream release
+ * d/ceph-mds.dirs: Actually create /var/lib/ceph/mds prior to changing
+ permissions (LP: #1544647).
+ * d/ceph.init: Restore link to init-ceph, resolving un-install failures
+ due to missing init script (LP: #1546112).
+
+ -- James Page <james.page@ubuntu.com> Wed, 17 Feb 2016 10:33:24 +0000
+
+ceph (9.2.0-0ubuntu5) xenial; urgency=medium
+
+ [ guessi ]
+ * d/ceph-mds.postinst: Fixup syntax error (LP: #1544647).
+
+ -- James Page <james.page@ubuntu.com> Tue, 16 Feb 2016 12:54:16 +0000
+
+ceph (9.2.0-0ubuntu4) xenial; urgency=medium
+
+ * d/p/fix-systemd-escaping.patch: Ensure that leading '/' is stripped
+ from block device paths when escaping for use in systemd unit
+ names.
+
+ -- James Page <james.page@ubuntu.com> Tue, 09 Feb 2016 11:03:03 +0000
+
+ceph (9.2.0-0ubuntu3) xenial; urgency=medium
+
+ * d/ceph{-common}.install: Move ceph_daemon module to common package
+ as its required to use the ceph command.
+ * d/rules: Disable parallel builds on arm64, resolving FTBFS due to
+ memory constraints in builders.
+
+ -- James Page <james.page@ubuntu.com> Fri, 15 Jan 2016 10:00:47 +0200
+
+ceph (9.2.0-0ubuntu2) xenial; urgency=medium
+
+ * d/control: Fixup broken Breaks/Replaces for backports to 14.04.
+
+ -- James Page <james.page@ubuntu.com> Wed, 06 Jan 2016 10:46:19 +0000
+
+ceph (9.2.0-0ubuntu1) xenial; urgency=medium
+
+ * [754935] Imported Upstream version 9.2.0
+ - [df85c3] Resync relevant packaging changes with upstream.
+ - [be5f82] Refresh patches.
+ - [d1f3fe] Add python-setuptools to BD's for ceph-detect-init.
+ - [b2f926] Add lsb-release to BD's to ensure that python modules are
+ installed to correct locations.
+ - [e4d702] Add python-sphinx to BD's to ensure man pages get generated
+ and installed.
+ - [3ead6e] Correct install location for ceph-monstore-update tool.
+ - [269754] [177b7a] Update symbols for new release.
+ * [6f322e5] Imported Upstream version 10.0.2
+ - [ba06deb] Add python-dev to BD's.
+ - [62c26dc] d/p/fix-systemd-escaping.patch: Ensure that leading '/' is
+ stripped from block device paths when escaping for use in
+ systemd unit names.
+ - [e02b2a1] d/p/pybind-flags.patch: Ensure that python flags are correct
+ set for cython rbd build.
+ - [d9dad09] Switch rbd python binding to cython
+ * [4c45629] Update NEWS file for infernalis changes.
+ * [940491e] Limit number of parallel builds to 2 to reduce memory footprint
+ on builders.
+ * [23e78f3] d/ceph-mds.postinst: Fix syntax error.
+ * [26182b5] d/ceph-mds.dirs: Actually create /var/lib/ceph/mds prior
+ to changing permissions (LP: #1544647).
+ * [414f4c1] d/ceph.init: Restore link to init-ceph, resolving un-install
+ failures due to missing init script (LP: #1546112).
+
+ -- James Page <james.page@ubuntu.com> Wed, 09 Dec 2015 18:02:30 +0000
+
+ceph (0.94.5-1) experimental; urgency=medium
+
+ * [2d330d6] New upstream release:
+ - [1e93090] Drop patch for CVE-2015-5245, included upstream.
+ - [20adc7d] Refresh all other patches.
+ * [9255e5d] Ensure any erasure coding test libraries and dangling symlinks
+ are not included in the ceph package.
+
+ -- James Page <james.page@ubuntu.com> Mon, 09 Nov 2015 12:09:51 +0000
+
+ceph (0.94.3-1) experimental; urgency=medium
+
+ * [580fef] Imported Upstream version 0.94.3 (Closes: #777814, #795178)
+ * [536935] Add upstream patch to fix CVE-2015-5245 (Closes: #798567)
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Fri, 18 Sep 2015 16:55:23 +0200
+
+ceph (0.94.2-2) experimental; urgency=medium
+
+ * Revert "Drop virtualenv BD, disable unit tests."
+ * Restore patches for test enablement.
+ * Display test-suite log output in the event of failures.
+
+ -- James Page <james.page@ubuntu.com> Mon, 20 Jul 2015 13:37:06 +0100
+
+ceph (0.94.2-1) experimental; urgency=medium
+
+ * Resync with Ubuntu, introducing Ceph Hammer stable release:
+ - d/*.symbols: Update inline with upstream additions, use regex
+ for ceph version symbol.
+ - d/lib-systemd/system/ceph-create-keys.service: Automatically create
+ admin and bootstrap keys after ceph mon startup.
+ - d/p/vivid-does-systemd.patch: Ensure that disks prepared on vivid
+ or later use systemd for init.
+ - d/lib-systemd/system/*.service: Align nofile limits and restart config
+ with equivalent upstart configurations.
+ - d/p/fix-cycles-arch.patch: Skip initialization of cycles_per_sec
+ if rtdsc (or equivalent) is not supported.
+ - d/ceph{-common}.install,control: Move ceph_argparse.py down into
+ ceph-common package to fixup ceph cli usage/autopkgtest failure.
+ - d/control,ceph-common.install,librbd1.install: Move rbdnamer and
+ associated udev rules into ceph-common package.
+ - d/control,python-*: Split out rbd, rados and cephfs bindings into
+ separate python packages, move some bits into ceph/ceph-common.
+ - d/control: Move python-flask dependency to ceph package, only required
+ for REST API.
+ - d/control: Use google-perftools on arm64.
+ - d/control: Re-order Recommends to prefer ntp over chrony for Ubuntu.
+ - d/p/ceph-osd-prestart-path.patch: Fixup path for ceph-osd upstart
+ configuration pre-start script.
+ - d/p/fix-argparse-defaults.patch: Workaround behavioural change in
+ argparse set_defaults in python 2.7.9
+ * New upstream point release:
+ - d/p/*: Refresh.
+ * d/p/use_system_jerasure.patch,d/control: Drop use of libjerasure
+ as the patch is intrusive and expensive to maintain; will revisit if
+ adopted upstream.
+
+ -- James Page <james.page@ubuntu.com> Tue, 16 Jun 2015 11:31:05 +0100
+
+ceph (0.87-2) experimental; urgency=low
+
+ * Team upload.
+
+ [ Gaudenz Steinlin ]
+ * README.Debian: added clarification about setting the hashpspool flag.
+ (Closes: #769596).
+
+ [ James Page ]
+ * Added new "modules.patch" to mark new erasure coding libraries as
+ modules, wildcard install.
+
+ [ Dmitry Smirnov ]
+ * Recommends: added "ntp" to list of time-daemon alternatives
+ (Closes: #767511).
+ * Introduced native systemd services (except "rbdmap"), (Closes: #769593).
+ * ceph-test: install forgotten files.
+ * Run post-build tests:
+ + updated "virtualenv-never-download.patch" to pass
+ "--system-site-packages" to virtualenv to prevent downloads.
+ + added new patches to disable network-dependent and failing tests.
+ * Patchworks:
+ - bug-9341.patch
+ + bug-10036.patch (to show OSD affinity in "ceph osd tree").
+ Thanks, Mykola Golub.
+ + bug-10059.patch
+ + 0latest-giant.patch (Last-Update: 2014-11-15).
+ + sleep-recover.patch
+ + tests-disable.patch (to disable tests that need cluster).
+ + tests-disable-ceph-disk.patch
+ + use_system_gtest.patch (commented)
+ as first attempt to build with system "libgtest-dev".
+ + use_system_jerasure.patch
+ * Build-Depends:
+ + libjerasure-dev (>= 2.0.0-2~)
+ + virtualenv
+ + valgrind [amd64 armhf i386 powerpc]
+ * rules: pass "--without-lttng" to explicitly disable "lttng" to avoid
+ auto-enable if found.
+ * rules: disabled bundled RocksDB:
+ RocksDB suppose to improve performance of keyvaluestore OSDs but the
+ latter slow down to nearly unusable state when filled over 1 TiB even with
+ RocksDB. Moreover KV backend is experimental and super dangerous -- I lost
+ cluster due to OSD poisoning caused by KV OSD which was plugged only
+ during limited time. LevelDB is good enough, for now I see no reason to
+ use RocksDB especially considering that it is not packaged separately.
+ * Removed myself from Uploaders.
+
+ -- Dmitry Smirnov <onlyjob@debian.org> Wed, 01 Apr 2015 11:47:38 +1100
+
+ceph (0.87-1) experimental; urgency=medium
+
+ * New major upstream release [October 2014].
+ + new "libradosstriper*" binary packages.
+ * Patchworks (removed old patches, refreshed remaining ones).
+ + "bug-9814.patch" to prevent OSD crash. Thanks, Haomai Wang.
+ * Install systemd sleep handler.
+ * Exclude erasure-code plugins from `dh_makeshlibs` processing to avoid
+ useless calls to `ldconfig` in maintainer scripts.
+ * Build-Depends:
+ + libbabeltrace-dev
+ + libbabeltrace-ctf-dev
+ + libbz2-dev
+ + libudev-dev
+ + zlib1g-dev
+ * Build with "--with-babeltrace".
+ * Build and statically link bundled RocksDB.
+
+ -- Dmitry Smirnov <onlyjob@debian.org> Thu, 30 Oct 2014 12:43:49 +1100
+
+ceph (0.80.9-2) unstable; urgency=medium
+
+ * [70fc1d] Add NEWS entry about CRUSH issues fixed in 0.80.9
+ * [f41bb6] Add NEWS entry about rbd backed filesystems and systemd
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Tue, 05 May 2015 21:29:15 +0200
+
+ceph (0.80.9-1) unstable; urgency=medium
+
+ * [4b4e] Imported Upstream version 0.80.9
+ * [7102] Remove patches firefly-latest and p2139 applied upstream
+ * [5869] Add myself to uploaders
+
+ -- Gaudenz Steinlin <gaudenz@debian.org> Mon, 04 May 2015 08:49:37 +0200
+
+ceph (0.80.7-2) unstable; urgency=medium
+
+ * Team upload.
+ * Build-Depends: +libjerasure-dev (>= 2.0.0-2~)
+ * New patch to use system "jerasure" library instead of its bundled copy.
+ * Removed myself from Uploaders.
- -- Sage Weil <sage@newdream.net> Fri, 30 Sep 2011 09:29:29 -0700
+ -- Dmitry Smirnov <onlyjob@debian.org> Thu, 11 Dec 2014 12:55:38 +1100
-ceph (0.35-1) experimental; urgency=low
+ceph (0.80.7-1) unstable; urgency=medium
- * New upstream release
+ * New upstream release [October 2014].
+ * Minor update to long description of "rbd-fuse" (Closes: #765462).
- -- Sage Weil <sage@newdream.net> Wed, 21 Sep 2011 09:36:03 -0700
+ -- Dmitry Smirnov <onlyjob@debian.org> Thu, 16 Oct 2014 04:36:23 +1100
-ceph (0.34-1) experimental; urgency=low
+ceph (0.80.6-1) unstable; urgency=medium
+
+ * New upstream release [October 2014].
+ * Standards-Version: 3.9.6.
+
+ -- Dmitry Smirnov <onlyjob@debian.org> Thu, 02 Oct 2014 23:07:04 +1000
+
+ceph (0.80.5-2) unstable; urgency=low
+
+ * Patchworks:
+ + new patch for Ceph#9341 to dramatically (e.g seconds instead of
+ hours) reduce rejoin (i.e. MDS restart) time (fuse clients).
+ + new "p2139.patch".
+ + new patch with fixes from Firefly HEAD;
+ includes patch to fix FTBFS on alpha (Closes: #756892).
+ updated "librbd1.symbols";
+ * Build-Depends: mark "yasm" as [amd64] (Closes: #760383).
+ * Recommends: + "time-daemon | chrony".
+
+ -- Dmitry Smirnov <onlyjob@debian.org> Tue, 16 Sep 2014 03:54:15 +1000
- * New upstream release
+ceph (0.80.5-1) unstable; urgency=medium
- -- Sage Weil <sage@newdream.net> Fri, 26 Aug 2011 21:48:35 -0700
+ * New upstream stable release:
+ - d/p/firefly-post-release.patch: Dropped, no longer required.
+ - d/lib{rados2,cephfs1}.symbols: Update with new symbols.
-ceph (0.33-1) experimental; urgency=low
+ -- James Page <jamespage@debian.org> Wed, 30 Jul 2014 10:15:40 +0100
- * New upstream release.
+ceph (0.80.4-1) unstable; urgency=medium
- -- Sage Weil <sage@newdream.net> Mon, 15 Aug 2011 16:42:07 -0700
+ * New upstream release [July 2014].
+ * New patches:
+ + rbdmap1-mount.patch
+ + rbdmap2-hooks.patch
+ + rbdmap3-lazyumount.patch
+ + bug-8821.patch
+ * radosgw: removed unused lintian overrides.
-ceph (0.32-1) experimental; urgency=low
+ -- Dmitry Smirnov <onlyjob@debian.org> Fri, 18 Jul 2014 02:33:39 +1000
- * New upstream release
+ceph (0.80.1-2) unstable; urgency=low
- -- Sage Weil <sage@newdream.net> Fri, 29 Jul 2011 21:42:08 -0700
+ * Megapatch from "firefly" branch with post-0.80.1 fixes.
+ * Patches for upstream bugs 8342, 8624 and some cherry-picks.
+ * New "bash-completion.patch" with Bash completion improvements.
+ * New patch to fix FTBFS on 'hppa' (Closes: #748571).
+ * "sample.ceph.conf.patch": minor update.
-ceph (0.30-1) experimental; urgency=low
+ -- Dmitry Smirnov <onlyjob@debian.org> Sat, 05 Jul 2014 20:29:44 +1000
- * New upstream release
+ceph (0.80.1-1) unstable; urgency=low
- -- Sage Weil <sage@newdream.net> Mon, 27 Jun 2011 20:06:06 -0700
+ * New upstream release [May 2014].
+ * Dropped all backported patches.
+ * New "sleep-recover" and "client-sleep[1,2,3]" patches to fix
+ fuse-client hang after resume from suspend [#8291]; thanks, Zheng Yan.
+ * New "gcj_search_path.patch" to find "jni.h" with gcj-jdk v4.9.0.
-ceph (0.29.1-1) experimental; urgency=low
+ -- Dmitry Smirnov <onlyjob@debian.org> Wed, 14 May 2014 09:24:15 +1000
- * New upstream release
+ceph (0.80-1) unstable; urgency=low
- -- Sage Weil <sage@newdream.net> Thu, 16 Jun 2011 13:10:47 -0700
+ * New upstream release [May 2014].
+ + upload to unstable.
+ * Updated "README.Debian".
+ * Updated "debian/copyright"; Thanks, László Böszörményi.
+ * Added backported patches:
+ [8113, 8175, 8282, 8291, bp0001, sample.ceph.conf].
+ * "gbp.conf": don't merge to experimental.
+ * lintian-overrides: spelling-error-in-binary * tEH the.
-ceph (0.29-1) experimental; urgency=low
+ -- Dmitry Smirnov <onlyjob@debian.org> Wed, 07 May 2014 16:43:07 +1000
- * New upstream release
+ceph (0.80~rc1-1) experimental; urgency=low
- -- Sage Weil <sage@newdream.net> Mon, 06 Jun 2011 09:59:25 -0700
+ * New upstream pre-release.
+ * Minor re-factoring of udev rules installation.
+ * ceph-common: added ceph-crush-location.1 man page.
+ * ceph-test-dbg: fixed Depends.
-ceph (0.28.2-1) experimental; urgency=low
+ -- Dmitry Smirnov <onlyjob@debian.org> Thu, 24 Apr 2014 02:52:12 +1000
- * New upstream release.
+ceph (0.79-3) experimental; urgency=low
- -- Sage Weil <sage@newdream.net> Sat, 28 May 2011 09:14:17 -0700
+ * New "arch.patch" to detect build architecture using dpkg-architecture.
+ * Mark amd64-only symbols as such.
+ * Minor rules cleanup.
-ceph (0.28.1-1) experimental; urgency=low
+ -- Dmitry Smirnov <onlyjob@debian.org> Sat, 19 Apr 2014 15:56:37 +1000
- * New upstream release.
+ceph (0.79-2) experimental; urgency=low
- -- Sage Weil <sage@newdream.net> Mon, 23 May 2011 21:11:30 -0700
+ [ James Page ]
+ * d/p/modules.patch,d/ceph.install: Mark all jerasure plugins as modules
+ and ensure they are all installed.
-ceph (0.28-1) experimental; urgency=low
+ [ Dmitry Smirnov ]
+ * Patchworks:
+ - removed unused "defaults-leveldb-osd.patch".
+ + improved description of "modules.patch". Thanks, James Page.
+ + added new backported patches [#5469, #8008, _1606, spelling].
+ * Added .symbols and "dh_makeshlibs -V" shlibs tightening (Closes: #744382).
+ * README.Debian: added note regarding kernel client mount option.
+ * copyright: added license for man files.
+ * control: "Suggests: logrotate".
- * New upstream release.
+ -- Dmitry Smirnov <onlyjob@debian.org> Fri, 18 Apr 2014 18:27:01 +1000
- -- Sage Weil <sage@newdream.net> Tue, 17 May 2011 18:03:11 -0700
+ceph (0.79-1) experimental; urgency=low
-ceph (0.27.1-1) experimental; urgency=low
+ * New upstream release [April 2014].
+ * Tighten dependency on ceph-common.
+ * Install pm-suspend handler to stop/start ceph services on suspend/resume.
+ * New (inactive) patch to bump OSD's leveldb defaults.
+ * Patches dropped (applied-upstream):
+ - init.patch
+ - logrotate.patch
+ - fix-defaultweight.patch
+ * Refreshed "modules.patch".
- * New upstream release.
+ -- Dmitry Smirnov <onlyjob@debian.org> Tue, 08 Apr 2014 16:52:04 +1000
- -- Sage Weil <sage@newdream.net> Thu, 05 May 2011 13:42:06 -0700
+ceph (0.78-2) experimental; urgency=low
-ceph (0.27-1) experimental; urgency=low
+ * Standards to 3.9.5.
+ * debian/copyright: reviewed and updated.
+ * ceph-test: added lintian-override for "binary-without-manpage".
+ * Patchworks:
+ + refreshed/renamed/reordered "virtualenv-never-download.patch".
+ + new "init.patch" for init.d scripts lintianisation.
+ + new "logrotate.patch" to avoid rotating empty logs.
+ + new "fix-defaultweight.patch" to fix weight calculation on OSD start.
+ + new "gcj.patch" with partial fix to FTBFS with gcj-jdk.
+ * Use symlinks to simplify installation of init.d and logrotate scripts.
+ * Added retrospective changelog entry to mention new B-D "libblkid-dev".
+ * Added "debian/clean file".
+ * Added "README.Debian" file with some hopefully useful notes.
+ * Added "mount.fuse.ceph.8" man page.
+ * rules:
+ + "dh --with" optimised.
+ + set JAVAC to prevent FTBFS due to incorrect use of 'gcj', when detected.
+ + verbose mode for 'cp' and 'rm' commands.
+ + build with "--as-needed" to minimise needless linking.
+ * control:
+ + lintian/duplicate-short-description + consistent capitalisation.
+ + removed needless versioned dependencies from Build-Depends.
+ + added myself to Uploaders.
- * New upstream release.
+ -- Dmitry Smirnov <onlyjob@debian.org> Tue, 25 Mar 2014 07:17:40 +1100
- -- Sage Weil <sage@newdream.net> Fri, 22 Apr 2011 16:51:49 -0700
+ceph (0.78-1) experimental; urgency=medium
+
+ * New upstream release:
+ - d/control: Add "xfslib-dev" and "libblkid-dev" to BD's.
+ - d/*: Sync relevant packaging changes from upstream.
+ - d/p/*: Drop upstreamed patches.
+ - d/p/modules.patch: Mark libcls_user.so and libec_jerasure.so as modules.
+ - d/ceph.install: Only install libec_jerasure.so.
+ * d/ceph-test.install: Install test binaries to /usr/lib/ceph/bin; they
+ really don't need to be installed on the default path.
+ * d/{ceph|radosgw|ceph-mds}.lintian-overrides: Add overrides for intentional
+ difference in naming and structure between upstart configurations and
+ init.d scripts.
+
+ -- James Page <james.page@ubuntu.com> Sat, 22 Mar 2014 18:27:40 +0000
+
+ceph (0.72.2-3) unstable; urgency=medium
+
+ * Team upload.
-ceph (0.26-1) experimental; urgency=low
+ [ James Page ]
+ * d/ceph-test.install: Install test binaries to /usr/lib/ceph/bin; they
+ really don't need to be installed on the default path.
+
+ [ Dmitry Smirnov ]
+ * Tightened shlibs with "dh_makeshlibs -V" (Closes: #679686).
+
+ -- Dmitry Smirnov <onlyjob@debian.org> Mon, 14 Apr 2014 17:28:20 +1000
+
+ceph (0.72.2-2) unstable; urgency=medium
+
+ * d/radosgw.{postinst,postrm,preinst}: Handle renaming of radosgw
+ upstart configuration on upgrade@0.72.1-3.
+ * d/{ceph|ceph-mds|radosgw}.{postinst|prerm}: Check to ensure that system
+ is running upstart before trying to start/stop upstart configurations
+ (Closes: #734241, #738845, #738845).
+
+ -- James Page <jamespage@debian.org> Sat, 08 Mar 2014 16:48:28 +0000
+
+ceph (0.72.2-1) unstable; urgency=medium
* New upstream release.
- * Make Ceph Linux only and build on all Linux archs (closes: #614890),
- but only build-depend google-perftools on x86 and x64 archs only.
- * Correct section of libcrush1, librados1, librbd1 and libceph1 to libs.
- * Make Ceph cross buildable (closes: #618939), thanks to Hector Oron.
- * Disable libatomic-ops on ARMv4t (armel) archs to prevent FTBFS
- (closes: #615235), thanks go to Hector Oron again.
- * Rename librados1{,-dbg,-dev} packages to librados2{,-dbg,-dev} ones;
- conflict with and replace the former ones.
- -- Laszlo Boszormenyi (GCS) <gcs@debian.hu> Fri, 01 Apr 2011 16:28:11 +0100
+ -- James Page <james.page@ubuntu.com> Wed, 01 Jan 2014 09:32:03 +0000
+
+ceph (0.72.1-3) unstable; urgency=low
+
+ * d/rules,ceph.install: Correct install paths for ceph-* helpers.
+ * d/p/modules: Mark libcls_kvs.so as module.
+ * d/rules: Rename radosgw upstart configuration to radosgw-instance to
+ avoid namespace conflict with init script which breaks backwards
+ compatibility (LP: #1255464).
+
+ -- James Page <james.page@ubuntu.com> Wed, 27 Nov 2013 10:52:48 +0000
+
+ceph (0.72.1-2) unstable; urgency=low
+
+ * Fix upgrade failures from ceph < 0.67.3-1 (Closes: #728164):
+ - d/control: ceph-mds Breaks/Replaces ceph (<< 0.67.3-1).
+ - d/control: ceph-fs-common Breaks/Replaces ceph-common (<< 0.67.3-1).
+ * d/rules,control: Use google-perftools on armhf and powerpc archs.
+
+ -- James Page <james.page@ubuntu.com> Mon, 25 Nov 2013 10:13:19 +0000
+
+ceph (0.72.1-1) unstable; urgency=low
+
+ * New upstream stable release:
+ - d/ceph-test.install: Add new ceph_filestore_tool, ceph-kvstore-tool
+ and ceph_test_cls_hello binaries, drop ceph_test_store_tool.
+ - d/ceph-common.install: Add new ceph-post-file binary and manpage.
+ - d/ceph.install: Tweaked install path /usr/sbin -> /sbin.
+ - d/control: Add new BD's on python-nose and yasm.
+ - d/copyright: Updates inline with changes in codebase.
+ - d/ceph.install,rules: Install rbdmap init file using dh_installinit.
+ - Refresh patches.
+ * d/control,rules: Disable unit testing; it requires a forked version of
+ cram and is still trying to download dependencies using virtualenv.
+
+ -- James Page <james.page@ubuntu.com> Fri, 22 Nov 2013 13:02:29 +0000
+
+ceph (0.67.3-1) unstable; urgency=low
+
+ [ Laszlo Boszormenyi ]
+ * New upstream release (Closes: #693866, #705262).
+ * Update debian/copyright.
+ * Sync with Ubuntu.
+
+ [ James Page ]
+ * d/control,rules,libcephfs-{java,jni}: Enable Java CephFS library,
+ add new BD's on javahelper and default-jdk, add dbg package.
+ * d/control: Add new BD on libboost-thread-dev for RADOS Gateway
+ keystone integration.
+ * d/{control,obsync.install}: Drop obsync package inline with
+ upstream.
+ * d/librbd-dev.install: Pickup new features.h file.
+ * Remove manual calls to ldconfig:
+ - d/lib{rados2|rbd1|cephfs1}.post*: Dropped - all these do is call
+ ldconfig which will automatically be done.
+ - d/rules: Let dh_makeshlibs do its magic with postinst/postrm.
+ * d/tests/*: Added autopkgtests for librbd, librados, python-ceph
+ and the ceph CLI.
+ * d/control: Fix versions of librbd1, librados2 and libcephfs1 for
+ python-ceph as it requires an exact version match.
+ * d/ceph.docs: Drop - README from upstream is only useful for developers
+ (Closes: #722957).
+ * d/rules: Drop --upstart-only from dh_installinit calls for upstart
+ configurations; this is deprecated in Ubuntu and not support in Debian.
+ * d/rules: Exclude jni package from shlibs generation to avoid pointless
+ ldconfig calls in maintainer scripts.
+
+ [ Bastian Blank ]
+ * Use debhelper 9.
+ * Use dh-autoreconf.
+ * Install files from source tree if possible.
+ * Run test-suite:
+ - Build-depend on python-virtualenv.
+ - Ask virtualenv to never download anything.
+ * Fix clean target.
+ * Properly mark library modules:
+ - Don't longer exclude them from stripping.
+ * Drop all libtool .la files.
+ * Generate python dependencies.
+ * Don't exclude stuff from shlibs generation.
+
+ -- Laszlo Boszormenyi (GCS) <gcs@debian.org> Tue, 01 Oct 2013 02:29:08 +0200
+
+ceph (0.48-1) unstable; urgency=low
+
+ * New upstream release, the first with long-term support.
+ * As gceph dropped by upstream, remove it from packaging.
+ * Build with hardening enabled and build-conflict with libcryptopp not to
+ mix up with libnss.
+ * Use symbol versioning (closes: #679686).
+ * Update debian/watch to GitHub tags.
+
+ -- Laszlo Boszormenyi (GCS) <gcs@debian.hu> Sat, 07 Jul 2012 07:53:40 +0200
+
+ceph (0.47.2-1) unstable; urgency=low
+
+ * New upstream release.
+ * Use system leveldb (closes: #667907).
+ * Remove librgw1 , librgw-dev and librgw1-dbg and add rest-bench and
+ rest-bench-dbg packages.
+ * Backport leveldb build fixes from upstream git as
+ fix_leveldb_dep_for_system_library_case.patch and
+ fix_leveldb_includes_for_system_library_case.patch .
+ * Update packaging.
+ * Sync with Ubuntu: switch build-dependency from libcryptopp to libnss as
+ libcryptopp is not seeded.
+
+ -- Laszlo Boszormenyi (GCS) <gcs@debian.hu> Sun, 03 Jun 2012 13:37:52 +0200
+
+ceph (0.44.1-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Laszlo Boszormenyi (GCS) <gcs@debian.hu> Fri, 06 Apr 2012 01:10:15 +0200
+
+ceph (0.43-1) unstable; urgency=low
+
+ * New upstream release, now creates /var/run/ceph on each start
+ (closes: #660238).
+ * Update debian/copyright .
+
+ -- Laszlo Boszormenyi (GCS) <gcs@debian.hu> Sun, 26 Feb 2012 04:07:02 +0100
+
+ceph (0.41-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Laszlo Boszormenyi (GCS) <gcs@debian.hu> Sun, 05 Feb 2012 10:07:38 +0100
+
+ceph (0.40-1) unstable; urgency=low
+
+ * New upstream release (closes: #652037).
+ * Adjust copyright to match upstream source changes.
+
+ -- Laszlo Boszormenyi (GCS) <gcs@debian.hu> Sat, 14 Jan 2012 12:01:30 +0100
+
+ceph (0.38-1) unstable; urgency=low
+
+ * New upstream release (closes: #647764), missingok is now part of logrotate
+ directives (closes: #645651).
+ * Rename ceph-client-tools package to ceph-common , libceph-dev to
+ libcephfs-dev and libceph1{,-dbg} ones to libcephfs1{,-dbg} respectively.
+ * Update upstream VCS locations.
+
+ -- Laszlo Boszormenyi (GCS) <gcs@debian.hu> Sun, 27 Nov 2011 21:40:52 +0100
+
+ceph (0.35-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Laszlo Boszormenyi (GCS) <gcs@debian.hu> Sat, 24 Sep 2011 16:51:57 +0200
+
+ceph (0.34-1) unstable; urgency=low
+
+ * New upstream release (closes: #638714).
+ * Make librbd-dev depends on librados-dev as it uses headers from the latter
+ (closes: #636845).
+ * Add new binary packages, gceph, gceph-dbg and obsync . The libcrush ones
+ removed.
+ * Change to quilt source format and tune packaging.
+
+ -- Laszlo Boszormenyi (GCS) <gcs@debian.hu> Sun, 28 Aug 2011 15:56:16 +0200
+
+ceph (0.27-1.1) unstable; urgency=low
+
+ * Non-maintainer upload.
+ * Remove references to other libraries from dependency_libs field
+ (closes: #621208).
+
+ -- Luk Claes <luk@debian.org> Sat, 28 May 2011 22:28:48 +0200
-ceph (0.25.2-1) experimental; urgency=low
+ceph (0.27-1) unstable; urgency=low
- * New upstream release
+ * New upstream release.
- -- Sage Weil <sage@newdream.net> Sun, 20 Mar 2011 21:07:38 -0700
+ -- Laszlo Boszormenyi (GCS) <gcs@debian.hu> Mon, 25 Apr 2011 10:09:05 +0200
-ceph (0.25.1-1) experimental; urgency=low
+ceph (0.25.2-1) unstable; urgency=low
- * New upstream release
+ * New upstream release.
+ * Make Ceph cross buildable (closes: #618939), thanks to Hector Oron.
+ * Disable libatomic-ops on ARMv4t (armel) archs to prevent FTBFS
+ (closes: #615235), thanks go to Hector Oron again.
+ * Rename librados1{,-dbg,-dev} packages to librados2{,-dbg,-dev} ones;
+ conflict with and replace the former ones.
+ * Add librbd1 and librbd-dev packages.
- -- Sage Weil <sage@newdream.net> Mon, 14 Mar 2011 14:43:47 -0700
+ -- Laszlo Boszormenyi (GCS) <gcs@debian.hu> Sun, 27 Mar 2011 15:51:23 +0200
-ceph (0.25-1) experimental; urgency=low
+ceph (0.24.3-2) unstable; urgency=low
- * New upstream release
+ * Make Ceph Linux only and build on all Linux archs (closes: #614890).
+ * Support parallel building via DEB_BUILD_OPTIONS .
+ * Add watch file, thanks to Clint Byrum (closes: #615021).
+ * Tune packaging.
- -- Sage Weil <sage@newdream.net> Fri, 04 Mar 2011 14:39:54 -0800
+ -- Laszlo Boszormenyi (GCS) <gcs@debian.hu> Fri, 25 Feb 2011 15:17:26 +0100
-ceph (0.24.3-1) experimental; urgency=low
+ceph (0.24.3-1) unstable; urgency=low
- * New upstream release
+ * New upstream bugfix release.
- -- Sage Weil <sage@newdream.net> Thu, 10 Feb 2011 09:14:00 -0800
+ -- Laszlo Boszormenyi (GCS) <gcs@debian.hu> Sat, 19 Feb 2011 12:25:43 +0100
-ceph (0.24.2-1) experimental; urgency=low
+ceph (0.24.2-1) unstable; urgency=low
- * New upstream release.
+ * New upstream bugfix release.
- -- Sage Weil <sage@newdream.net> Mon, 24 Jan 2011 11:02:24 -0800
+ -- Laszlo Boszormenyi (GCS) <gcs@debian.hu> Sat, 29 Jan 2011 15:25:14 +0100
-ceph (0.24.1-1) experimental; urgency=low
+ceph (0.24.1-1) unstable; urgency=low
- * New upstream release.
+ * New upstream bugfix release.
- -- Sage Weil <sage@newdream.net> Fri, 07 Jan 2011 16:49:48 -0800
+ -- Laszlo Boszormenyi (GCS) <gcs@debian.hu> Tue, 11 Jan 2011 22:23:18 +0100
-ceph (0.24-1) experimental; urgency=low
+ceph (0.24-1) unstable; urgency=low
* New upstream release.
@@ -785,3 +2715,4 @@ ceph (0.23.1-1) experimental; urgency=low
* Initial release (Closes: #506040)
-- Sage Weil <sage@newdream.net> Sun, 21 Nov 2010 15:22:21 -0800
+
diff --git a/debian/clean b/debian/clean
new file mode 100644
index 000000000..7a394d2e5
--- /dev/null
+++ b/debian/clean
@@ -0,0 +1,36 @@
+configure
+src/rocksdb/util/build_version.cc
+src/pybind/*.pyc
+src/test/pybind/*.pyc
+src/rapidjson/thirdparty/gtest/googlemock/msvc/2005/gmock.sln
+src/rapidjson/thirdparty/gtest/googlemock/msvc/2005/gmock.vcproj
+src/rapidjson/thirdparty/gtest/googlemock/msvc/2005/gmock_config.vsprops
+src/rapidjson/thirdparty/gtest/googlemock/msvc/2005/gmock_main.vcproj
+src/rapidjson/thirdparty/gtest/googlemock/msvc/2005/gmock_test.vcproj
+src/rapidjson/thirdparty/gtest/googlemock/msvc/2010/gmock.sln
+src/rapidjson/thirdparty/gtest/googlemock/msvc/2010/gmock.vcxproj
+src/rapidjson/thirdparty/gtest/googlemock/msvc/2010/gmock_config.props
+src/rapidjson/thirdparty/gtest/googlemock/msvc/2010/gmock_main.vcxproj
+src/rapidjson/thirdparty/gtest/googlemock/msvc/2010/gmock_test.vcxproj
+src/rapidjson/thirdparty/gtest/googletest/codegear/gtest.cbproj
+src/rapidjson/thirdparty/gtest/googletest/codegear/gtest.groupproj
+src/rapidjson/thirdparty/gtest/googletest/codegear/gtest_all.cc
+src/rapidjson/thirdparty/gtest/googletest/codegear/gtest_link.cc
+src/rapidjson/thirdparty/gtest/googletest/codegear/gtest_main.cbproj
+src/rapidjson/thirdparty/gtest/googletest/codegear/gtest_unittest.cbproj
+src/rapidjson/thirdparty/gtest/googletest/msvc/gtest-md.sln
+src/rapidjson/thirdparty/gtest/googletest/msvc/gtest-md.vcproj
+src/rapidjson/thirdparty/gtest/googletest/msvc/gtest.sln
+src/rapidjson/thirdparty/gtest/googletest/msvc/gtest.vcproj
+src/rapidjson/thirdparty/gtest/googletest/msvc/gtest_main-md.vcproj
+src/rapidjson/thirdparty/gtest/googletest/msvc/gtest_main.vcproj
+src/rapidjson/thirdparty/gtest/googletest/msvc/gtest_prod_test-md.vcproj
+src/rapidjson/thirdparty/gtest/googletest/msvc/gtest_prod_test.vcproj
+src/rapidjson/thirdparty/gtest/googletest/msvc/gtest_unittest-md.vcproj
+src/rapidjson/thirdparty/gtest/googletest/msvc/gtest_unittest.vcproj
+debian/ceph-common.logrotate
+debian/radosgw.init
+src/jaegertracing/opentelemetry-cpp/third_party/ms-gsl/tests/*.cpp
+src/s3select/rapidjson/thirdparty/gtest/googlemock/msvc/2005/*
+src/s3select/rapidjson/thirdparty/gtest/googlemock/msvc/2010/*
+src/s3select/rapidjson/thirdparty/gtest/googletest/codegear/gtest*
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index 48082f72f..000000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-12
diff --git a/debian/control b/debian/control
index 041dfcc79..c70e16ef2 100644
--- a/debian/control
+++ b/debian/control
@@ -1,132 +1,124 @@
Source: ceph
Section: admin
Priority: optional
+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+XSBC-Original-Maintainer: Ceph Packaging Team <team+ceph@tracker.debian.org>
+Uploaders:
+ James Page <jamespage@debian.org>,
+ Gaudenz Steinlin <gaudenz@debian.org>,
+ Bernd Zeimetz <bzed@debian.org>,
Homepage: http://ceph.com/
-Vcs-Git: git://github.com/ceph/ceph.git
-Vcs-Browser: https://github.com/ceph/ceph
-Maintainer: Ceph Maintainers <ceph-maintainers@ceph.io>
-Uploaders: Ken Dreyer <kdreyer@redhat.com>,
- Alfredo Deza <adeza@redhat.com>,
-Build-Depends: automake,
- bison,
- cmake (>= 3.10.2),
- cpio,
- cython3,
- debhelper (>= 10),
- default-jdk,
- dh-exec,
- dh-python,
- flex,
- git,
- golang,
- gperf,
- g++ (>= 11),
- javahelper,
- jq <pkg.ceph.check>,
- jsonnet <pkg.ceph.check>,
- junit4,
- libarrow-dev <pkg.ceph.arrow>,
- libparquet-dev <pkg.ceph.arrow>,
- libaio-dev,
- libbabeltrace-ctf-dev,
- libbabeltrace-dev,
- libblkid-dev (>= 2.17),
- libc-ares-dev <pkg.ceph.crimson>,
- libcrypto++-dev <pkg.ceph.crimson>,
- libcryptsetup-dev,
- libcap-ng-dev,
- libcap-dev,
- libcunit1-dev,
- libcurl4-openssl-dev,
- libevent-dev,
- libexpat1-dev,
- libffi-dev [!amd64] <pkg.ceph.check>,
- libfmt-dev (>= 6.1.2),
- libfuse-dev,
- libgoogle-perftools-dev [i386 amd64 arm64],
- libgnutls28-dev <pkg.ceph.crimson>,
- libhwloc-dev <pkg.ceph.crimson>,
- libibverbs-dev,
- libicu-dev,
- librdmacm-dev,
- libkeyutils-dev,
- libldap2-dev,
- liblttng-ust-dev,
- liblua5.3-dev,
- liblz4-dev (>= 0.0~r131),
- libncurses-dev,
- libnss3-dev,
- liboath-dev,
- libnuma-dev <pkg.ceph.crimson>,
- libpciaccess-dev <pkg.ceph.crimson>,
- libsctp-dev <pkg.ceph.crimson>,
- libsnappy-dev,
- libsqlite3-dev,
- libssl-dev,
- libtool,
- liblmdb-dev,
- libudev-dev,
- libnl-genl-3-dev,
- libxml2-dev,
- librabbitmq-dev,
- libre2-dev,
- libutf8proc-dev (>= 2.2.0),
- librdkafka-dev,
- libthrift-dev (>= 0.13.0),
- libyaml-cpp-dev (>= 0.6),
- libzstd-dev <pkg.ceph.check>,
- libxmlsec1 <pkg.ceph.check>,
- libxmlsec1-nss <pkg.ceph.check>,
- libxmlsec1-openssl <pkg.ceph.check>,
- libxmlsec1-dev <pkg.ceph.check>,
- libdaxctl-dev (>= 63) <pkg.ceph.pmdk>,
- libndctl-dev (>= 63) <pkg.ceph.pmdk>,
- libpmem-dev <pkg.ceph.pmdk>,
- libpmemobj-dev (>= 1.8) <pkg.ceph.pmdk>,
- libprotobuf-dev <pkg.ceph.crimson>,
- ninja-build,
- nlohmann-json3-dev,
- patch,
- pkg-config,
- prometheus <pkg.ceph.check>,
- protobuf-compiler <pkg.ceph.crimson>,
- python3-all-dev,
- python3-cherrypy3,
- python3-natsort,
- python3-pecan <pkg.ceph.check>,
- python3-bcrypt <pkg.ceph.check>,
- tox <pkg.ceph.check>,
- python3-coverage <pkg.ceph.check>,
- python3-dateutil <pkg.ceph.check>,
- python3-grpcio <pkg.ceph.check>,
- python3-openssl <pkg.ceph.check>,
- python3-prettytable <pkg.ceph.check>,
- python3-requests <pkg.ceph.check>,
- python3-scipy <pkg.ceph.check>,
- python3-setuptools,
- python3-sphinx,
- python3-venv,
- python3-werkzeug <pkg.ceph.check>,
- python3-yaml,
- ragel <pkg.ceph.crimson>,
- socat <pkg.ceph.check>,
- systemd,
- systemtap-sdt-dev <pkg.ceph.crimson>,
- uuid-dev <pkg.ceph.check>,
- uuid-runtime,
- valgrind,
- xfslibs-dev,
- xmlstarlet <pkg.ceph.check>,
- nasm [amd64],
- zlib1g-dev,
-Standards-Version: 4.4.0
+Vcs-Git: https://git.launchpad.net/~ubuntu-server-dev/ubuntu/+source/ceph
+Build-Depends:
+ architecture-is-64-bit,
+ cmake,
+ cython3-legacy,
+ debhelper-compat (= 10),
+ default-jdk,
+ dh-exec,
+ dh-python,
+ dpkg-dev (>= 1.16.1~),
+ gperf,
+ javahelper,
+ junit4,
+ libaio-dev,
+ libbabeltrace-ctf-dev,
+ libbabeltrace-dev,
+ libblkid-dev (>= 2.17),
+ libboost-atomic-dev (>= 1.82.0),
+ libboost-chrono-dev (>= 1.82.0),
+ libboost-context-dev (>= 1.82.0) [!mips64el !ia64 !m68k !ppc64 !sh4 !sparc64 !x32],
+ libboost-coroutine-dev (>= 1.82.0) [!mips64el !ia64 !m68k !ppc64 !sh4 !sparc64 !x32],
+ libboost-date-time-dev (>= 1.82.0),
+ libboost-filesystem-dev (>= 1.82.0),
+ libboost-iostreams-dev (>= 1.82.0),
+ libboost-program-options-dev (>= 1.82.0),
+ libboost-python-dev (>= 1.82.0),
+ libboost-random-dev (>= 1.82.0),
+ libboost-regex-dev (>= 1.82.0),
+ libboost-system-dev (>= 1.82.0),
+ libboost-test-dev (>= 1.82.0),
+ libboost-thread-dev (>= 1.82.0),
+ libboost-timer-dev (>= 1.82.0),
+ libboost-url-dev (>= 1.82.0),
+ libbz2-dev,
+ libc-ares-dev,
+ libcap-dev,
+ libcap-ng-dev,
+ libcrypto++-dev,
+ libcryptsetup-dev,
+ libcunit1-dev,
+ libcurl4-gnutls-dev,
+ libedit-dev,
+ libexpat1-dev,
+ libfmt-dev,
+ libfuse3-dev,
+ libgnutls28-dev,
+ libgoogle-perftools-dev [amd64 powerpc arm64 ppc64el],
+ libhwloc-dev,
+ libibverbs-dev,
+ libicu-dev,
+ libkeyutils-dev,
+ libldap2-dev,
+ libleveldb-dev,
+ liblmdb-dev,
+ liblua5.4-dev,
+ liblz4-dev (>= 0.0~r131),
+ libncurses-dev,
+ libnl-3-dev,
+ libnl-genl-3-dev,
+ libnss3-dev,
+ libnuma-dev,
+ liboath-dev,
+ libpciaccess-dev,
+ libpmem-dev [amd64 arm64 ppc64el],
+ libpmemobj-dev [amd64 arm64 ppc64el],
+ libprotobuf-dev,
+ librabbitmq-dev,
+ librdmacm-dev,
+ libsctp-dev,
+ libsnappy-dev,
+ libsqlite3-dev,
+ libssl-dev,
+ libtool,
+ libudev-dev,
+ libxml2-dev,
+ libyaml-cpp-dev,
+ lsb-release,
+ luarocks,
+ nasm (>= 2.13.03) [amd64],
+ pkgconf,
+ protobuf-compiler,
+ python3-cherrypy3,
+ python3-dev,
+ python3-jinja2,
+ python3-markupsafe,
+ python3-packaging,
+ python3-pecan,
+ python3-pip,
+ python3-setuptools,
+ python3-sphinx,
+ python3-venv,
+ python3-yaml,
+ ragel,
+ systemtap-sdt-dev,
+ tox,
+ uuid-runtime,
+ valgrind [amd64 powerpc ppc64el s390x arm64],
+ virtualenv,
+ xfslibs-dev,
+ zlib1g-dev,
+Standards-Version: 4.2.1
Package: ceph
Architecture: linux-any
-Depends: ceph-mgr (= ${binary:Version}),
- ceph-mon (= ${binary:Version}),
- ceph-osd (= ${binary:Version}),
-Recommends: ceph-mds (= ${binary:Version}),
+Depends:
+ ceph-mgr (= ${binary:Version}),
+ ceph-mon (= ${binary:Version}),
+ ceph-osd (= ${binary:Version}),
+ ${misc:Depends},
+Suggests:
+ ceph-mds (= ${binary:Version}),
Description: distributed storage and file system
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
@@ -134,128 +126,213 @@ Description: distributed storage and file system
Package: ceph-base
Architecture: linux-any
-Depends: binutils,
- ceph-common (= ${binary:Version}),
- logrotate,
- parted,
- psmisc,
- ${misc:Depends},
- ${shlibs:Depends},
- ${python3:Depends}
-Recommends: btrfs-tools,
- ceph-mds (= ${binary:Version}),
- librados2 (= ${binary:Version}),
- libradosstriper1 (= ${binary:Version}),
- librbd1 (= ${binary:Version}),
- ntp | time-daemon,
- nvme-cli,
- smartmontools,
-Replaces: ceph (<< 10),
- ceph-common (<< 0.78-500),
- ceph-test (<< 12.2.2-14),
- python-ceph (<< 0.92-1223),
-Breaks: ceph (<< 10),
- ceph-test (<< 12.2.2-14),
- python-ceph (<< 0.92-1223),
+Depends:
+ binutils,
+ ceph-common (= ${binary:Version}),
+ cryptsetup-bin | cryptsetup,
+ gdisk,
+ hdparm | sdparm,
+ parted,
+ uuid-runtime,
+ xfsprogs,
+ ${misc:Depends},
+ ${python3:Depends},
+ ${shlibs:Depends},
+Pre-Depends:
+ ${misc:Pre-Depends},
+Recommends:
+ ceph-mds (= ${binary:Version}),
+ chrony | time-daemon | ntp,
+ librados2 (= ${binary:Version}),
+ librbd1 (= ${binary:Version}),
+ nvme-cli,
+ smartmontools (>= 7.0),
+Suggests:
+ btrfs-tools,
+ logrotate,
Description: common ceph daemon libraries and management tools
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage.
+ Ceph is a distributed storage system designed to provide excellent
+ performance, reliability, and scalability.
.
This package contains the libraries and management tools that are common among
the Ceph server daemons (ceph-mon, ceph-mgr, ceph-osd, ceph-mds). These tools
are necessary for creating, running, and administering a Ceph storage cluster.
-Package: ceph-base-dbg
+Package: ceph-common
Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: ceph-base (= ${binary:Version}),
- ${misc:Depends},
-Description: debugging symbols for ceph-base
+Depends:
+ librbd1 (= ${binary:Version}),
+ python3-ceph-argparse (= ${binary:Version}),
+ python3-ceph-common (= ${binary:Version}),
+ python3-cephfs (= ${binary:Version}),
+ python3-prettytable,
+ python3-rados (= ${binary:Version}),
+ python3-rbd (= ${binary:Version}),
+ python3-requests,
+ ${misc:Depends},
+ ${python3:Depends},
+ ${shlibs:Depends},
+Conflicts:
+ ceph-client-tools,
+Breaks:
+ ceph-mds (<< 14.2.5-3~),
+Replaces:
+ ceph-mds (<< 14.2.5-3~),
+Suggests:
+ ceph,
+ ceph-mds,
+Description: common utilities to mount and interact with a ceph storage cluster
+ Ceph is a distributed storage and file system designed to provide
+ excellent performance, reliability, and scalability. This is a collection
+ of common tools that allow one to interact with and administer a Ceph cluster.
+
+Package: ceph-exporter
+Architecture: linux-any
+Depends:
+ ceph-base (= ${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Description: metrics exporter for the ceph distributed storage system
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
block and file system storage.
.
- This package contains the libraries and management tools that are common among
- the Ceph server daemons (ceph-mon, ceph-mgr, ceph-osd, ceph-mds). These tools
- are necessary for creating, running, and administering a Ceph storage cluster.
+ This package contains the metrics exporter daemon, which is used to expose
+ the performance metrics.
+
+Package: ceph-fuse
+Architecture: amd64
+Depends:
+ python3,
+ ${misc:Depends},
+ ${python3:Depends},
+ ${shlibs:Depends},
+Recommends:
+ fuse,
+Description: FUSE-based client for the Ceph distributed file system
+ Ceph is a distributed network file system designed to provide
+ excellent performance, reliability, and scalability. This is a
+ FUSE-based client that allows one to mount a Ceph file system without
+ root privileges.
.
- This package contains the debugging symbols for ceph-base.
+ Because the FUSE-based client has certain inherent performance
+ limitations, it is recommended that the native Linux kernel client
+ be used if possible. If it is not practical to load a kernel module
+ (insufficient privileges, older kernel, etc.), then the FUSE client will
+ do.
-Package: cephadm
-Architecture: linux-any
-Recommends: podman (>= 2.0.2) | docker.io | docker-ce
-Depends: adduser (>= 3.11),
- lvm2,
- python3,
- ${python3:Depends},
-Description: cephadm utility to bootstrap ceph daemons with systemd and containers
+Package: ceph-grafana-dashboards
+Architecture: all
+Depends:
+ ${misc:Depends},
+Description: Grafana dashboards for the Ceph dashboard
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
block and file system storage.
.
- The cephadm utility is used to bootstrap a Ceph cluster and to manage
- ceph daemons deployed with systemd and containers.
+ This package contains Grafana dashboards that are used by the Ceph Dashboard
+ for monitoring.
-Package: ceph-mds
+Package: ceph-immutable-object-cache
Architecture: linux-any
-Depends: ceph-base (= ${binary:Version}),
- ${misc:Depends},
- ${shlibs:Depends},
-Recommends: ceph-fuse (= ${binary:Version}),
- libcephfs2 (= ${binary:Version}),
-Replaces: ceph (<< 0.93-417),
-Breaks: ceph (<< 0.93-417),
-Description: metadata server for the ceph distributed file system
+Depends:
+ librados2 (= ${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Description: Ceph daemon for immutable object cache
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
- block and file system storage.
+ block and file system storage. This is a daemon for immutable
+ object cache.
+
+Package: ceph-mds
+Architecture: linux-any
+Depends:
+ ceph-base (= ${binary:Version}),
+ librados2 (= ${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Recommends:
+ libcephfs2 (= ${binary:Version}),
+Suggests:
+ ceph-fuse,
+Breaks:
+ ceph (<< 0.67.3-1),
+Replaces:
+ ceph (<< 0.67.3-1),
+Description: metadata server for the ceph distributed file system
+ Ceph is a distributed storage and network file system designed to
+ provide excellent performance, reliability, and scalability.
.
This package contains the metadata server daemon, which is used to
create a distributed file system on top of the ceph storage cluster.
-Package: ceph-mds-dbg
+Package: ceph-mgr
Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: ceph-mds (= ${binary:Version}),
- ${misc:Depends},
-Description: debugging symbols for ceph-mds
+Depends:
+ ceph-base (= ${binary:Version}),
+ ceph-mgr-modules-core (= ${binary:Version}),
+ libsqlite3-mod-ceph (= ${binary:Version}),
+ python3-bcrypt,
+ python3-cherrypy3,
+ python3-jwt,
+ python3-pecan,
+ python3-werkzeug,
+ ${misc:Depends},
+ ${python3:Depends},
+ ${shlibs:Depends},
+Replaces:
+ ceph (<< 0.93-417),
+Breaks:
+ ceph (<< 0.93-417),
+Suggests:
+ ceph-mgr-cephadm,
+ ceph-mgr-dashboard,
+ ceph-mgr-diskprediction-local,
+ ceph-mgr-k8sevents,
+Description: manager for the ceph distributed file system
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
block and file system storage.
.
- This package contains the debugging symbols for ceph-mds.
+ This package contains the manager daemon, which is used to expose high
+ level management and monitoring functionality.
-Package: ceph-mgr
-Architecture: linux-any
-Depends: ceph-base (= ${binary:Version}),
- ceph-mgr-modules-core (= ${binary:Version}),
- libsqlite3-mod-ceph (= ${binary:Version}),
- librados2 (= ${binary:Version}),
- ${misc:Depends},
- ${python3:Depends},
- ${shlibs:Depends},
-Recommends: ceph-mgr-dashboard,
- ceph-mgr-diskprediction-local,
- ceph-mgr-k8sevents,
- ceph-mgr-cephadm
-Suggests: python3-influxdb
-Replaces: ceph (<< 0.93-417),
-Breaks: ceph (<< 0.93-417),
-Description: manager for the ceph distributed storage system
+Package: ceph-mgr-cephadm
+Architecture: all
+Depends:
+ ceph-mgr (= ${binary:Version}),
+ cephadm,
+ openssh-client,
+ python3-cherrypy3,
+ python3-jinja2,
+ ${misc:Depends},
+ ${python:Depends},
+Description: cephadm orchestrator module for ceph-mgr
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
block and file system storage.
.
- This package contains the manager daemon, which is used to expose high
- level management and monitoring functionality.
+ This package contains the CEPHADM module for ceph-mgr's orchestration
+ functionality, to allow ceph-mgr to perform orchestration functions
+ over a standard SSH connection.
Package: ceph-mgr-dashboard
Architecture: all
-Depends: ceph-mgr (= ${binary:Version}),
- ${python3:Depends}
+Depends:
+ ceph-mgr (>= ${binary:Version}),
+ python3-bcrypt,
+ python3-cherrypy3,
+ python3-jwt,
+ python3-openssl,
+ python3-routes,
+ python3-werkzeug,
+ python3-yaml,
+ ${misc:Depends},
+ ${python3:Depends},
+ ${shlibs:Depends},
+Suggests:
+ python3-onelogin-saml2,
Description: dashboard module for ceph-mgr
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
@@ -270,8 +347,14 @@ Description: dashboard module for ceph-mgr
Package: ceph-mgr-diskprediction-local
Architecture: all
-Depends: ceph-mgr (= ${binary:Version}),
- ${python3:Depends}
+Depends:
+ ceph-mgr (>= ${binary:Version}),
+ python3-numpy,
+ python3-scipy,
+ python3-sklearn,
+ ${misc:Depends},
+ ${python3:Depends},
+ ${shlibs:Depends},
Description: diskprediction-local module for ceph-mgr
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
@@ -280,41 +363,13 @@ Description: diskprediction-local module for ceph-mgr
This package contains the diskprediction_local module for the ceph-mgr
daemon, which helps predict disk failures.
-Package: ceph-mgr-modules-core
-Architecture: all
-Depends: ${misc:Depends},
- ${python3:Depends},
-Replaces: ceph-mgr (<< 15.1.0)
-Breaks: ceph-mgr (<< 15.1.0)
-Description: ceph manager modules which are always enabled
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage.
- .
- This package contains a set of core ceph-mgr modules which are always
- enabled.
-
-Package: ceph-mgr-rook
-Architecture: all
-Depends: ceph-mgr (= ${binary:Version}),
- ${misc:Depends},
- ${python3:Depends},
- ${shlibs:Depends},
-Description: rook module for ceph-mgr
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage.
- .
- This package contains the rook module for ceph-mgr's orchestration
- functionality, to allow ceph-mgr to install and configure ceph using
- Rook.
-
Package: ceph-mgr-k8sevents
Architecture: all
-Depends: ceph-mgr (= ${binary:Version}),
- python3-kubernetes,
- ${misc:Depends},
- ${python3:Depends},
+Depends:
+ ceph-mgr (>= ${binary:Version}),
+ python3-kubernetes,
+ ${misc:Depends},
+ ${python:Depends},
Description: kubernetes events module for ceph-mgr
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
@@ -324,44 +379,56 @@ Description: kubernetes events module for ceph-mgr
ceph related events to the kubernetes events API, and track all events
that occur within the rook-ceph namespace.
-Package: ceph-mgr-cephadm
+Package: ceph-mgr-modules-core
Architecture: all
-Depends: ceph-mgr (= ${binary:Version}),
- cephadm,
- ${misc:Depends},
- ${python3:Depends},
- openssh-client,
- python3-jinja2,
- python3-cherrypy3
-Description: cephadm orchestrator module for ceph-mgr
+Depends:
+ python3-dateutil,
+ python3-openssl,
+ ${misc:Depends},
+ ${python3:Depends},
+ ${shlibs:Depends},
+Suggests:
+ ceph-mgr-rook,
+Replaces:
+ ceph-mgr (<< 15.1.1-0ubuntu1~),
+Breaks:
+ ceph-mgr (<< 15.1.1-0ubuntu1~),
+Description: ceph manager modules which are always enabled
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
block and file system storage.
.
- This package contains the CEPHADM module for ceph-mgr's orchestration
- functionality, to allow ceph-mgr to perform orchestration functions
- over a standard SSH connection.
+ This package contains a set of core ceph-mgr modules which are always
+ enabled.
-Package: ceph-mgr-dbg
-Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: ceph-mgr (= ${binary:Version}),
- ${misc:Depends},
-Description: debugging symbols for ceph-mgr
+Package: ceph-mgr-rook
+Architecture: all
+Depends:
+ ceph-mgr (>= ${binary:Version}),
+ python3-jsonpatch,
+ ${misc:Depends},
+ ${python3:Depends},
+ ${shlibs:Depends},
+Description: rook module for ceph-mgr
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
block and file system storage.
.
- This package contains the debugging symbols for ceph-mgr.
+ This package contains the rook module for ceph-mgr's orchestration
+ functionality, to allow ceph-mgr to install and configure ceph using
+ Rook.
Package: ceph-mon
Architecture: linux-any
-Depends: ceph-base (= ${binary:Version}),
- ${misc:Depends},
- ${shlibs:Depends},
-Replaces: ceph (<< 10), ceph-test (<< 12.2.2-14)
-Breaks: ceph (<< 10), ceph-test (<< 12.2.2-14)
+Depends:
+ ceph-base (= ${binary:Version}),
+ ${misc:Depends},
+ ${python3:Depends},
+ ${shlibs:Depends},
+Replaces:
+ ceph (<< 10.2.2-0ubuntu2~),
+Breaks:
+ ceph (<< 10.2.2-0ubuntu2~),
Description: monitor server for the ceph storage system
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
@@ -372,36 +439,26 @@ Description: monitor server for the ceph storage system
cluster that provides extremely reliable and durable storage of cluster
membership, configuration, and state.
-Package: ceph-mon-dbg
-Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: ceph-mon (= ${binary:Version}),
- ${misc:Depends},
-Description: debugging symbols for ceph-mon
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage.
- .
- This package contains the debugging symbols for ceph-mon.
-
Package: ceph-osd
Architecture: linux-any
-Depends: ceph-base (= ${binary:Version}),
- sudo,
- ${misc:Depends},
- ${python3:Depends},
- ${shlibs:Depends},
- libprotobuf23 <pkg.ceph.crimson>,
-Replaces: ceph (<< 10),
- ceph-test (<< 12.2.2-14),
- ceph-osd (<< 17.0.0)
-Breaks: ceph (<< 10),
- ceph-test (<< 12.2.2-14),
- ceph-osd (<< 17.0.0)
-Recommends: ceph-volume (= ${binary:Version}),
- nvme-cli,
- smartmontools,
+Depends:
+ ceph-base (= ${binary:Version}),
+ sudo,
+ ${misc:Depends},
+ ${python3:Depends},
+ ${shlibs:Depends},
+Pre-Depends:
+ ceph-common (= ${binary:Version}),
+Replaces:
+ ceph (<< 10.2.2-0ubuntu2~),
+ ceph-test (<< 12.2.8+dfsg1-1~),
+Breaks:
+ ceph (<< 10.2.2-0ubuntu2~),
+ ceph-test (<< 12.2.8+dfsg1-1~),
+Recommends:
+ ceph-volume (= ${binary:Version}),
+ nvme-cli,
+ smartmontools,
Description: OSD server for the ceph storage system
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
@@ -411,30 +468,55 @@ Description: OSD server for the ceph storage system
It is responsible for storing objects on a local file system
and providing access to them over the network.
-Package: ceph-osd-dbg
-Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: ceph-osd (= ${binary:Version}),
- ${misc:Depends},
-Description: debugging symbols for ceph-osd
+Package: ceph-prometheus-alerts
+Architecture: all
+Depends:
+ ${misc:Depends},
+Description: Prometheus alerts for the Ceph dashboard
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
block and file system storage.
.
- This package contains the debugging symbols for ceph-osd.
+ This package contains alerts used for Prometheus to interact with the
+ Ceph Dashboard.
+
+Package: ceph-resource-agents
+Architecture: all
+Priority: extra
+Recommends:
+ pacemaker,
+Depends:
+ ceph (>= ${binary:Version}),
+ resource-agents-common,
+ ${misc:Depends},
+Description: OCF-compliant resource agents for Ceph
+ Ceph is a distributed storage and network file system designed to provide
+ excellent performance, reliability, and scalability.
+ .
+ This package contains the resource agents (RAs) which integrate
+ Ceph with OCF-compliant cluster resource managers,
+ such as Pacemaker.
Package: ceph-volume
Architecture: all
Section: python
-Depends: ceph-osd (= ${binary:Version}),
- cryptsetup-bin,
- e2fsprogs,
- lvm2,
- parted,
- xfsprogs,
- ${misc:Depends},
- ${python3:Depends}
+Depends:
+ cryptsetup-bin,
+ e2fsprogs,
+ lvm2,
+ parted,
+ python3-ceph-common (= ${binary:Version}),
+ python3-packaging,
+ util-linux,
+ xfsprogs,
+ ${misc:Depends},
+ ${python3:Depends},
+Enhances:
+ ceph-osd,
+Breaks:
+ ceph-osd (<< 17.0.0~),
+Replaces:
+ ceph-osd (<< 17.0.0~),
Description: tool to facilidate OSD deployment
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
@@ -444,296 +526,191 @@ Description: tool to facilidate OSD deployment
lvm or physical disks, and trying to follow a predictable, and robust
way of preparing, activating, and starting the deployed OSD.
-Package: ceph-fuse
-Architecture: linux-any
-Depends: ${misc:Depends},
- ${shlibs:Depends},
- ${python3:Depends},
- fuse,
-Description: FUSE-based client for the Ceph distributed file system
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage. This is a
- FUSE-based client that allows one to mount a Ceph file system without
- root privileges.
- .
- Because the FUSE-based client has certain inherent performance
- limitations, it is recommended that the native Linux kernel client
- be used if possible. If it is not practical to load a kernel module
- (insufficient privileges, older kernel, etc.), then the FUSE client will
- do.
-
-Package: ceph-fuse-dbg
-Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: ceph-fuse (= ${binary:Version}),
- ${misc:Depends},
-Description: debugging symbols for ceph-fuse
+Package: cephadm
+Architecture: all
+Depends:
+ lvm2,
+ ${misc:Depends},
+ ${python3:Depends},
+Recommends:
+ docker.io,
+Description: cephadm utility to bootstrap ceph daemons with systemd and containers
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
- block and file system storage. This is a
- FUSE-based client that allows one to mount a Ceph file system without
- root privileges.
+ block and file system storage.
.
- This package contains the debugging symbols for ceph-fuse.
+ The cephadm utility is used to bootstrap a Ceph cluster and to manage
+ ceph daemons deployed with systemd and containers.
Package: cephfs-mirror
Architecture: linux-any
-Depends: ceph-common (= ${binary:Version}),
- librados2 (= ${binary:Version}),
- libcephfs2 (= ${binary:Version}),
- ${misc:Depends},
- ${shlibs:Depends},
-Description: Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage. This is a daemon for mirroring CephFS
- directory snapshots between Ceph clusters.
-
-Package: cephfs-mirror-dbg
-Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: cephfs-mirror (= ${binary:Version}),
- ${misc:Depends}
-Description: debugging symbols for cephfs-mirror
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage. This is a daemon for mirroring CephFS
- directory snapshots between Ceph clusters.
-
-Package: rbd-fuse
-Architecture: linux-any
-Depends: ${misc:Depends},
- ${shlibs:Depends},
-Recommends: fuse,
-Description: FUSE-based rbd client for the Ceph distributed file system
+Depends:
+ ceph-common (= ${binary:Version}),
+ libcephfs2 (= ${binary:Version}),
+ librados2 (= ${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Description: Daemon for mirroring CephFS directory snapshots
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
- block and file system storage. This is a
- FUSE-based client that allows one to map Ceph rbd images as files.
- .
- FUSE base client that allows one to map Ceph rbd images as files.
-
-Package: rbd-fuse-dbg
-Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: rbd-fuse (= ${binary:Version}),
- ${misc:Depends},
-Description: debugging symbols for rbd-fuse
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage. This is a
- FUSE-based client that allows one to map Ceph rbd images as files.
+ block and file system storage.
.
- This package contains the debugging symbols for rbd-fuse.
+ This package contains the daemon for mirroring CephFS directory
+ snapshots between Ceph clusters.
-Package: ceph-immutable-object-cache
-Architecture: linux-any
-Depends: ceph-common (= ${binary:Version}),
- librados2 (= ${binary:Version}),
- ${misc:Depends},
- ${shlibs:Depends},
-Description: Ceph daemon for immutable object cache
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage. This is a daemon for immutable
- object cache.
-
-Package: ceph-immutable-object-cache-dbg
-Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: ceph-immutable-object-cache (= ${binary:Version}),
- ${misc:Depends},
-Description: debugging symbols for ceph-immutable-object-cache
+Package: cephfs-shell
+Architecture: all
+Depends:
+ ${misc:Depends},
+ ${python3:Depends},
+Description: interactive shell for the Ceph distributed file system
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
- block and file system storage. This is a daemon for immutable
- object cache.
+ block and file system storage. This is an interactive tool that
+ allows accessing a Ceph file system without mounting it by providing
+ a nice pseudo-shell which works like an FTP client.
.
- This package contains the debugging symbols for ceph-immutable-object-cache.
-
-Package: rbd-mirror
-Architecture: linux-any
-Depends: ceph-common (= ${binary:Version}),
- librados2 (= ${binary:Version}),
- ${misc:Depends},
- ${shlibs:Depends},
-Description: Ceph daemon for mirroring RBD images
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage. This is a
- daemon for mirroring RBD images between Ceph clusters, streaming
- changes asynchronously.
+ This package contains a CLI for interacting with the CephFS.
-Package: rbd-mirror-dbg
-Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: rbd-mirror (= ${binary:Version}),
- ${misc:Depends},
-Description: debugging symbols for rbd-mirror
+Package: crimson-osd
+Architecture: amd64 arm64 ppc64el s390x
+Depends:
+ ceph-osd (= ${binary:Version}),
+ ${misc:Depends},
+Description: Crimson OSD server for the ceph storage system
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
- block and file system storage. This is a
- daemon for mirroring RBD images between Ceph clusters, streaming
- changes asynchronously.
+ block and file system storage.
.
- This package contains the debugging symbols for rbd-mirror.
-
-Package: rbd-nbd
-Architecture: linux-any
-Depends: ${misc:Depends},
- ${shlibs:Depends},
-Description: NBD-based rbd client for the Ceph distributed file system
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage. This is a
- NBD-based client that allows one to map Ceph rbd images as local
- block device.
+ Crimson is a re-implementation of the ceph-osd daemon using a more
+ platform aware and scalable software architecture (seastar).
.
- NBD base client that allows one to map Ceph rbd images as local
- block device.
+ This package contains the Crimson Object Storage Daemon for the
+ Ceph storage system. It is responsible for storing objects on a
+ local file system and providing access to them over the network.
-Package: rbd-nbd-dbg
+Package: libcephfs-dev
Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: rbd-nbd (= ${binary:Version}),
- ${misc:Depends},
-Description: debugging symbols for rbd-nbd
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage. This is a
- NBD-based client that allows one to map Ceph rbd images as local
- block device.
+Section: libdevel
+Depends:
+ libcephfs2 (= ${binary:Version}),
+ ${misc:Depends},
+Conflicts:
+ libceph-dev,
+ libceph1-dev,
+ libcephfs2-dev,
+Replaces:
+ libceph-dev,
+ libceph1-dev,
+ libcephfs2-dev,
+Description: Ceph distributed file system client library (development files)
+ Ceph is a distributed network file system designed to provide
+ excellent performance, reliability, and scalability. This is a
+ shared library allowing applications to access a Ceph distributed
+ file system via a POSIX-like interface.
.
- This package contains the debugging symbols for rbd-nbd.
-
-Package: ceph-common
-Architecture: linux-any
-Depends: adduser (>= 3.11),
- librbd1 (= ${binary:Version}),
- python3-cephfs (= ${binary:Version}),
- python3-ceph-argparse (= ${binary:Version}),
- python3-ceph-common (= ${binary:Version}),
- python3-prettytable,
- python3-rados (= ${binary:Version}),
- python3-rbd (= ${binary:Version}),
- python3-rgw (= ${binary:Version}),
- ${misc:Depends},
- ${python3:Depends},
- ${shlibs:Depends},
-Conflicts: ceph-client-tools,
-Replaces: ceph (<< 10),
- ceph-client-tools,
- ceph-fs-common (<< 11.0),
- ceph-test (<< 9.0.3-1646),
- librbd1 (<< 0.92-1238),
- python-ceph (<< 0.92-1223),
- radosgw (<< 12.0.3)
-Breaks: ceph (<< 10),
- ceph-fs-common (<< 11.0),
- ceph-test (<< 9.0.3-1646),
- librbd1 (<< 0.92-1238),
- python-ceph (<< 0.92-1223),
- radosgw (<< 12.0.3)
-Suggests: ceph-base (= ${binary:Version}),
- ceph-mds (= ${binary:Version}),
-Description: common utilities to mount and interact with a ceph storage cluster
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage. This is a collection
- of common tools that allow one to interact with and administer a Ceph cluster.
+ This package contains development files needed for building applications that
+ link against libcephfs2.
-Package: ceph-common-dbg
-Architecture: linux-any
-Depends: ceph-common (= ${binary:Version}),
- ${misc:Depends},
-Conflicts: ceph-client-tools-dbg,
-Replaces: ceph-client-tools-dbg,
- ceph-test-dbg (<< 9.0.3-1646),
-Breaks: ceph-test-dbg (<< 9.0.3-1646),
-Section: debug
-Priority: extra
-Description: debugging symbols for ceph-common
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage. This is a collection
- of common tools that allow one to interact with and administer a Ceph cluster.
+Package: libcephfs-java
+Architecture: all
+Section: java
+Depends:
+ libcephfs-jni (>= ${binary:Version}),
+ ${java:Depends},
+ ${misc:Depends},
+Description: Java library for the Ceph File System
+ Ceph is a distributed storage system designed to provide excellent
+ performance, reliability, and scalability.
.
- This package contains the debugging symbols for ceph-common.
+ This package contains the Java library for interacting with the Ceph
+ File System.
-Package: ceph-resource-agents
+Package: libcephfs-jni
Architecture: linux-any
-Recommends: pacemaker,
-Priority: extra
-Depends: ceph (= ${binary:Version}),
- resource-agents,
- ${misc:Depends},
-Description: OCF-compliant resource agents for Ceph
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage.
+Section: libs
+Depends:
+ libcephfs2 (= ${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Description: Java Native Interface library for CephFS Java bindings
+ Ceph is a distributed storage system designed to provide excellent
+ performance, reliability, and scalability.
.
- This package contains the resource agents (RAs) which integrate
- Ceph with OCF-compliant cluster resource managers,
- such as Pacemaker.
+ This package contains the Java Native Interface library for interacting
+ with the Ceph File System.
-Package: librados2
-Conflicts: librados
-Replaces: librados
+Package: libcephfs2
Architecture: linux-any
Section: libs
-Depends: ${misc:Depends},
- ${shlibs:Depends},
-Description: RADOS distributed object store client library
- RADOS is a reliable, autonomic distributed object storage cluster
- developed as part of the Ceph distributed storage system. This is a
- shared library allowing applications to access the distributed object
- store using a simple file-like interface.
+Conflicts:
+ libceph,
+ libceph1,
+ libcephfs,
+Replaces:
+ libceph,
+ libceph1,
+ libcephfs,
+Depends:
+ ${misc:Depends},
+ ${shlibs:Depends},
+Pre-Depends:
+ ${misc:Pre-Depends},
+Description: Ceph distributed file system client library
+ Ceph is a distributed network file system designed to provide
+ excellent performance, reliability, and scalability. This is a
+ shared library allowing applications to access a Ceph distributed
+ file system via a POSIX-like interface.
-Package: librados2-dbg
+Package: librados-dev
Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: librados2 (= ${binary:Version}),
- ${misc:Depends},
-Description: debugging symbols for librados
+Section: libdevel
+Depends:
+ librados2 (= ${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Conflicts:
+ librados1-dev,
+ librados2-dev,
+Replaces:
+ librados1-dev,
+ librados2-dev,
+Description: RADOS distributed object store client library (development files)
RADOS is a reliable, autonomic distributed object storage cluster
developed as part of the Ceph distributed storage system. This is a
shared library allowing applications to access the distributed object
store using a simple file-like interface.
.
- This package contains debugging symbols for librados.
+ This package contains development files needed for building applications that
+ link against librados2.
-Package: librados-dev
+Package: librados2
Architecture: linux-any
-Section: libdevel
-Depends: librados2 (= ${binary:Version}),
- ${misc:Depends},
- ${shlibs:Depends},
-Conflicts: librados1-dev,
- librados2-dev,
-Replaces: librados1-dev,
- librados2-dev,
-Description: RADOS distributed object store client library (development files)
+Section: libs
+Conflicts:
+ librados,
+ librados1,
+Replaces:
+ librados,
+ librados1,
+Depends:
+ ${misc:Depends},
+ ${shlibs:Depends},
+Pre-Depends:
+ ${misc:Pre-Depends},
+Description: RADOS distributed object store client library
RADOS is a reliable, autonomic distributed object storage cluster
developed as part of the Ceph distributed storage system. This is a
shared library allowing applications to access the distributed object
store using a simple file-like interface.
- .
- This package contains development files needed for building applications that
- link against librados.
Package: libradospp-dev
Architecture: linux-any
Section: libdevel
-Depends: librados-dev (= ${binary:Version}),
- ${misc:Depends},
- ${shlibs:Depends},
+Depends:
+ librados-dev (= ${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
Description: RADOS distributed object store client C++ library (development files)
RADOS is a reliable, autonomic distributed object storage cluster
developed as part of the Ceph distributed storage system. This is a
@@ -743,73 +720,12 @@ Description: RADOS distributed object store client C++ library (development file
This package contains development files needed for building C++ applications that
link against librados.
-Package: libsqlite3-mod-ceph
-Architecture: any
-Section: libs
-Depends: librados2 (= ${binary:Version}),
- ${misc:Depends},
- ${shlibs:Depends},
-Description: SQLite3 VFS for Ceph
- A SQLite3 VFS for storing and manipulating databases stored on Ceph's RADOS
- distributed object store.
- .
- This packages contains the loadable extension module for SQLite3.
-
-Package: libsqlite3-mod-ceph-dbg
-Architecture: any
-Section: debug
-Priority: extra
-Depends: libsqlite3-mod-ceph (= ${binary:Version}),
- libsqlite3-0-dbgsym,
- ${misc:Depends},
-Description: debugging symbols for libsqlite3-mod-ceph
- A SQLite3 VFS for storing and manipulating databases stored on Ceph's RADOS
- distributed object store.
- .
- This package contains debugging symbols for libsqlite3-mod-ceph.
-
-Package: libsqlite3-mod-ceph-dev
-Architecture: any
-Section: libdevel
-Depends: libsqlite3-mod-ceph (= ${binary:Version}),
- libsqlite3-dev,
- ${misc:Depends},
-Description: SQLite3 VFS for Ceph (development files)
- A SQLite3 VFS for storing and manipulating databases stored on Ceph's RADOS
- distributed object store.
- .
- This package contains development files needed for building applications that
- link against libsqlite3-mod-ceph.
-
-Package: libradosstriper1
-Architecture: linux-any
-Section: libs
-Depends: librados2 (= ${binary:Version}),
- ${misc:Depends},
- ${shlibs:Depends},
-Description: RADOS striping interface
- Striping interface built on top of the rados library, allowing
- to stripe bigger objects onto several standard rados objects using
- an interface very similar to the rados one.
-
-Package: libradosstriper1-dbg
-Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: libradosstriper1 (= ${binary:Version}),
- ${misc:Depends},
-Description: debugging symbols for libradosstriper
- libradosstriper is a striping interface built on top of the rados
- library, allowing to stripe bigger objects onto several standard
- rados objects using an interface very similar to the rados one.
- .
- This package contains debugging symbols for libradosstriper.
-
Package: libradosstriper-dev
Architecture: linux-any
Section: libdevel
-Depends: libradosstriper1 (= ${binary:Version}),
- ${misc:Depends},
+Depends:
+ libradosstriper1 (= ${binary:Version}),
+ ${misc:Depends},
Description: RADOS striping interface (development files)
libradosstriper is a striping interface built on top of the rados
library, allowing to stripe bigger objects onto several standard
@@ -818,40 +734,29 @@ Description: RADOS striping interface (development files)
This package contains development files needed for building applications that
link against libradosstriper.
-Package: librbd1
+Package: libradosstriper1
Architecture: linux-any
Section: libs
-Depends: librados2 (= ${binary:Version}),
- ${misc:Depends},
- ${shlibs:Depends},
-Description: RADOS block device client library
- RBD is a block device striped across multiple distributed objects
- in RADOS, a reliable, autonomic distributed object storage cluster
- developed as part of the Ceph distributed storage system. This is a
- shared library allowing applications to manage these block devices.
-
-Package: librbd1-dbg
-Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: librbd1 (= ${binary:Version}),
- ${misc:Depends},
-Description: debugging symbols for librbd1
- RBD is a block device striped across multiple distributed objects
- in RADOS, a reliable, autonomic distributed object storage cluster
- developed as part of the Ceph distributed storage system. This is a
- shared library allowing applications to manage these block devices.
- .
- This package contains debugging symbols for librbd1.
+Depends:
+ librados2 (= ${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Description: RADOS striping interface
+ Striping interface built on top of the rados library, allowing
+ to stripe bigger objects onto several standard rados objects using
+ an interface very similar to the rados one.
Package: librbd-dev
Architecture: linux-any
Section: libdevel
-Depends: librados-dev (= ${binary:Version}),
- librbd1 (= ${binary:Version}),
- ${misc:Depends},
-Conflicts: librbd1-dev,
-Replaces: librbd1-dev,
+Depends:
+ librados-dev,
+ librbd1 (= ${binary:Version}),
+ ${misc:Depends},
+Conflicts:
+ librbd1-dev,
+Replaces:
+ librbd1-dev,
Description: RADOS block device client library (development files)
RBD is a block device striped across multiple distributed objects
in RADOS, a reliable, autonomic distributed object storage cluster
@@ -861,98 +766,28 @@ Description: RADOS block device client library (development files)
This package contains development files needed for building applications that
link against librbd1.
-Package: libcephfs2
-Conflicts: libceph,
- libceph1,
- libcephfs,
-Replaces: libceph,
- libceph1,
- libcephfs,
-Architecture: linux-any
-Section: libs
-Depends: ${misc:Depends},
- ${shlibs:Depends},
-Description: Ceph distributed file system client library
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage. This is a
- shared library allowing applications to access a Ceph distributed
- file system via a POSIX-like interface.
-
-Package: libcephfs2-dbg
-Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: libcephfs2 (= ${binary:Version}),
- ${misc:Depends},
-Conflicts: libceph1-dbg,
-Replaces: libceph1-dbg,
-Description: debugging symbols for libcephfs2
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage. This is a
- shared library allowing applications to access a Ceph distributed
- file system via a POSIX-like interface.
- .
- This package contains debugging symbols for libcephfs2.
-
-Package: libcephfs-dev
-Architecture: linux-any
-Section: libdevel
-Depends: libcephfs2 (= ${binary:Version}),
- ${misc:Depends},
-Conflicts: libceph-dev,
- libceph1-dev,
- libcephfs2-dev,
-Replaces: libceph-dev,
- libceph1-dev,
- libcephfs2-dev,
-Description: Ceph distributed file system client library (development files)
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage. This is a
- shared library allowing applications to access a Ceph distributed
- file system via a POSIX-like interface.
- .
- This package contains development files needed for building applications that
- link against libcephfs.
-
-Package: librgw2
+Package: librbd1
Architecture: linux-any
Section: libs
-Depends: librados2 (= ${binary:Version}),
- ${misc:Depends},
- ${shlibs:Depends},
- liblua5.3-dev,
- luarocks,
-Description: RADOS Gateway client library
- RADOS is a distributed object store used by the Ceph distributed
- storage system. This package provides a REST gateway to the
- object store that aims to implement a superset of Amazon's S3
- service.
- .
- This package contains the library interface and headers only.
-
-Package: librgw2-dbg
-Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: librgw2 (= ${binary:Version}),
- ${misc:Depends},
-Description: debugging symbols for librbd1
- RADOS is a distributed object store used by the Ceph distributed
- storage system. This package provides a REST gateway to the
- object store that aims to implement a superset of Amazon's S3
- service.
- .
- This package contains debugging symbols for librgw2.
+Depends:
+ librados2 (= ${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Pre-Depends:
+ ${misc:Pre-Depends},
+Description: RADOS block device client library
+ RBD is a block device striped across multiple distributed objects
+ in RADOS, a reliable, autonomic distributed object storage cluster
+ developed as part of the Ceph distributed storage system. This is a
+ shared library allowing applications to manage these block devices.
Package: librgw-dev
Architecture: linux-any
Section: libdevel
-Depends: librados-dev (= ${binary:Version}),
- librgw2 (= ${binary:Version}),
- ${misc:Depends},
+Depends:
+ librados-dev (= ${binary:Version}),
+ librgw2 (= ${binary:Version}),
+ ${misc:Depends},
Description: RADOS client library (development files)
RADOS is a distributed object store used by the Ceph distributed
storage system. This package provides a REST gateway to the
@@ -962,164 +797,154 @@ Description: RADOS client library (development files)
This package contains development files needed for building applications
that link against librgw2.
-Package: radosgw
+Package: librgw2
Architecture: linux-any
-Depends: ceph-common (= ${binary:Version}),
- librgw2 (= ${binary:Version}),
- mime-support,
- ${misc:Depends},
- ${shlibs:Depends},
-Suggests: gawk,
-Recommends: ntp | time-daemon,
-Description: REST gateway for RADOS distributed object store
+Section: libs
+Depends:
+ librados2 (= ${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Description: RADOS Gateway client library
RADOS is a distributed object store used by the Ceph distributed
storage system. This package provides a REST gateway to the
object store that aims to implement a superset of Amazon's S3
- service as well as the OpenStack Object Storage ("Swift") API.
+ service.
.
- This package contains the proxy daemon and related tools only.
+ This package contains the library interface and headers only.
-Package: radosgw-dbg
-Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: radosgw (= ${binary:Version}),
- ${misc:Depends},
-Description: debugging symbols for radosgw
- RADOS is a distributed object store used by the Ceph distributed
- storage system. This package provides a REST gateway to the
- object store that aims to implement a superset of Amazon's S3
- service as well as the OpenStack Object Storage ("Swift") API.
+Package: libsqlite3-mod-ceph
+Architecture: any
+Section: libs
+Depends:
+ ${misc:Depends},
+ ${shlibs:Depends},
+Description: SQLite3 VFS for Ceph
+ A SQLite3 VFS for storing and manipulating databases stored on Ceph's RADOS
+ distributed object store.
.
- This package contains debugging symbols for radosgw.
-
-Package: ceph-test
-Architecture: linux-any
-Depends: ceph-common,
- curl,
- jq,
- socat,
- xmlstarlet,
- ${misc:Depends},
- ${shlibs:Depends},
-Replaces: ceph-base (<< 11)
-Breaks: ceph-base (<< 1)
-Description: Ceph test and benchmarking tools
- This package contains tools for testing and benchmarking Ceph.
+ This packages contains the loadable extension module for SQLite3.
-Package: ceph-test-dbg
-Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: ceph-common (= ${binary:Version}),
- ceph-test (= ${binary:Version}),
- curl,
- ${misc:Depends},
-Description: Ceph test and benchmarking tools
+Package: libsqlite3-mod-ceph-dev
+Architecture: any
+Section: libdevel
+Depends:
+ libsqlite3-dev,
+ libsqlite3-mod-ceph (= ${binary:Version}),
+ ${misc:Depends},
+Description: SQLite3 VFS for Ceph (development files)
+ A SQLite3 VFS for storing and manipulating databases stored on Ceph's RADOS
+ distributed object store.
.
- This package contains the debugging symbols for ceph-test.
+ This package contains development files needed for building applications that
+ link against libsqlite3-mod-ceph.
Package: python3-ceph
-Architecture: linux-any
+Architecture: all
Section: python
-Depends: python3-cephfs (= ${binary:Version}),
- python3-rados (= ${binary:Version}),
- python3-rbd (= ${binary:Version}),
- python3-rgw (= ${binary:Version}),
-Description: Meta-package for python libraries for the Ceph libraries
+Depends:
+ python3-cephfs (<< ${source:Version}.1~),
+ python3-cephfs (>= ${source:Version}),
+ python3-rados (<< ${source:Version}.1~),
+ python3-rados (>= ${source:Version}),
+ python3-rbd (<< ${source:Version}.1~),
+ python3-rbd (>= ${source:Version}),
+ python3-rgw (<< ${source:Version}.1~),
+ python3-rgw (>= ${source:Version}),
+ ${misc:Depends},
+Description: Meta-package for all Python 3.x modules for the Ceph libraries
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
block and file system storage.
.
- This package is a metapackage for all Python 2 bindings.
+ This package is a metapackage for all Ceph Python 3.x bindings.
-Package: python3-rados
+Package: python3-ceph-argparse
Architecture: linux-any
Section: python
-Depends: librados2,
- ${misc:Depends},
- ${python3:Depends},
- ${shlibs:Depends},
-Description: Python 3 libraries for the Ceph librados library
+Depends:
+ ${misc:Depends},
+ ${python3:Depends},
+Description: Python 3 utility libraries for Ceph CLI
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
block and file system storage.
.
- This package contains Python 3 libraries for interacting with Ceph's
- RADOS object storage.
+ This package contains types and routines for Python 3 used by the
+ Ceph CLI as well as the RESTful interface.
-Package: python3-rados-dbg
-Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: python3-rados (= ${binary:Version}),
- python3-dbg,
- ${misc:Depends}
-Description: Python 3 libraries for the Ceph librados library
+Package: python3-ceph-common
+Architecture: all
+Section: python
+Depends:
+ ${misc:Depends},
+ ${python3:Depends},
+Description: Python 3 utility libraries for Ceph
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
block and file system storage.
.
- This package contains Python 3 libraries for interacting with Ceph's
- RADOS object storage.
- .
- This package contains the debugging symbols for python3-rados.
+ This package contains data structures, classes and functions used by Ceph.
+ It also contains utilities used for the cephadm orchestrator.
-Package: python3-rbd
+Package: python3-cephfs
Architecture: linux-any
Section: python
-Depends: librbd1 (>= ${binary:Version}),
- ${misc:Depends},
- ${python3:Depends},
- ${shlibs:Depends},
-Description: Python 3 libraries for the Ceph librbd library
+Depends:
+ libcephfs2 (= ${binary:Version}),
+ python3-ceph-argparse (= ${binary:Version}),
+ python3-rados (= ${binary:Version}),
+ ${misc:Depends},
+ ${python3:Depends},
+ ${shlibs:Depends},
+Description: Python 3 libraries for the Ceph libcephfs library
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
block and file system storage.
.
This package contains Python 3 libraries for interacting with Ceph's
- RBD block device library.
+ CephFS file system client library.
-Package: python3-rbd-dbg
+Package: python3-rados
Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: python3-rbd (= ${binary:Version}),
- python3-dbg,
- ${misc:Depends},
-Description: Python 3 libraries for the Ceph librbd library
+Section: python
+Depends:
+ librados2 (= ${binary:Version}),
+ ${misc:Depends},
+ ${python3:Depends},
+ ${shlibs:Depends},
+Description: Python 3 libraries for the Ceph librados library
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
block and file system storage.
.
This package contains Python 3 libraries for interacting with Ceph's
- RBD block device library.
- .
- This package contains the debugging symbols for python3-rbd.
+ RADOS object storage.
-Package: python3-rgw
+Package: python3-rbd
Architecture: linux-any
Section: python
-Depends: librgw2 (>= ${binary:Version}),
- python3-rados (= ${binary:Version}),
- ${misc:Depends},
- ${python3:Depends},
- ${shlibs:Depends},
-Description: Python 3 libraries for the Ceph librgw library
+Depends:
+ librbd1 (>= ${binary:Version}),
+ ${misc:Depends},
+ ${python3:Depends},
+ ${shlibs:Depends},
+Description: Python 3 libraries for the Ceph librbd library
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
block and file system storage.
.
This package contains Python 3 libraries for interacting with Ceph's
- RGW library.
+ RBD block device library.
-Package: python3-rgw-dbg
+Package: python3-rgw
Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: python3-rgw (= ${binary:Version}),
- python3-dbg,
- ${misc:Depends},
+Section: python
+Depends:
+ librgw2 (>= ${binary:Version}),
+ python3-rados (= ${binary:Version}),
+ ${misc:Depends},
+ ${python3:Depends},
+ ${shlibs:Depends},
Description: Python 3 libraries for the Ceph librgw library
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
@@ -1127,132 +952,71 @@ Description: Python 3 libraries for the Ceph librgw library
.
This package contains Python 3 libraries for interacting with Ceph's
RGW library.
- .
- This package contains the debugging symbols for python3-rgw.
-
-Package: python3-cephfs
-Architecture: linux-any
-Section: python
-Depends: libcephfs2 (= ${binary:Version}),
- python3-rados (= ${binary:Version}),
- python3-ceph-argparse (= ${binary:Version}),
- ${misc:Depends},
- ${python3:Depends},
- ${shlibs:Depends},
-Description: Python 3 libraries for the Ceph libcephfs library
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage.
- .
- This package contains Python 3 libraries for interacting with Ceph's
- CephFS file system client library.
-
-Package: python3-cephfs-dbg
-Architecture: linux-any
-Section: debug
-Priority: extra
-Depends: python3-cephfs (= ${binary:Version}),
- python3-dbg,
- ${misc:Depends},
-Description: Python 3 libraries for the Ceph libcephfs library
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage.
- .
- This package contains Python 3 libraries for interacting with Ceph's
- CephFS file system client library.
- .
- This package contains the debugging symbols for python3-cephfs.
-
-Package: python3-ceph-argparse
-Architecture: all
-Section: python
-Depends: ${misc:Depends},
- ${python3:Depends},
-Description: Python 3 utility libraries for Ceph CLI
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage.
- .
- This package contains types and routines for Python 3 used by the
- Ceph CLI as well as the RESTful interface.
-
-Package: python3-ceph-common
-Architecture: all
-Section: python
-Depends: ${misc:Depends},
- ${python3:Depends},
-Description: Python 3 utility libraries for Ceph
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage.
- .
- This package contains data structures, classes and functions used by Ceph.
- It also contains utilities used for the cephadm orchestrator.
-
-Package: libcephfs-java
-Section: java
-Architecture: all
-Depends: libcephfs-jni (= ${binary:Version}),
- ${java:Depends},
- ${misc:Depends},
-Description: Java libraries for the Ceph File System
-
-Package: libcephfs-jni
-Architecture: linux-any
-Section: java
-Depends: libcephfs2 (= ${binary:Version}),
- ${java:Depends},
- ${misc:Depends},
- ${shlibs:Depends},
-Description: Java Native Interface library for CephFS Java bindings
Package: rados-objclass-dev
Architecture: linux-any
Section: libdevel
-Depends: librados-dev (= ${binary:Version}), ${misc:Depends},
+Depends:
+ librados-dev (= ${binary:Version}),
+ ${misc:Depends},
Description: RADOS object class development kit.
.
This package contains development files needed for building RADOS object class plugins.
-Package: cephfs-shell
-Architecture: all
-Depends: ${misc:Depends},
- ${python3:Depends}
-Description: interactive shell for the Ceph distributed file system
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage. This is an interactive tool that
- allows accessing a Ceph file system without mounting it by providing
- a nice pseudo-shell which works like an FTP client.
+Package: radosgw
+Architecture: linux-any
+Depends:
+ ceph-common (= ${binary:Version}),
+ librgw2 (= ${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Suggests:
+ logrotate,
+Description: REST gateway for RADOS distributed object store
+ RADOS is a distributed object store used by the Ceph distributed
+ storage system. This package provides a REST gateway to the
+ object store that aims to implement a superset of Amazon's S3
+ service as well as the OpenStack Object Storage ("Swift") API.
.
- This package contains a CLI for interacting with the CephFS.
+ This package contains the proxy daemon and related tools only.
-Package: cephfs-top
-Architecture: all
-Depends: ${misc:Depends},
- ${python3:Depends}
-Description: This package provides a top(1) like utility to display various
- filesystem metrics in realtime.
- .
- This package contains utility for displaying filesystem metrics.
+Package: rbd-fuse
+Architecture: linux-any
+Depends:
+ ${misc:Depends},
+ ${shlibs:Depends},
+Recommends:
+ fuse,
+Description: FUSE-based rbd client for the Ceph distributed file system
+ Ceph is a distributed network file system designed to provide
+ excellent performance, reliability, and scalability. This is a
+ FUSE-based client that allows one to map Ceph rbd images as files.
-Package: ceph-grafana-dashboards
-Architecture: all
-Description: grafana dashboards for the ceph dashboard
- Ceph is a massively scalable, open-source, distributed
- storage system that runs on commodity hardware and delivers object,
- block and file system storage.
+Package: rbd-mirror
+Architecture: linux-any
+Depends:
+ ceph-common (= ${binary:Version}),
+ librados2 (= ${binary:Version}),
+ ${misc:Depends},
+ ${shlibs:Depends},
+Description: Ceph daemon for mirroring RBD images
+ Ceph is a distributed storage system designed to provide excellent
+ performance, reliability, and scalability.
.
- This package contains Grafana dashboards that are used by the Ceph Dashboard
- for monitoring.
+ This package provides a daemon for mirroring RBD images between
+ Ceph clusters, streaming changes asynchronously.
-Package: ceph-prometheus-alerts
-Architecture: all
-Description: prometheus alerts for the ceph dashboard
+Package: rbd-nbd
+Architecture: linux-any
+Depends:
+ ${misc:Depends},
+ ${shlibs:Depends},
+Description: NBD-based rbd client for the Ceph distributed file system
Ceph is a massively scalable, open-source, distributed
storage system that runs on commodity hardware and delivers object,
- block and file system storage.
+ block and file system storage. This is a
+ NBD-based client that allows one to map Ceph rbd images as local
+ block device.
.
- This package contains alerts used for prometheus to interact with the
- Ceph Dashboard.
+ NBD base client that allows one to map Ceph rbd images as local
+ block device.
diff --git a/debian/copyright b/debian/copyright
index 8dc4b9e4f..39eb7bb69 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -1,11 +1,43 @@
-Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: ceph
-Upstream-Contact: Ceph Developers <dev@ceph.io>
+Upstream-Contact: Sage Weil <sage@newdream.net>
Source: http://ceph.com/
+Files-Excluded:
+ debian
+ src/rapidjson/bin/jsonchecker/*
+ */DotZLib.chm
+ src/rocksdb/docs/*
+ qa/workunits/erasure-code/jquery.flot.js
+ */jquery.js
+ src/civetweb/src/third_party/duktape*
+ src/civetweb/examples/_obsolete/websocket_client/ssl/server.key.orig
+ src/civetweb/resources/cert/client.key.orig
+ src/civetweb/resources/cert/server.key.orig
+ src/civetweb/resources/cert/server_bkup.key.orig
+ src/erasure-code/jerasure/jerasure/Examples/makefile.orig
+ src/erasure-code/jerasure/jerasure/include/config.h.in~
+ src/erasure-code/jerasure/jerasure/makefile.orig
Files: *
-Copyright: (c) 2004-2010 by Sage Weil <sage@newdream.net>
-License: LGPL-2.1 or LGPL-3 (see COPYING-LGPL2.1 and COPYING-LGPL3)
+Copyright: 2004-2014 Sage Weil <sage@newdream.net>
+ 2004-2014 Inktank <info@inktank.com>
+ Inktank, Inc
+ Inktank Storage, Inc.
+ 2012-2014 Red Hat <contact@redhat.com>
+ 2013-2014 Cloudwatt <libre.licensing@cloudwatt.com>
+ 2013 CohortFS, LLC
+ 2004-2011 Dreamhost
+ 2013 eNovance SAS <licensing@enovance.com>
+ 2014 Adam Crume <adamcrume@gmail.com>
+ 2012 Florian Haas, hastexo
+ 2010 Greg Farnum <gregf@hq.newdream.net>
+ 2014 John Spray <john.spray@inktank.com
+ 2004-2012 New Dream Network
+ 2014 Sebastien Ponce <sebastien.ponce@cern.ch>
+ 2011 Stanislav Sedov <stas@FreeBSD.org>
+ 2013-2014 UnitedStack <haomai@unitedstack.com>
+ 2011 Wido den Hollander <wido@widodh.nl>
+License: LGPL2.1 (see COPYING-LGPL2.1)
Files: cmake/modules/FindLTTngUST.cmake
Copyright:
@@ -22,7 +54,8 @@ License: GPL3
Files: src/mount/canonicalize.c
Copyright: Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
-License: LGPL-2 or later
+License: LGPL2 or later (see COPYING-GPL2)
+
Files: src/os/btrfs_ioctl.h
Copyright: Copyright (C) 2007 Oracle. All rights reserved.
@@ -41,12 +74,6 @@ Copyright:
Copyright 2012-2013 Intel Corporation All Rights Reserved.
License: BSD 3-clause
-Files: src/common/deleter.h
-Copyright:
- Copyright (C) 2014 Cloudius Systems, Ltd.
-License:
- Apache-2.0
-
Files: src/common/sctp_crc32.c:
Copyright:
Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
@@ -54,18 +81,18 @@ Copyright:
License:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
+ .
a) Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
+ .
b) Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
-
+ .
c) Neither the name of Cisco Systems, Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
-
+ .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -78,26 +105,14 @@ License:
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
-Files: src/common/sstring.hh
-Copyright:
- Copyright 2014 Cloudius Systems
-License:
- Apache-2.0
-
-Files: src/include/cpp-btree
-Copyright:
- Copyright 2013 Google Inc. All Rights Reserved.
-License:
- Apache-2.0
-
Files: src/json_spirit
Copyright:
Copyright John W. Wilkinson 2007 - 2011
License:
The MIT License
-
+ .
Copyright (c) 2007 - 2010 John W. Wilkinson
-
+ .
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
@@ -106,10 +121,10 @@ License:
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
-
+ .
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
-
+ .
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -121,7 +136,9 @@ License:
Files: src/test/common/Throttle.cc src/test/filestore/chain_xattr.cc
Copyright: Copyright (C) 2013 Cloudwatt <libre.licensing@cloudwatt.com>
-License: LGPL-2.1 or later
+License: LGPL2.1 or later
+
+
Files: src/osd/ErasureCodePluginJerasure/*.{c,h}
Copyright: Copyright (c) 2011, James S. Plank <plank@cs.utk.edu>
@@ -129,19 +146,19 @@ License:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
-
+ .
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
-
+ .
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
-
+ .
- Neither the name of the University of Tennessee nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
-
+ .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -155,10 +172,28 @@ License:
WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-Packaging:
- Copyright (C) 2004-2009 by Sage Weil <sage@newdream.net>
- Copyright (C) 2010 Canonical, Ltd.
- Licensed under LGPL-2.1 or LGPL-3.0
+
+Files: qa/workunits/erasure-code/jquery.js
+Copyright: 2012 jQuery Foundation and other contributors
+License: MIT
+
+Files: qa/workunits/erasure-code/jquery.{flot.categories,flot}.js
+Copyright: 2007-2014 IOLA and Ole Laursen.
+License: MIT
+
+Files: src/include/timegm.h
+Copyright: Howard Hinnant
+ 2010-2011 Vicente J. Botet Escriba
+License: Boost Software License, Version 1.0
+
+Files: src/pybind/mgr/diskprediction_local/models/*
+Copyright: None
+License: Public domain
+
+Files: src/ceph-volume/plugin/zfs/*
+Copyright: 2018, Willem Jan Withagen
+License: BSD 3-clause
+
Files: src/test/perf_local.cc
Copyright:
@@ -167,20 +202,188 @@ Copyright:
License:
The MIT License
-File: qa/workunits/erasure-code/jquery.js
- Copyright 2012 jQuery Foundation and other contributors
- Released under the MIT license
- http://jquery.org/license
-Files: qa/workunits/erasure-code/jquery.{flot.categories,flot}.js
- Copyright (c) 2007-2014 IOLA and Ole Laursen.
- Licensed under the MIT license.
+Comment: -----------------------------------------------
+ Content above is taken from upstream's COPYING file.
+ Unfortunately it is incomplete. Debian/Ubuntu packaging
+ findings/additions are below.
+ -------------------------------------------------------
+
+
+Files: src/erasure-code/jerasure/ErasureCode*
+ src/erasure-code/ErasureCode*
+ src/erasure-code/isa/*
+ src/include/str_map.h
+ src/test/common/test_str_map.cc
+ src/test/erasure-code/*
+ src/test/rgw/test_rgw_manifest.cc
+Copyright: 2014 CERN/Switzerland
+ 2013-2014 Cloudwatt <libre.licensing@cloudwatt.com>
+ 2014 Red Hat <contact@redhat.com>
+ 2013 eNovance SAS <licensing@enovance.com>
+License: LGPL-2.1+
+
+
+Files: src/erasure-code/isa/isa-l/erasure_code/*
+Copyright: 2011-2014 Intel Corporation
+License: BSD-3-clause
+
+Files: src/rocksdb/*
+Copyright: 2004-2013 Facebook, Inc.
+ 2011 The LevelDB Authors
+ 2009 Google Inc.
+License: BSD-3-clause
+Comment:
+ Additional Grant of Patent Rights
+ .
+ “Software” means the rocksdb software distributed by Facebook, Inc.
+ .
+ Facebook hereby grants you a perpetual, worldwide, royalty-free,
+ non-exclusive, irrevocable (subject to the termination provision below)
+ license under any rights in any patent claims owned by Facebook, to make,
+ have made, use, sell, offer to sell, import, and otherwise transfer the
+ Software. For avoidance of doubt, no license is granted under Facebook’s
+ rights in any patent claims that are infringed by (i) modifications to the
+ Software made by you or a third party, or (ii) the Software in combination
+ with any software or other technology provided by you or a third party.
+ .
+ The license granted hereunder will terminate, automatically and without
+ notice, for anyone that makes any claim (including by filing any lawsuit,
+ assertion or other action) alleging (a) direct, indirect, or contributory
+ infringement or inducement to infringe any patent: (i) by Facebook or any
+ of its subsidiaries or affiliates, whether or not such claim is related
+ to the Software, (ii) by any party if such claim arises in whole or in
+ part from any software, product or service of Facebook or any of its
+ subsidiaries or affiliates, whether or not such claim is related to the
+ Software, or (iii) by any party relating to the Software; or (b) that
+ any right in any patent claim of Facebook is invalid or unenforceable.
+
+
+Files: src/rocksdb/util/xxhash.*
+Copyright: 2012-2014, Yann Collet.
+License: BSD-2-clause
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ .
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+ .
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-Files: src/include/timegm.h
- Copyright (C) Copyright Howard Hinnant
- Copyright (C) Copyright 2010-2011 Vicente J. Botet Escriba
- License: Boost Software License, Version 1.0
+
+Files: src/mount/canonicalize.c
+ src/test/common/test_config.cc
+ src/test/crush/TestCrushWrapper.cc
+ src/test/common/Throttle.cc
+ src/test/objectstore/chain_xattr.cc
+ src/test/mon/mon-test-helpers.sh
+ src/test/objectstore/chain_xattr.cc
+ src/test/osd/osd-test-helpers.sh
+ src/ceph-disk
+ src/stop.sh
+Copyright: 1993 Rick Sladkey <jrs@world.std.com>
+ 2013 Inktank <info@inktank.com>
+ 2013-2014 Cloudwatt <libre.licensing@cloudwatt.com>
+License: LGPL-2+
+
+Files: src/os/btrfs_ioctl.h
+ src/test/mon/PGMap.cc
+Copyright: 2007 Oracle. All rights reserved.
+ 2014 Inktank <info@inktank.com>
+License: GPL-2
+
+Files: src/common/ceph_hash.cc
+Copyright: 1995-1997 Robert J. Jenkins Jr.
+License: public-domain
+ This file uses Robert Jenkin's hash function as detailed at:
+ .
+ http://burtleburtle.net/bob/hash/evahash.html
+ .
+ This is in the public domain.
+
+Files: src/common/bloom_filter.hpp
+Copyright: 2000 Arash Partow
+License: Boost-Software-License-1.0
+ Permission is hereby granted, free of charge, to any person or organization
+ obtaining a copy of the software and accompanying documentation covered by
+ this license (the "Software") to use, reproduce, display, distribute,
+ execute, and transmit the Software, and to prepare derivative works of the
+ Software, and to permit third-parties to whom the Software is furnished to
+ do so, all subject to the following:
+ .
+ The copyright notices in the Software and this entire statement,
+ including the above license grant, this restriction and the following
+ disclaimer, must be included in all copies of the Software, in whole or
+ in part, and all derivative works of the Software, unless such copies
+ or derivative works are solely in the form of machine-executable object
+ code generated by a source language processor.
+ .
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+ SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+ FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+Files: src/common/crc32c_intel*
+Copyright: 2012-2013 Intel Corporation All Rights Reserved.
+License: BSD-3-clause
+
+Files: src/common/sctp_crc32.c
+Copyright: 2001-2007, by Cisco Systems, Inc. All rights reserved,
+ 2004-2006 Intel Corporation - All Rights Reserved
+License: BSD-3-clause
+
+Files: src/erasure-code/jerasure/gf-complete/*/*
+Copyright: 2013 James S. Plank
+ Ethan L. Miller
+ Kevin M. Greenan
+ Benjamin A. Arnold
+ John A. Burnum
+ Adam W. Disney
+ Allen C. McBride
+License: BSD-3-clause
+Comment:
+ https://bitbucket.org/jimplank/gf-complete
+
+Files: src/erasure-code/jerasure/jerasure/*/*
+Copyright: 2011-2013 James S. Plank <plank@cs.utk.edu>
+ 2013 Kevin Greenan
+License: BSD-3-clause
+
+Files: src/gtest/*
+Copyright: 2008, Google Inc.
+License: BSD-3-clause
+
+Files: src/civetweb/*
+Copyright: 2004-2013 Sergey Lyubka
+ 2013-2014 the Civetweb developers
+License: Expat
+
+Files: src/json_spirit/*
+Copyright: 2007-2011, John W. Wilkinson
+License: Expat
+
+Files: src/java/native/ScopedLocalRef.h
+ src/java/native/JniConstants.*
+Copyright: 2010 The Android Open Source Project
License: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -197,6 +400,76 @@ License: Apache-2.0
The complete text of the Apache License, Version 2.0
can be found in "/usr/share/common-licenses/Apache-2.0".
+Files: src/libs3/*
+Copyright: 2008 Bryan Ischo <bryan@ischo.com>
+License: GPL-3/OpenSSL
+ libs3 is free software: you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation, version 3 of the License.
+ .
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this library and its programs with the
+ OpenSSL library, and distribute linked combinations including the two.
+ .
+ libs3 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 General Public License for more
+ details.
+ .
+ The complete text of the GNU General Public License version 3
+ can be found in "/usr/share/common-licenses/GPL-3' file.
+
+
+Files: src/mount/mtab.c
+Copyright: util-linux-ng AUTHORS
+License: GPL-2+
+Comment:
+ "mount/fstab.c" from line 559:
+ https://git.kernel.org/cgit/utils/util-linux/util-linux.git/tree/mount-deprecated/fstab.c?h=v2.22#n559
+ https://git.kernel.org/cgit/utils/util-linux/util-linux.git/tree/README.licensing
+
+Files: src/test/librbd/fsx.c
+Copyright: 1991, NeXT Computer, Inc.
+License: APSL-2.0
+ The contents of this file constitute Original Code as defined in and
+ are subject to the Apple Public Source License Version 2.0 (the
+ "License"). You may not use this file except in compliance with the
+ License. Please obtain a copy of the License at
+ http://www.opensource.apple.com/apsl/ and read it before using this file.
+ .
+ This Original Code and all software distributed under the License are
+ distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
+ License for the specific language governing rights and limitations
+ under the License.
+Comment:
+ http://codemonkey.org.uk/projects/fsx/
+ http://codemonkey.org.uk/projects/fsx/fsx-macosforge/fsx.c
+
+Files: man/*
+ debian/man/*
+Copyright: 2010-2014, Inktank Storage, Inc. and contributors.
+License: CC-BY-SA-3.0
+
+
+Files: debian/missing-sources/bootstrap.js
+Copyright: 2011-2015 Twitter, Inc
+License: MIT
+
+Files: debian/missing-sources/two.js
+Copyright: 2012 - 2017 jonobr1 / http://jonobr1.com
+License: MIT
+
+Files: debian/*
+Copyright: 2010 Sage Weil <sage@newdream.net>
+ 2010 Canonical, Ltd.
+ 2011-2013 László Böszörményi (GCS) <gcs@debian.org>
+ 2013-2014 James Page <james.page@ubuntu.com>
+ 2014 Dmitry Smirnov <onlyjob@debian.org>
+ 2019 Bernd Zeimetz <bzed@debian.org>
+License: LGPL-2.1
License: GPL-2
This program is free software; you can redistribute it and/or modify
@@ -233,23 +506,6 @@ License: GPL-2+
On Debian systems, the complete text of the GNU General Public License
version 2 can be found in `/usr/share/common-licenses/GPL-2'.
-License: GPL-3+
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- .
- This program 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 General Public License for more details.
- .
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- .
- On Debian systems, the complete text of the GNU General Public
- License version 3 can be found in `/usr/share/common-licenses/GPL-3'.
-
License: LGPL-2.1
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -302,7 +558,7 @@ License: LGPL-2+
On Debian systems, the complete text of the GNU Lesser General
Public License 2 can be found in `/usr/share/common-licenses/LGPL-2'.
-License: MIT
+License: Expat
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
@@ -320,6 +576,10 @@ License: MIT
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+Comment:
+ This license also known as "MIT" however FSF consider "MIT" labelling
+ ambiguous and copyright-format specification recommend to label such license
+ as "Expat".
License: CC-BY-SA-3.0
Creative Commons Attribution-ShareAlike 3.0 Unported
diff --git a/debian/crimson-osd.install b/debian/crimson-osd.install
new file mode 100644
index 000000000..621ac634b
--- /dev/null
+++ b/debian/crimson-osd.install
@@ -0,0 +1 @@
+usr/bin/crimson-osd
diff --git a/debian/gbp.conf b/debian/gbp.conf
new file mode 100644
index 000000000..2d42999c8
--- /dev/null
+++ b/debian/gbp.conf
@@ -0,0 +1,3 @@
+[DEFAULT]
+debian-branch = ubuntu/oracular
+pristine-tar = True
diff --git a/debian/lib-systemd/system-sleep/ceph b/debian/lib-systemd/system-sleep/ceph
new file mode 100755
index 000000000..cf62f8321
--- /dev/null
+++ b/debian/lib-systemd/system-sleep/ceph
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+#/lib/systemd/system-sleep/ceph
+
+case $1 in
+pre)
+ /bin/systemctl stop ceph
+;;
+post)
+ /bin/systemctl start ceph
+;;
+esac
diff --git a/debian/lib-systemd/system/ceph-create-keys.service b/debian/lib-systemd/system/ceph-create-keys.service
new file mode 100644
index 000000000..4e29bc1e9
--- /dev/null
+++ b/debian/lib-systemd/system/ceph-create-keys.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Create Ceph client.admin key when possible
+PartOf=ceph-mon.service
+
+[Service]
+Environment=CLUSTER=ceph
+Environment=CONFIG=/etc/ceph/ceph.conf
+EnvironmentFile=-/etc/default/ceph
+ExecStart=/usr/sbin/ceph-create-keys --cluster ${CLUSTER} --id %H
diff --git a/debian/lib-systemd/system/ceph-mds.service b/debian/lib-systemd/system/ceph-mds.service
new file mode 100644
index 000000000..86ff057f1
--- /dev/null
+++ b/debian/lib-systemd/system/ceph-mds.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=Ceph metadata server daemon (MDS)
+Documentation=man:ceph-mds
+After=network-online.target nss-lookup.target
+Wants=network-online.target nss-lookup.target
+PartOf=ceph.target
+
+[Service]
+LimitNOFILE=1048576
+LimitNPROC=1048576
+EnvironmentFile=-/etc/default/ceph
+Environment=CLUSTER=ceph
+ExecStart=/usr/bin/ceph-mds -f --cluster ${CLUSTER} --id %H --setuser ceph --setgroup ceph
+
+[Install]
+WantedBy=multi-user.target
diff --git a/debian/lib-systemd/system/ceph-mon.service b/debian/lib-systemd/system/ceph-mon.service
new file mode 100644
index 000000000..d89c74a64
--- /dev/null
+++ b/debian/lib-systemd/system/ceph-mon.service
@@ -0,0 +1,22 @@
+[Unit]
+Description=Ceph cluster monitor daemon
+Documentation=man:ceph-mon
+
+After=network-online.target local-fs.target ceph-create-keys.service
+Wants=network-online.target local-fs.target ceph-create-keys.service
+
+PartOf=ceph.target
+
+[Service]
+LimitNOFILE=1048576
+LimitNPROC=1048576
+EnvironmentFile=-/etc/default/ceph
+Environment=CLUSTER=ceph
+ExecStart=/usr/bin/ceph-mon -f --cluster ${CLUSTER} --id %H --setuser ceph --setgroup ceph
+ExecReload=/bin/kill -HUP $MAINPID
+Restart=on-failure
+RestartSec=30
+TasksMax=infinity
+
+[Install]
+WantedBy=multi-user.target
diff --git a/debian/lib-systemd/system/ceph-osd@.service b/debian/lib-systemd/system/ceph-osd@.service
new file mode 100644
index 000000000..adfa6a02f
--- /dev/null
+++ b/debian/lib-systemd/system/ceph-osd@.service
@@ -0,0 +1,22 @@
+[Unit]
+Description=Ceph object storage daemon (OSD)
+Documentation=man:ceph-osd
+After=network-online.target
+Wants=network-online.target
+PartOf=ceph.service
+RequiresMountsFor=/var/lib/ceph/osd/ceph-%i
+
+[Service]
+Environment=CLUSTER=ceph
+Environment=CONFIG=/etc/ceph/ceph.conf
+EnvironmentFile=-/etc/default/ceph
+ExecStartPre=-/bin/sh -c '${osd_prestart_sh}' -- %i
+ExecStartPre=/usr/lib/ceph/ceph-osd-prestart.sh --id %i --cluster ${CLUSTER}
+ExecStart=/usr/bin/ceph-osd --id %i --foreground --cluster ${CLUSTER} -c ${CONFIG}
+ExecStopPost=-/bin/sh -c '${osd_poststop_sh}' -- %i
+LimitNOFILE=327680
+Restart=on-failure
+RestartSec=30
+
+[Install]
+WantedBy=multi-user.target
diff --git a/debian/libcephfs-dev.install b/debian/libcephfs-dev.install
index cf22dce62..7674931a5 100644
--- a/debian/libcephfs-dev.install
+++ b/debian/libcephfs-dev.install
@@ -1,5 +1,4 @@
usr/include/cephfs/ceph_ll_client.h
usr/include/cephfs/libcephfs.h
-usr/include/cephfs/types.h
usr/include/cephfs/metrics/Types.h
-usr/lib/libcephfs.so
+usr/lib/*/libcephfs.so
diff --git a/debian/libcephfs-jni.install b/debian/libcephfs-jni.install
index 072b99033..15cb91d90 100644
--- a/debian/libcephfs-jni.install
+++ b/debian/libcephfs-jni.install
@@ -1 +1 @@
-usr/lib/libcephfs_jni.so* usr/lib/jni
+usr/lib/*/libcephfs_jni.so* usr/lib/jni
diff --git a/debian/libcephfs-jni.lintian-overrides b/debian/libcephfs-jni.lintian-overrides
new file mode 100644
index 000000000..93a0dacaf
--- /dev/null
+++ b/debian/libcephfs-jni.lintian-overrides
@@ -0,0 +1 @@
+binary-or-shlib-defines-rpath usr/lib/jni/*
diff --git a/debian/libcephfs2.install b/debian/libcephfs2.install
index b7c0eb058..f09e93ca5 100644
--- a/debian/libcephfs2.install
+++ b/debian/libcephfs2.install
@@ -1 +1 @@
-usr/lib/libcephfs.so.*
+usr/lib/*/libcephfs.so.*
diff --git a/debian/libcephfs2.lintian-overrides b/debian/libcephfs2.lintian-overrides
new file mode 100644
index 000000000..d4041ca8e
--- /dev/null
+++ b/debian/libcephfs2.lintian-overrides
@@ -0,0 +1,2 @@
+# False-positives:
+spelling-error-in-binary * tEH the
diff --git a/debian/libcephfs2.symbols b/debian/libcephfs2.symbols
new file mode 100644
index 000000000..8471417d0
--- /dev/null
+++ b/debian/libcephfs2.symbols
@@ -0,0 +1,206 @@
+libcephfs.so.2 libcephfs2 #MINVER#
+ (regex|c++)"^_.*" 12.0.3
+ ceph_abort_conn@Base 14.2.0
+ ceph_buffer_free@Base 12.0.3
+ ceph_chdir@Base 12.0.3
+ ceph_chmod@Base 12.0.3
+ ceph_chmodat@Base 17.0.0~
+ ceph_chown@Base 12.0.3
+ ceph_chownat@Base 17.0.0~
+ ceph_close@Base 12.0.3
+ ceph_closedir@Base 12.0.3
+ ceph_conf_get@Base 12.0.3
+ ceph_conf_parse_argv@Base 12.0.3
+ ceph_conf_parse_env@Base 12.0.3
+ ceph_conf_read_file@Base 12.0.3
+ ceph_conf_set@Base 12.0.3
+ ceph_create@Base 12.0.3
+ ceph_create_from_rados@Base 12.0.3
+ ceph_create_with_context@Base 12.0.3
+ ceph_debug_get_fd_caps@Base 12.0.3
+ ceph_debug_get_file_caps@Base 12.0.3
+ ceph_fallocate@Base 12.0.3
+ ceph_fchmod@Base 12.0.3
+ ceph_fchown@Base 12.0.3
+ ceph_fdopendir@Base 17.0.0~
+ ceph_fgetxattr@Base 12.0.3
+ ceph_finish_reclaim@Base 14.2.0
+ ceph_flistxattr@Base 12.0.3
+ ceph_flock@Base 12.0.3
+ ceph_free_snap_info_buffer@Base 16.0.0
+ ceph_fremovexattr@Base 12.0.3
+ ceph_fsetattrx@Base 12.0.3
+ ceph_fsetxattr@Base 12.0.3
+ ceph_fstat@Base 14.2.0
+ ceph_fstatx@Base 12.0.3
+ ceph_fsync@Base 12.0.3
+ ceph_ftruncate@Base 12.0.3
+ ceph_futime@Base 14.2.0
+ ceph_futimens@Base 14.2.0
+ ceph_futimes@Base 14.2.0
+ ceph_get_cap_return_timeout@Base 13.2.0
+ ceph_get_default_data_pool_name@Base 12.1.4
+ ceph_get_file_extent_osds@Base 12.0.3
+ ceph_get_file_layout@Base 12.0.3
+ ceph_get_file_object_size@Base 12.0.3
+ ceph_get_file_pool@Base 12.0.3
+ ceph_get_file_pool_name@Base 12.0.3
+ ceph_get_file_replication@Base 12.0.3
+ ceph_get_file_stripe_address@Base 12.0.3
+ ceph_get_file_stripe_count@Base 12.0.3
+ ceph_get_file_stripe_unit@Base 12.0.3
+ ceph_get_fs_cid@Base 14.2.0
+ ceph_get_instance_id@Base 14.2.0
+ ceph_get_local_osd@Base 12.0.3
+ ceph_get_mount_context@Base 12.0.3
+ ceph_get_osd_addr@Base 12.0.3
+ ceph_get_osd_crush_location@Base 12.0.3
+ ceph_get_path_layout@Base 12.0.3
+ ceph_get_path_object_size@Base 12.0.3
+ ceph_get_path_pool@Base 12.0.3
+ ceph_get_path_pool_name@Base 12.0.3
+ ceph_get_path_replication@Base 12.0.3
+ ceph_get_path_stripe_count@Base 12.0.3
+ ceph_get_path_stripe_unit@Base 12.0.3
+ ceph_get_pool_id@Base 12.0.3
+ ceph_get_pool_name@Base 12.0.3
+ ceph_get_pool_replication@Base 12.0.3
+ ceph_get_snap_info@Base 16.0.0
+ ceph_get_stripe_unit_granularity@Base 12.0.3
+ ceph_getaddrs@Base 15.1.0
+ ceph_getcwd@Base 12.0.3
+ ceph_getdents@Base 12.0.3
+ ceph_getdnames@Base 12.0.3
+ ceph_getxattr@Base 12.0.3
+ ceph_init@Base 12.0.3
+ ceph_is_mounted@Base 12.0.3
+ ceph_lazyio@Base 14.2.0
+ ceph_lazyio_propagate@Base 15.1.0
+ ceph_lazyio_synchronize@Base 15.1.0
+ ceph_lchmod@Base 17.0.0~
+ ceph_lchown@Base 12.0.3
+ ceph_lgetxattr@Base 12.0.3
+ ceph_link@Base 12.0.3
+ ceph_listxattr@Base 12.0.3
+ ceph_ll_close@Base 12.0.3
+ ceph_ll_commit_blocks@Base 12.0.3
+ ceph_ll_create@Base 12.0.3
+ ceph_ll_delegation@Base 13.2.0
+ ceph_ll_fallocate@Base 14.2.0
+ ceph_ll_file_layout@Base 12.0.3
+ ceph_ll_forget@Base 12.0.3
+ ceph_ll_fsync@Base 12.0.3
+ ceph_ll_get_inode@Base 12.0.3
+ ceph_ll_get_internal_offset@Base 12.0.3
+ ceph_ll_get_stripe_osd@Base 12.0.3
+ ceph_ll_getattr@Base 12.0.3
+ ceph_ll_getlk@Base 12.0.3
+ ceph_ll_getxattr@Base 12.0.3
+ ceph_ll_lazyio@Base 14.2.0
+ ceph_ll_link@Base 12.0.3
+ ceph_ll_listxattr@Base 12.0.3
+ ceph_ll_lookup@Base 12.0.3
+ ceph_ll_lookup_inode@Base 12.0.3
+ ceph_ll_lookup_root@Base 12.0.3
+ ceph_ll_lookup_vino@Base 17.0.0~
+ ceph_ll_lseek@Base 12.0.3
+ ceph_ll_mkdir@Base 12.0.3
+ ceph_ll_mknod@Base 12.0.3
+ ceph_ll_num_osds@Base 12.0.3
+ ceph_ll_open@Base 12.0.3
+ ceph_ll_opendir@Base 12.0.3
+ ceph_ll_osdaddr@Base 12.0.3
+ ceph_ll_put@Base 12.0.3
+ ceph_ll_read@Base 12.0.3
+ ceph_ll_read_block@Base 12.0.3
+ ceph_ll_readlink@Base 12.0.3
+ ceph_ll_readv@Base 12.0.3
+ ceph_ll_register_callbacks2@Base 17.0.0~
+ ceph_ll_register_callbacks@Base 16.0.0
+ ceph_ll_releasedir@Base 12.0.3
+ ceph_ll_removexattr@Base 12.0.3
+ ceph_ll_rename@Base 12.0.3
+ ceph_ll_rmdir@Base 12.0.3
+ ceph_ll_setattr@Base 12.0.3
+ ceph_ll_setlk@Base 12.0.3
+ ceph_ll_setxattr@Base 12.0.3
+ ceph_ll_snap_seq@Base 12.0.3
+ ceph_ll_statfs@Base 12.0.3
+ ceph_ll_stripe_unit@Base 12.0.3
+ ceph_ll_symlink@Base 12.0.3
+ ceph_ll_sync_inode@Base 13.2.0
+ ceph_ll_unlink@Base 12.0.3
+ ceph_ll_walk@Base 12.0.3
+ ceph_ll_write@Base 12.0.3
+ ceph_ll_write_block@Base 12.0.3
+ ceph_ll_writev@Base 12.0.3
+ ceph_llistxattr@Base 12.0.3
+ ceph_localize_reads@Base 12.0.3
+ ceph_lremovexattr@Base 12.0.3
+ ceph_lseek@Base 12.0.3
+ ceph_lsetxattr@Base 12.0.3
+ ceph_lstat@Base 14.2.0
+ ceph_lutimes@Base 14.2.0
+ ceph_may_delete@Base 17.0.0~
+ ceph_mds_command@Base 12.0.3
+ ceph_mkdir@Base 12.0.3
+ ceph_mkdirat@Base 17.0.0~
+ ceph_mkdirs@Base 12.0.3
+ ceph_mknod@Base 12.0.3
+ ceph_mksnap@Base 16.0.0
+ ceph_mount@Base 12.0.3
+ ceph_mount_perms@Base 12.0.3
+ ceph_mount_perms_set@Base 13.2.0
+ ceph_open@Base 12.0.3
+ ceph_open_layout@Base 12.0.3
+ ceph_openat@Base 17.0.0~
+ ceph_opendir@Base 12.0.3
+ ceph_preadv@Base 12.0.3
+ ceph_pwritev@Base 12.0.3
+ ceph_read@Base 12.0.3
+ ceph_readdir@Base 12.0.3
+ ceph_readdir_r@Base 12.0.3
+ ceph_readdirplus_r@Base 12.0.3
+ ceph_readlink@Base 12.0.3
+ ceph_readlinkat@Base 17.0.0~
+ ceph_release@Base 12.0.3
+ ceph_removexattr@Base 12.0.3
+ ceph_rename@Base 12.0.3
+ ceph_rewinddir@Base 12.0.3
+ ceph_rmdir@Base 12.0.3
+ ceph_rmsnap@Base 16.0.0
+ ceph_seekdir@Base 12.0.3
+ ceph_select_filesystem@Base 14.2.0
+ ceph_set_default_file_replication@Base 12.0.3
+ ceph_set_default_file_stripe_count@Base 12.0.3
+ ceph_set_default_file_stripe_unit@Base 12.0.3
+ ceph_set_default_object_size@Base 12.0.3
+ ceph_set_default_preferred_pg@Base 12.0.3
+ ceph_set_deleg_timeout@Base 13.2.0
+ ceph_set_mount_timeout@Base 17.0.0~
+ ceph_set_session_timeout@Base 14.2.0
+ ceph_set_uuid@Base 14.2.0
+ ceph_setattrx@Base 12.0.3
+ ceph_setxattr@Base 12.0.3
+ ceph_shutdown@Base 12.0.3
+ ceph_start_reclaim@Base 14.2.0
+ ceph_stat@Base 14.2.0
+ ceph_statfs@Base 12.0.3
+ ceph_statx@Base 12.0.3
+ ceph_statxat@Base 17.0.0~
+ ceph_symlink@Base 12.0.3
+ ceph_symlinkat@Base 17.0.0~
+ ceph_sync_fs@Base 12.0.3
+ ceph_telldir@Base 12.0.3
+ ceph_truncate@Base 12.0.3
+ ceph_umask@Base 14.2.0
+ ceph_unlink@Base 12.0.3
+ ceph_unlinkat@Base 17.0.0~
+ ceph_unmount@Base 12.0.3
+ ceph_userperm_destroy@Base 12.0.3
+ ceph_userperm_new@Base 12.0.3
+ ceph_utime@Base 12.0.3
+ ceph_utimensat@Base 17.0.0~
+ ceph_utimes@Base 14.2.0
+ ceph_version@Base 12.0.3
+ ceph_write@Base 12.0.3
diff --git a/debian/librados-dev.install b/debian/librados-dev.install
index 75d5ea7de..edaa359fc 100644
--- a/debian/librados-dev.install
+++ b/debian/librados-dev.install
@@ -1,6 +1,5 @@
usr/bin/librados-config
usr/include/rados/librados.h
usr/include/rados/rados_types.h
-usr/lib/librados.so
-usr/lib/librados_tp.so
+usr/lib/*/librados.so
usr/share/man/man8/librados-config.8
diff --git a/debian/librados2.install b/debian/librados2.install
index 816e55fce..2020e29c4 100644
--- a/debian/librados2.install
+++ b/debian/librados2.install
@@ -1,3 +1,2 @@
-usr/lib/ceph/libceph-common.so.*
-usr/lib/librados.so.*
-usr/lib/librados_tp.so.*
+usr/lib/*/ceph/libceph-common.so*
+usr/lib/*/librados.so.*
diff --git a/debian/librados2.lintian-overrides b/debian/librados2.lintian-overrides
new file mode 100644
index 000000000..d4041ca8e
--- /dev/null
+++ b/debian/librados2.lintian-overrides
@@ -0,0 +1,2 @@
+# False-positives:
+spelling-error-in-binary * tEH the
diff --git a/debian/librados2.symbols b/debian/librados2.symbols
new file mode 100644
index 000000000..5d013a06c
--- /dev/null
+++ b/debian/librados2.symbols
@@ -0,0 +1,404 @@
+libceph-common.so.2 librados2 #MINVER#
+ (regex|c++)"^_.*" 12.0.3
+ (regex)"^ceph_ver__[0-9a-f]{40}@Base$" 12.0.3
+ MDS_GID_NONE@Base 12.0.3
+ XXH32@Base 12.0.3
+ XXH32_canonicalFromHash@Base 12.0.3
+ XXH32_createState@Base 12.0.3
+ XXH32_digest@Base 12.0.3
+ XXH32_freeState@Base 12.0.3
+ XXH32_hashFromCanonical@Base 12.0.3
+ XXH32_reset@Base 12.0.3
+ XXH32_update@Base 12.0.3
+ XXH64@Base 12.0.3
+ XXH64_canonicalFromHash@Base 12.0.3
+ XXH64_createState@Base 12.0.3
+ XXH64_digest@Base 12.0.3
+ XXH64_freeState@Base 12.0.3
+ XXH64_hashFromCanonical@Base 12.0.3
+ XXH64_reset@Base 12.0.3
+ XXH64_update@Base 12.0.3
+ XXH_versionNumber@Base 12.0.3
+ boost_asio_detail_posix_thread_function@Base 12.0.3
+ (arch=amd64 i386)ceph_arch_intel_aesni@Base 12.0.3
+ (arch=amd64 i386)ceph_arch_intel_pclmul@Base 12.0.3
+ (arch=amd64 i386)ceph_arch_intel_probe@Base 12.0.3
+ (arch=amd64 i386)ceph_arch_intel_sse2@Base 12.0.3
+ (arch=amd64 i386)ceph_arch_intel_sse3@Base 12.0.3
+ (arch=amd64 i386)ceph_arch_intel_sse41@Base 12.0.3
+ (arch=amd64 i386)ceph_arch_intel_sse42@Base 12.0.3
+ (arch=amd64 i386)ceph_arch_intel_ssse3@Base 12.0.3
+ (arch=arm64 armhf)ceph_arch_aarch64_crc32@Base 12.0.3
+ (arch=arm64 armhf)ceph_arch_arm_probe@Base 12.0.3
+ (arch=ppc64el)ceph_arch_ppc_crc32@Base 12.0.3
+ (arch=ppc64el)ceph_arch_ppc_probe@Base 12.0.3a
+ (arch=arm64 armhf)ceph_arch_neon@Base 12.0.3
+ ceph_arch_probe@Base 12.0.3
+ ceph_arch_probed@Base 12.0.3
+ ceph_armor@Base 12.0.3
+ ceph_armor_line_break@Base 12.0.3
+ ceph_choose_crc32@Base 12.1.4
+ (arch=arm64)ceph_crc32c_aarch64@Base 12.0.3
+ ceph_crc32c_func@Base 12.0.3
+ (arch=amd64 i386)ceph_crc32c_intel_fast@Base 12.0.3
+ (arch=amd64 i386)ceph_crc32c_intel_fast_exists@Base 12.0.3
+ (arch=ppc64el)ceph_crc32c_ppc@Base 12.0.3
+ ceph_crc32c_sctp@Base 12.0.3
+ ceph_crc32c_zeros@Base 12.1.4
+ ceph_memzero_s@Base 16.0.0
+ ceph_options@Base 12.1.4
+ ceph_strerror_r@Base 15.1.0
+ ceph_unarmor@Base 12.0.3
+ check_for_control_characters@Base 12.0.3
+ check_for_control_characters_cstr@Base 12.0.3
+ check_utf8@Base 12.0.3
+ check_utf8_cstr@Base 12.0.3
+ code_environment_to_str@Base 12.0.3
+ (arch=ppc64el)crc_zero@Base 12.1.4
+ crush_add_bucket@Base 12.0.3
+ crush_add_list_bucket_item@Base 12.0.3
+ crush_add_rule@Base 12.0.3
+ crush_add_straw2_bucket_item@Base 12.0.3
+ crush_add_straw_bucket_item@Base 12.0.3
+ crush_add_tree_bucket_item@Base 12.0.3
+ crush_add_uniform_bucket_item@Base 12.0.3
+ crush_addition_is_unsafe@Base 12.0.3
+ crush_adjust_list_bucket_item_weight@Base 12.0.3
+ crush_adjust_straw2_bucket_item_weight@Base 12.0.3
+ crush_adjust_straw_bucket_item_weight@Base 12.0.3
+ crush_adjust_tree_bucket_item_weight@Base 12.0.3
+ crush_adjust_uniform_bucket_item_weight@Base 12.0.3
+ crush_bucket_add_item@Base 12.0.3
+ crush_bucket_adjust_item_weight@Base 12.0.3
+ crush_bucket_alg_name@Base 12.0.3
+ crush_bucket_remove_item@Base 12.0.3
+ crush_calc_straw@Base 12.0.3
+ crush_create@Base 12.0.3
+ crush_destroy@Base 12.0.3
+ crush_destroy_bucket@Base 12.0.3
+ crush_destroy_bucket_list@Base 12.0.3
+ crush_destroy_bucket_straw2@Base 12.0.3
+ crush_destroy_bucket_straw@Base 12.0.3
+ crush_destroy_bucket_tree@Base 12.0.3
+ crush_destroy_bucket_uniform@Base 12.0.3
+ crush_destroy_choose_args@Base 12.0.3
+ crush_destroy_rule@Base 12.0.3
+ crush_do_rule@Base 12.0.3
+ crush_finalize@Base 12.0.3
+ crush_get_bucket_item_weight@Base 12.0.3
+ crush_get_next_bucket_id@Base 12.0.3
+ crush_hash32@Base 12.0.3
+ crush_hash32_2@Base 12.0.3
+ crush_hash32_3@Base 12.0.3
+ crush_hash32_4@Base 12.0.3
+ crush_hash32_5@Base 12.0.3
+ crush_hash_name@Base 12.0.3
+ crush_init_workspace@Base 12.0.3
+ crush_make_bucket@Base 12.0.3
+ crush_make_choose_args@Base 12.0.3
+ crush_make_list_bucket@Base 12.0.3
+ crush_make_rule@Base 12.0.3
+ crush_make_straw2_bucket@Base 12.0.3
+ crush_make_straw_bucket@Base 12.0.3
+ crush_make_tree_bucket@Base 12.0.3
+ crush_make_uniform_bucket@Base 12.0.3
+ crush_multiplication_is_unsafe@Base 12.0.3
+ crush_remove_bucket@Base 12.0.3
+ crush_remove_list_bucket_item@Base 12.0.3
+ crush_remove_straw2_bucket_item@Base 12.0.3
+ crush_remove_straw_bucket_item@Base 12.0.3
+ crush_remove_tree_bucket_item@Base 12.0.3
+ crush_remove_uniform_bucket_item@Base 12.0.3
+ crush_reweight_bucket@Base 12.0.3
+ crush_rule_set_step@Base 12.0.3
+ decode_utf8@Base 12.0.3
+ encode_utf8@Base 12.0.3
+ g_code_env@Base 12.0.3
+ get_linux_version@Base 12.0.3
+ get_page_size@Base 16.0.0
+ get_process_name@Base 12.0.3
+ get_self_exe_path@Base 16.0.0
+ is_control_character@Base 12.0.3
+ mime_decode_from_qp@Base 12.0.3
+ mime_encode_as_qp@Base 12.0.3
+ module_has_param@Base 12.0.3
+ module_load@Base 12.0.3
+ pem_key@Base 12.0.3
+ pipe_cloexec@Base 16.0.0
+ resolve_addrs@Base 12.0.3
+ reverse_bits@Base 12.1.4
+ reverse_nibbles@Base 12.1.4
+ safe_cat@Base 12.0.3
+ safe_pread@Base 12.0.3
+ safe_pread_exact@Base 12.0.3
+ safe_pwrite@Base 12.0.3
+ safe_read@Base 12.0.3
+ safe_read_exact@Base 12.0.3
+ safe_read_file@Base 12.0.3
+ safe_recv@Base 16.0.0
+ safe_recv_exact@Base 16.0.0
+ safe_send@Base 16.0.0
+ safe_splice@Base 12.0.3
+ safe_splice_exact@Base 12.0.3
+ safe_write@Base 12.0.3
+ safe_write_file@Base 12.0.3
+ sctp_crc_c@Base 12.0.3
+ sctp_crc_tableil8_o32@Base 12.0.3
+ sctp_crc_tableil8_o40@Base 12.0.3
+ sctp_crc_tableil8_o48@Base 12.0.3
+ sctp_crc_tableil8_o56@Base 12.0.3
+ sctp_crc_tableil8_o64@Base 12.0.3
+ sctp_crc_tableil8_o72@Base 12.0.3
+ sctp_crc_tableil8_o80@Base 12.0.3
+ sctp_crc_tableil8_o88@Base 12.0.3
+ set_legacy_crush_map@Base 12.0.3
+ set_optimal_crush_map@Base 12.0.3
+librados.so.2 librados2 #MINVER#
+ (symver)LIBRADOS_14.2.0 14.2.0
+ (symver)LIBRADOS_PRIVATE 14.2.0
+ rados_aio_append@Base 0.72.2
+ rados_aio_cancel@Base 0.87
+ rados_aio_cmpext@Base 12.0.3
+ rados_aio_create_completion2@Base 15.1.0
+ rados_aio_create_completion@Base 0.72.2
+ rados_aio_exec@Base 12.0.3
+ rados_aio_flush@Base 0.72.2
+ rados_aio_flush_async@Base 0.72.2
+ rados_aio_get_return_value@Base 0.72.2
+ rados_aio_get_version@Base 12.0.3
+ rados_getaddrs@Base 15.1.0
+ rados_aio_getxattr@Base 12.0.3
+ rados_aio_getxattrs@Base 12.0.3
+ rados_aio_ioctx_selfmanaged_snap_create@Base 12.0.3
+ rados_aio_ioctx_selfmanaged_snap_remove@Base 12.0.3
+ rados_aio_is_complete@Base 0.72.2
+ rados_aio_is_complete_and_cb@Base 0.72.2
+ rados_aio_is_safe@Base 0.72.2
+ rados_aio_is_safe_and_cb@Base 0.72.2
+ rados_aio_notify@Base 10.1.0
+ rados_aio_read@Base 0.72.2
+ rados_aio_read_op_operate@Base 0.79
+ rados_aio_release@Base 0.72.2
+ rados_aio_remove@Base 0.72.2
+ rados_aio_rmxattr@Base 12.0.3
+ rados_aio_setxattr@Base 12.0.3
+ rados_aio_stat@Base 0.72.2
+ rados_aio_unlock@Base 12.0.3
+ rados_aio_unwatch@Base 10.1.0
+ rados_aio_wait_for_complete@Base 0.72.2
+ rados_aio_wait_for_complete_and_cb@Base 0.72.2
+ rados_aio_wait_for_safe@Base 0.72.2
+ rados_aio_wait_for_safe_and_cb@Base 0.72.2
+ rados_aio_watch2@Base 12.0.3
+ rados_aio_watch@Base 10.1.0
+ rados_aio_watch_flush@Base 10.1.0
+ rados_aio_write@Base 0.72.2
+ rados_aio_write_full@Base 0.72.2
+ rados_aio_write_op_operate@Base 0.79
+ rados_aio_writesame@Base 12.0.3
+ rados_append@Base 0.72.2
+ rados_application_enable@Base 12.1.4
+ rados_application_list@Base 12.1.4
+ rados_application_metadata_get@Base 12.1.4
+ rados_application_metadata_list@Base 12.1.4
+ rados_application_metadata_remove@Base 12.1.4
+ rados_application_metadata_set@Base 12.1.4
+ rados_blacklist_add@Base 0.93
+ rados_blocklist_add@Base 16.0.0
+ rados_break_lock@Base 0.72.2
+ rados_buffer_free@Base 0.72.2
+ rados_cache_pin@Base 10.1.0
+ rados_cache_unpin@Base 10.1.0
+ rados_cct@Base 0.72.2
+ rados_checksum@Base 12.0.3
+ rados_cluster_fsid@Base 0.72.2
+ rados_cluster_stat@Base 0.72.2
+ rados_cmpext@Base 12.0.3
+ rados_conf_get@Base 0.72.2
+ rados_conf_parse_argv@Base 0.72.2
+ rados_conf_parse_argv_remainder@Base 0.72.2
+ rados_conf_parse_env@Base 0.72.2
+ rados_conf_read_file@Base 0.72.2
+ rados_conf_set@Base 0.72.2
+ rados_connect@Base 0.72.2
+ rados_create2@Base 0.72.2
+ rados_create@Base 0.72.2
+ rados_create_read_op@Base 0.79
+ rados_create_with_context@Base 0.72.2
+ rados_create_write_op@Base 0.79
+ rados_decode_notify_response@Base 16.0.0
+ rados_exec@Base 0.72.2
+ rados_free_notify_response@Base 16.0.0
+ rados_get_instance_id@Base 0.72.2
+ rados_get_last_version@Base 0.72.2
+ rados_get_min_compatible_client@Base 13.2.0
+ rados_get_min_compatible_osd@Base 14.2.0
+ rados_getxattr@Base 0.72.2
+ rados_getxattrs@Base 0.72.2
+ rados_getxattrs_end@Base 0.72.2
+ rados_getxattrs_next@Base 0.72.2
+ rados_inconsistent_pg_list@Base 10.1.0
+ rados_ioctx_cct@Base 0.72.2
+ rados_ioctx_create2@Base 0.93
+ rados_ioctx_create@Base 0.72.2
+ rados_ioctx_destroy@Base 0.72.2
+ rados_ioctx_get_cluster@Base 0.72.2
+ rados_ioctx_get_id@Base 0.72.2
+ rados_ioctx_get_namespace@Base 14.2.0
+ rados_ioctx_get_pool_name@Base 0.72.2
+ rados_ioctx_locator_set_key@Base 0.72.2
+ rados_ioctx_pool_get_auid@Base 0.72.2
+ rados_ioctx_pool_required_alignment2@Base 10.1.0
+ rados_ioctx_pool_required_alignment@Base 0.79
+ rados_ioctx_pool_requires_alignment2@Base 10.1.0
+ rados_ioctx_pool_requires_alignment@Base 0.79
+ rados_ioctx_pool_set_auid@Base 0.72.2
+ rados_ioctx_pool_stat@Base 0.72.2
+ rados_ioctx_pool_stat@LIBRADOS_14.2.0 14.2.0
+ rados_ioctx_selfmanaged_snap_create@Base 0.72.2
+ rados_ioctx_selfmanaged_snap_remove@Base 0.72.2
+ rados_ioctx_selfmanaged_snap_rollback@Base 0.72.2
+ rados_ioctx_selfmanaged_snap_set_write_ctx@Base 0.72.2
+ rados_ioctx_set_namespace@Base 0.72.2
+ rados_ioctx_snap_create@Base 0.72.2
+ rados_ioctx_snap_get_name@Base 0.72.2
+ rados_ioctx_snap_get_stamp@Base 0.72.2
+ rados_ioctx_snap_list@Base 0.72.2
+ rados_ioctx_snap_lookup@Base 0.72.2
+ rados_ioctx_snap_remove@Base 0.72.2
+ rados_ioctx_snap_rollback@Base 0.80~rc1
+ rados_ioctx_snap_set_read@Base 0.72.2
+ rados_list_lockers@Base 0.72.2
+ rados_lock_exclusive@Base 0.72.2
+ rados_lock_shared@Base 0.72.2
+ rados_mgr_command@Base 12.0.3
+ rados_mgr_command_target@Base 15.1.0
+ rados_mon_command@Base 0.72.2
+ rados_mon_command_target@Base 0.72.2
+ rados_monitor_log2@Base 12.1.4
+ rados_monitor_log@Base 0.72.2
+ rados_nobjects_list_close@Base 0.93
+ rados_nobjects_list_get_cursor@Base 12.0.3
+ rados_nobjects_list_get_pg_hash_position@Base 0.93
+ rados_nobjects_list_next2@Base 17.0.0~
+ rados_nobjects_list_next@Base 0.93
+ rados_nobjects_list_open@Base 0.93
+ rados_nobjects_list_seek@Base 0.93
+ rados_nobjects_list_seek_cursor@Base 12.0.3
+ rados_notify2@Base 0.93
+ rados_notify@Base 0.72.2
+ rados_notify_ack@Base 0.93
+ rados_object_list@Base 10.1.0
+ rados_object_list_begin@Base 10.1.0
+ rados_object_list_cursor_cmp@Base 10.1.0
+ rados_object_list_cursor_free@Base 10.1.0
+ rados_object_list_end@Base 10.1.0
+ rados_object_list_free@Base 10.1.0
+ rados_object_list_is_end@Base 10.1.0
+ rados_object_list_slice@Base 10.1.0
+ rados_objects_list_close@Base 0.72.2
+ rados_objects_list_get_pg_hash_position@Base 0.79
+ rados_objects_list_next@Base 0.72.2
+ rados_objects_list_open@Base 0.72.2
+ rados_objects_list_seek@Base 0.79
+ rados_omap_get_end@Base 0.79
+ rados_omap_get_next2@Base 13.2.0
+ rados_omap_get_next@Base 0.79
+ rados_omap_iter_size@Base 14.2.0
+ rados_osd_command@Base 0.72.2
+ rados_pg_command@Base 0.72.2
+ rados_ping_monitor@Base 0.72.2
+ rados_pool_create@Base 0.72.2
+ rados_pool_create_with_all@Base 0.72.2
+ rados_pool_create_with_auid@Base 0.72.2
+ rados_pool_create_with_crush_rule@Base 0.72.2
+ rados_pool_delete@Base 0.72.2
+ rados_pool_get_base_tier@Base 0.93
+ rados_pool_list@Base 0.72.2
+ rados_pool_lookup@Base 0.72.2
+ rados_pool_reverse_lookup@Base 0.72.2
+ rados_read@Base 0.72.2
+ rados_read_op_assert_exists@Base 0.79
+ rados_read_op_assert_version@Base 0.93
+ rados_read_op_checksum@Base 12.0.3
+ rados_read_op_cmpext@Base 12.0.3
+ rados_read_op_cmpxattr@Base 0.79
+ rados_read_op_exec@Base 0.79
+ rados_read_op_exec_user_buf@Base 0.79
+ rados_read_op_getxattrs@Base 0.79
+ rados_read_op_omap_cmp2@Base 13.2.0
+ rados_read_op_omap_cmp@Base 0.79
+ rados_read_op_omap_get_keys2@Base 12.0.3
+ rados_read_op_omap_get_keys@Base 0.79
+ rados_read_op_omap_get_vals2@Base 12.0.3
+ rados_read_op_omap_get_vals@Base 0.79
+ rados_read_op_omap_get_vals_by_keys2@Base 13.2.0
+ rados_read_op_omap_get_vals_by_keys@Base 0.79
+ rados_read_op_operate@Base 0.79
+ rados_read_op_read@Base 0.79
+ rados_read_op_set_flags@Base 0.79
+ rados_read_op_stat@Base 0.79
+ rados_release_read_op@Base 0.79
+ rados_release_write_op@Base 0.79
+ rados_remove@Base 0.72.2
+ rados_rmxattr@Base 0.72.2
+ rados_rollback@Base 0.72.2
+ rados_service_register@Base 12.1.4
+ rados_service_update_status@Base 12.1.4
+ rados_set_alloc_hint2@Base 12.0.3
+ rados_set_alloc_hint@Base 0.79
+ rados_set_osdmap_full_try@Base 13.2.0
+ rados_set_pool_full_try@Base 15.1.0
+ rados_setxattr@Base 0.72.2
+ rados_shutdown@Base 0.72.2
+ rados_stat@Base 0.72.2
+ rados_tmap_get@Base 0.72.2
+ rados_tmap_get@LIBRADOS_14.2.0 14.2.0
+ rados_tmap_put@Base 0.72.2
+ rados_tmap_put@LIBRADOS_14.2.0 14.2.0
+ rados_tmap_update@Base 0.72.2
+ rados_tmap_update@LIBRADOS_14.2.0 14.2.0
+ rados_trunc@Base 0.72.2
+ rados_unlock@Base 0.72.2
+ rados_unset_osdmap_full_try@Base 13.2.0
+ rados_unset_pool_full_try@Base 15.1.0
+ rados_unwatch2@Base 0.93
+ rados_unwatch@Base 0.72.2
+ rados_version@Base 0.72.2
+ rados_wait_for_latest_osdmap@Base 0.79
+ rados_watch2@Base 0.93
+ rados_watch3@Base 12.0.3
+ rados_watch@Base 0.72.2
+ rados_watch_check@Base 0.93
+ rados_watch_flush@Base 0.93
+ rados_write@Base 0.72.2
+ rados_write_full@Base 0.72.2
+ rados_write_op_append@Base 0.79
+ rados_write_op_assert_exists@Base 0.79
+ rados_write_op_assert_version@Base 0.93
+ rados_write_op_cmpext@Base 12.0.3
+ rados_write_op_cmpxattr@Base 0.79
+ rados_write_op_create@Base 0.79
+ rados_write_op_exec@Base 0.79
+ rados_write_op_omap_clear@Base 0.79
+ rados_write_op_omap_cmp2@Base 13.2.0
+ rados_write_op_omap_cmp@Base 0.79
+ rados_write_op_omap_rm_keys2@Base 13.2.0
+ rados_write_op_omap_rm_keys@Base 0.79
+ rados_write_op_omap_rm_range2@Base 15.1.0
+ rados_write_op_omap_set2@Base 13.2.0
+ rados_write_op_omap_set@Base 0.79
+ rados_write_op_operate2@Base 10.1.0
+ rados_write_op_operate@Base 0.79
+ rados_write_op_remove@Base 0.79
+ rados_write_op_rmxattr@Base 0.79
+ rados_write_op_set_alloc_hint2@Base 12.0.3
+ rados_write_op_set_alloc_hint@Base 0.79
+ rados_write_op_set_flags@Base 0.79
+ rados_write_op_setxattr@Base 0.79
+ rados_write_op_truncate@Base 0.79
+ rados_write_op_write@Base 0.79
+ rados_write_op_write_full@Base 0.79
+ rados_write_op_writesame@Base 12.0.3
+ rados_write_op_zero@Base 0.79
+ rados_writesame@Base 12.0.3
diff --git a/debian/libradosstriper-dev.install b/debian/libradosstriper-dev.install
index f7986d30f..4d6d7b5a0 100644
--- a/debian/libradosstriper-dev.install
+++ b/debian/libradosstriper-dev.install
@@ -1,3 +1,3 @@
usr/include/radosstriper/libradosstriper.h
usr/include/radosstriper/libradosstriper.hpp
-usr/lib/libradosstriper.so
+usr/lib/*/libradosstriper.so
diff --git a/debian/libradosstriper1.install b/debian/libradosstriper1.install
index 46235acff..742549ba9 100644
--- a/debian/libradosstriper1.install
+++ b/debian/libradosstriper1.install
@@ -1 +1 @@
-usr/lib/libradosstriper.so.*
+usr/lib/*/libradosstriper.so.*
diff --git a/debian/libradosstriper1.symbols b/debian/libradosstriper1.symbols
new file mode 100644
index 000000000..a33eb91e9
--- /dev/null
+++ b/debian/libradosstriper1.symbols
@@ -0,0 +1,38 @@
+libradosstriper.so.1 libradosstriper1 #MINVER#
+ (regex|c++)"^_.*" 0.87
+ rados_striper_aio_append@Base 0.87
+ rados_striper_aio_flush@Base 0.87
+ rados_striper_aio_read@Base 0.87
+ rados_striper_aio_remove@Base 12.0.3
+ rados_striper_aio_stat@Base 12.0.3
+ rados_striper_aio_write@Base 0.87
+ rados_striper_aio_write_full@Base 0.87
+ rados_striper_append@Base 0.87
+ rados_striper_create@Base 0.87
+ rados_striper_destroy@Base 0.87
+ rados_striper_getxattr@Base 0.87
+ rados_striper_getxattrs@Base 0.87
+ rados_striper_getxattrs_end@Base 0.87
+ rados_striper_getxattrs_next@Base 0.87
+ rados_striper_multi_aio_create_completion@Base 0.87
+ rados_striper_multi_aio_get_return_value@Base 0.87
+ rados_striper_multi_aio_is_complete@Base 0.87
+ rados_striper_multi_aio_is_complete_and_cb@Base 0.87
+ rados_striper_multi_aio_is_safe@Base 0.87
+ rados_striper_multi_aio_is_safe_and_cb@Base 0.87
+ rados_striper_multi_aio_release@Base 0.87
+ rados_striper_multi_aio_wait_for_complete@Base 0.87
+ rados_striper_multi_aio_wait_for_complete_and_cb@Base 0.87
+ rados_striper_multi_aio_wait_for_safe@Base 0.87
+ rados_striper_multi_aio_wait_for_safe_and_cb@Base 0.87
+ rados_striper_read@Base 0.87
+ rados_striper_remove@Base 0.87
+ rados_striper_rmxattr@Base 0.87
+ rados_striper_set_object_layout_object_size@Base 0.87
+ rados_striper_set_object_layout_stripe_count@Base 0.87
+ rados_striper_set_object_layout_stripe_unit@Base 0.87
+ rados_striper_setxattr@Base 0.87
+ rados_striper_stat@Base 0.87
+ rados_striper_trunc@Base 0.87
+ rados_striper_write@Base 0.87
+ rados_striper_write_full@Base 0.87
diff --git a/debian/librbd-dev.install b/debian/librbd-dev.install
index 6028f4288..c6b455e58 100644
--- a/debian/librbd-dev.install
+++ b/debian/librbd-dev.install
@@ -1,5 +1,4 @@
usr/include/rbd/features.h
usr/include/rbd/librbd.h
usr/include/rbd/librbd.hpp
-usr/lib/librbd.so
-usr/lib/librbd_tp.so
+usr/lib/*/librbd.so
diff --git a/debian/librbd1.install b/debian/librbd1.install
index 8c9fc46a2..f22bdec6a 100644
--- a/debian/librbd1.install
+++ b/debian/librbd1.install
@@ -1,3 +1,2 @@
-usr/lib/librbd.so.*
-usr/lib/librbd_tp.so.*
-usr/lib/ceph/librbd/*
+usr/lib/*/ceph/librbd/*
+usr/lib/*/librbd.so.*
diff --git a/debian/librbd1.symbols b/debian/librbd1.symbols
new file mode 100644
index 000000000..f04feac78
--- /dev/null
+++ b/debian/librbd1.symbols
@@ -0,0 +1,283 @@
+libceph_librbd_parent_cache.so.1 librbd1a
+ (regex|c++)"^_.*" 0.87
+librbd.so.1 librbd1 #MINVER#
+ (regex|c++)"^_.*" 0.87
+ rbd_aio_close@Base 10.1.0
+ rbd_aio_compare_and_write@Base 12.1.4
+ rbd_aio_create_completion@Base 0.72.2
+ rbd_aio_discard@Base 0.72.2
+ rbd_aio_flush@Base 0.72.2
+ rbd_aio_get_arg@Base 10.1.0
+ rbd_aio_get_return_value@Base 0.72.2
+ rbd_aio_is_complete@Base 0.72.2
+ rbd_aio_mirror_image_create_snapshot@Base 16.0.0
+ rbd_aio_mirror_image_demote@Base 12.0.3
+ rbd_aio_mirror_image_get_global_status@Base 15.1.0
+ rbd_aio_mirror_image_get_info@Base 12.0.3
+ rbd_aio_mirror_image_get_mode@Base 16.0.0
+ rbd_aio_mirror_image_get_status@Base 12.0.3
+ rbd_aio_mirror_image_promote@Base 12.0.3
+ rbd_aio_open@Base 10.1.0
+ rbd_aio_open_by_id@Base 12.0.3
+ rbd_aio_open_by_id_read_only@Base 12.0.3
+ rbd_aio_open_read_only@Base 10.1.0
+ rbd_aio_read2@Base 0.93
+ rbd_aio_read@Base 0.72.2
+ rbd_aio_readv@Base 12.0.3
+ rbd_aio_release@Base 0.72.2
+ rbd_aio_wait_for_complete@Base 0.72.2
+ rbd_aio_write2@Base 0.93
+ rbd_aio_write@Base 0.72.2
+ rbd_aio_write_zeroes@Base 16.0.0
+ rbd_aio_writesame@Base 12.0.3
+ rbd_aio_writev@Base 12.0.3
+ rbd_break_lock@Base 0.72.2
+ rbd_clone2@Base 0.72.2
+ rbd_clone3@Base 10.1.0
+ rbd_clone@Base 0.72.2
+ rbd_close@Base 0.72.2
+ rbd_compare_and_write@Base 12.1.4
+ rbd_config_image_list@Base 14.2.0
+ rbd_config_image_list_cleanup@Base 14.2.0
+ rbd_config_pool_list@Base 14.2.0
+ rbd_config_pool_list_cleanup@Base 14.2.0
+ rbd_copy2@Base 0.72.2
+ rbd_copy3@Base 10.1.0
+ rbd_copy4@Base 12.0.3
+ rbd_copy@Base 0.72.2
+ rbd_copy_with_progress2@Base 0.72.2
+ rbd_copy_with_progress3@Base 12.0.3
+ rbd_copy_with_progress4@Base 12.0.3
+ rbd_copy_with_progress@Base 0.72.2
+ rbd_create2@Base 0.72.2
+ rbd_create3@Base 0.72.2
+ rbd_create4@Base 10.1.0
+ rbd_create@Base 0.72.2
+ rbd_deep_copy@Base 13.2.0
+ rbd_deep_copy_with_progress@Base 13.2.0
+ rbd_diff_iterate2@Base 9.2.0
+ rbd_diff_iterate@Base 0.72.2
+ rbd_discard@Base 0.72.2
+ rbd_encryption_format@Base 16.0.0
+ rbd_encryption_load@Base 16.0.0
+ rbd_features_from_string@Base 15.1.0
+ rbd_features_to_string@Base 15.1.0
+ rbd_flatten@Base 0.72.2
+ rbd_flatten_with_progress@Base 12.0.3
+ rbd_flush@Base 0.72.2
+ rbd_get_access_timestamp@Base 14.2.0
+ rbd_get_block_name_prefix@Base 12.0.3
+ rbd_get_create_timestamp@Base 12.1.4
+ rbd_get_data_pool_id@Base 12.0.3
+ rbd_get_features@Base 0.72.2
+ rbd_get_flags@Base 0.93
+ rbd_get_group@Base 13.2.0
+ rbd_get_id@Base 12.0.3
+ rbd_get_migration_source_spec@Base 16.0.0
+ rbd_get_modify_timestamp@Base 14.2.0
+ rbd_get_name@Base 13.2.0
+ rbd_get_old_format@Base 0.72.2
+ rbd_get_op_features@Base 13.2.0
+ rbd_get_overlap@Base 0.72.2
+ rbd_get_parent@Base 14.2.0
+ rbd_get_parent_info2@Base 12.0.3
+ rbd_get_parent_info@Base 0.72.2
+ rbd_get_size@Base 0.72.2
+ rbd_get_stripe_count@Base 0.72.2
+ rbd_get_stripe_unit@Base 0.72.2
+ rbd_group_create@Base 13.2.0
+ rbd_group_image_add@Base 13.2.0
+ rbd_group_image_list@Base 13.2.0
+ rbd_group_image_list_cleanup@Base 13.2.0
+ rbd_group_image_remove@Base 13.2.0
+ rbd_group_image_remove_by_id@Base 13.2.0
+ rbd_group_info_cleanup@Base 13.2.0
+ rbd_group_list@Base 13.2.0
+ rbd_group_remove@Base 13.2.0
+ rbd_group_rename@Base 13.2.0
+ rbd_group_snap_create2@Base 16.0.0
+ rbd_group_snap_create@Base 13.2.0
+ rbd_group_snap_list@Base 13.2.0
+ rbd_group_snap_list_cleanup@Base 13.2.0
+ rbd_group_snap_remove@Base 13.2.0
+ rbd_group_snap_rename@Base 13.2.0
+ rbd_group_snap_rollback@Base 14.2.0
+ rbd_group_snap_rollback_with_progress@Base 14.2.0
+ rbd_image_options_clear@Base 10.1.0
+ rbd_image_options_create@Base 10.1.0
+ rbd_image_options_destroy@Base 10.1.0
+ rbd_image_options_get_string@Base 10.1.0
+ rbd_image_options_get_uint64@Base 10.1.0
+ rbd_image_options_is_empty@Base 10.1.0
+ rbd_image_options_is_set@Base 12.0.3
+ rbd_image_options_set_string@Base 10.1.0
+ rbd_image_options_set_uint64@Base 10.1.0
+ rbd_image_options_unset@Base 10.1.0
+ rbd_image_spec_cleanup@Base 14.2.0
+ rbd_image_spec_list_cleanup@Base 14.2.0
+ rbd_invalidate_cache@Base 0.80.5-2~
+ rbd_is_exclusive_lock_owner@Base 0.93
+ rbd_linked_image_spec_cleanup@Base 14.2.0
+ rbd_linked_image_spec_list_cleanup@Base 14.2.0
+ rbd_list2@Base 14.2.0
+ rbd_list@Base 0.72.2
+ rbd_list_child_cleanup@Base 13.2.0
+ rbd_list_children2@Base 13.2.0
+ rbd_list_children3@Base 14.2.0
+ rbd_list_children@Base 0.72.2
+ rbd_list_children_cleanup@Base 13.2.0
+ rbd_list_descendants@Base 14.2.0
+ rbd_list_lockers@Base 0.72.2
+ rbd_lock_acquire@Base 12.0.3
+ rbd_lock_break@Base 12.0.3
+ rbd_lock_exclusive@Base 0.72.2
+ rbd_lock_get_owners@Base 12.0.3
+ rbd_lock_get_owners_cleanup@Base 12.0.3
+ rbd_lock_release@Base 12.0.3
+ rbd_lock_shared@Base 0.72.2
+ rbd_metadata_get@Base 9.2.0
+ rbd_metadata_list@Base 9.2.0
+ rbd_metadata_remove@Base 9.2.0
+ rbd_metadata_set@Base 9.2.0
+ rbd_migration_abort@Base 14.2.0
+ rbd_migration_abort_with_progress@Base 14.2.0
+ rbd_migration_commit@Base 14.2.0
+ rbd_migration_commit_with_progress@Base 14.2.0
+ rbd_migration_execute@Base 14.2.0
+ rbd_migration_execute_with_progress@Base 14.2.0
+ rbd_migration_prepare@Base 14.2.0
+ rbd_migration_prepare_import@Base 16.0.0
+ rbd_migration_status@Base 14.2.0
+ rbd_migration_status_cleanup@Base 14.2.0
+ rbd_mirror_image_create_snapshot2@Base 16.0.0
+ rbd_mirror_image_create_snapshot@Base 15.1.0
+ rbd_mirror_image_demote@Base 10.1.0
+ rbd_mirror_image_disable@Base 10.1.0
+ rbd_mirror_image_enable2@Base 15.1.0
+ rbd_mirror_image_enable@Base 10.1.0
+ rbd_mirror_image_get_global_status@Base 15.1.0
+ rbd_mirror_image_get_info@Base 10.1.0
+ rbd_mirror_image_get_info_cleanup@Base 15.1.0
+ rbd_mirror_image_get_instance_id@Base 14.2.0
+ rbd_mirror_image_get_mode@Base 15.1.0
+ rbd_mirror_image_get_status@Base 12.0.3
+ rbd_mirror_image_global_status_cleanup@Base 15.1.0
+ rbd_mirror_image_global_status_list@Base 15.1.0
+ rbd_mirror_image_global_status_list_cleanup@Base 15.1.0
+ rbd_mirror_image_info_list@Base 15.1.0
+ rbd_mirror_image_info_list_cleanup@Base 15.1.0
+ rbd_mirror_image_instance_id_list@Base 14.2.0
+ rbd_mirror_image_instance_id_list_cleanup@Base 14.2.0
+ rbd_mirror_image_promote@Base 10.1.0
+ rbd_mirror_image_resync@Base 10.1.0
+ rbd_mirror_image_status_list@Base 12.0.3
+ rbd_mirror_image_status_list_cleanup@Base 12.0.3
+ rbd_mirror_image_status_summary@Base 12.0.3
+ rbd_mirror_mode_get@Base 10.1.0
+ rbd_mirror_mode_set@Base 10.1.0
+ rbd_mirror_peer_add@Base 10.1.0
+ rbd_mirror_peer_bootstrap_create@Base 14.2.5
+ rbd_mirror_peer_bootstrap_import@Base 14.2.5
+ rbd_mirror_peer_get_attributes@Base 14.2.0
+ rbd_mirror_peer_list@Base 10.1.0
+ rbd_mirror_peer_list_cleanup@Base 10.1.0
+ rbd_mirror_peer_remove@Base 10.1.0
+ rbd_mirror_peer_set_attributes@Base 14.2.0
+ rbd_mirror_peer_set_client@Base 10.1.0
+ rbd_mirror_peer_set_cluster@Base 10.1.0
+ rbd_mirror_peer_site_add@Base 15.1.0
+ rbd_mirror_peer_site_get_attributes@Base 15.1.0
+ rbd_mirror_peer_site_list@Base 15.1.0
+ rbd_mirror_peer_site_list_cleanup@Base 15.1.0
+ rbd_mirror_peer_site_remove@Base 15.1.0
+ rbd_mirror_peer_site_set_attributes@Base 15.1.0
+ rbd_mirror_peer_site_set_client_name@Base 15.1.0
+ rbd_mirror_peer_site_set_direction@Base 15.1.0
+ rbd_mirror_peer_site_set_name@Base 15.1.0
+ rbd_mirror_site_name_get@Base 14.2.5
+ rbd_mirror_site_name_set@Base 14.2.5
+ rbd_mirror_uuid_get@Base 15.1.1
+ rbd_namespace_create@Base 14.2.0
+ rbd_namespace_exists@Base 14.2.0
+ rbd_namespace_list@Base 14.2.0
+ rbd_namespace_remove@Base 14.2.0
+ rbd_open@Base 0.72.2
+ rbd_open_by_id@Base 12.0.3
+ rbd_open_by_id_read_only@Base 12.0.3
+ rbd_open_read_only@Base 0.72.2
+ rbd_poll_io_events@Base 10.1.0
+ rbd_pool_init@Base 14.2.0
+ rbd_pool_metadata_get@Base 14.2.0
+ rbd_pool_metadata_list@Base 14.2.0
+ rbd_pool_metadata_remove@Base 14.2.0
+ rbd_pool_metadata_set@Base 14.2.0
+ rbd_pool_stats_create@Base 14.2.0
+ rbd_pool_stats_destroy@Base 14.2.0
+ rbd_pool_stats_get@Base 14.2.0
+ rbd_pool_stats_option_add_uint64@Base 14.2.0
+ rbd_quiesce_unwatch@Base 16.0.0
+ rbd_quiesce_watch@Base 16.0.0
+ rbd_read2@Base 0.93
+ rbd_read@Base 0.72.2
+ rbd_read_iterate2@Base 0.72.2
+ rbd_read_iterate@Base 0.72.2
+ rbd_rebuild_object_map@Base 9.2.0
+ rbd_remove@Base 0.72.2
+ rbd_remove_with_progress@Base 0.72.2
+ rbd_rename@Base 0.72.2
+ rbd_resize2@Base 12.0.3
+ rbd_resize@Base 0.72.2
+ rbd_resize_with_progress@Base 0.72.2
+ rbd_set_image_notification@Base 10.1.0
+ rbd_snap_create2@Base 16.0.0
+ rbd_snap_create@Base 0.72.2
+ rbd_snap_exists@Base 15.1.0
+ rbd_snap_get_group_namespace@Base 13.2.0
+ rbd_snap_get_id@Base 15.1.0
+ rbd_snap_get_limit@Base 12.0.3
+ rbd_snap_get_mirror_namespace@Base 15.1.1
+ rbd_snap_get_name@Base 15.1.0
+ rbd_snap_get_namespace_type@Base 13.2.0
+ rbd_snap_get_timestamp@Base 12.0.3
+ rbd_snap_get_trash_namespace@Base 14.2.0
+ rbd_snap_group_namespace_cleanup@Base 13.2.0
+ rbd_snap_is_protected@Base 0.72.2
+ rbd_snap_list@Base 0.72.2
+ rbd_snap_list_end@Base 0.72.2
+ rbd_snap_mirror_namespace_cleanup@Base 15.1.1
+ rbd_snap_protect@Base 0.72.2
+ rbd_snap_remove2@Base 12.0.3
+ rbd_snap_remove@Base 0.72.2
+ rbd_snap_remove_by_id@Base 14.2.0
+ rbd_snap_rename@Base 10.1.0
+ rbd_snap_rollback@Base 0.72.2
+ rbd_snap_rollback_with_progress@Base 0.72.2
+ rbd_snap_set@Base 0.72.2
+ rbd_snap_set_by_id@Base 13.2.0
+ rbd_snap_set_limit@Base 12.0.3
+ rbd_snap_spec_cleanup@Base 14.2.0
+ rbd_snap_unprotect@Base 0.72.2
+ rbd_sparsify@Base 14.2.0
+ rbd_sparsify_with_progress@Base 14.2.0
+ rbd_stat@Base 0.72.2
+ rbd_trash_get@Base 12.0.3
+ rbd_trash_get_cleanup@Base 12.0.3
+ rbd_trash_list@Base 12.0.3
+ rbd_trash_list_cleanup@Base 12.0.3
+ rbd_trash_move@Base 12.0.3
+ rbd_trash_purge@Base 14.2.0
+ rbd_trash_purge_with_progress@Base 14.2.0
+ rbd_trash_remove@Base 12.0.3
+ rbd_trash_remove_with_progress@Base 12.0.3
+ rbd_trash_restore@Base 12.0.3
+ rbd_unlock@Base 0.72.2
+ rbd_update_features@Base 9.2.0
+ rbd_update_unwatch@Base 12.0.3
+ rbd_update_watch@Base 12.0.3
+ rbd_version@Base 0.72.2
+ rbd_watchers_list@Base 13.2.0
+ rbd_watchers_list_cleanup@Base 13.2.0
+ rbd_write2@Base 0.93
+ rbd_write@Base 0.72.2
+ rbd_write_zeroes@Base 16.0.0
+ rbd_writesame@Base 12.0.3
diff --git a/debian/librgw-dev.install b/debian/librgw-dev.install
index ed2a81dba..56d4da008 100644
--- a/debian/librgw-dev.install
+++ b/debian/librgw-dev.install
@@ -1,3 +1,3 @@
usr/include/rados/librgw.h
usr/include/rados/rgw_file.h
-usr/lib/librgw.so
+usr/lib/*/librgw.so
diff --git a/debian/librgw2.install b/debian/librgw2.install
index b86fb891e..267c56113 100644
--- a/debian/librgw2.install
+++ b/debian/librgw2.install
@@ -1 +1 @@
-usr/lib/librgw.so.*
+usr/lib/*/librgw.so.*
diff --git a/debian/libsqlite3-mod-ceph.install b/debian/libsqlite3-mod-ceph.install
index f327c7fc8..c33877245 100644
--- a/debian/libsqlite3-mod-ceph.install
+++ b/debian/libsqlite3-mod-ceph.install
@@ -1 +1 @@
-usr/lib/libcephsqlite.so
+usr/lib/*/libcephsqlite.so
diff --git a/debian/libsqlite3-mod-ceph.symbols b/debian/libsqlite3-mod-ceph.symbols
deleted file mode 100644
index d9679a13d..000000000
--- a/debian/libsqlite3-mod-ceph.symbols
+++ /dev/null
@@ -1,37 +0,0 @@
-libcephsqlite.so libsqlite3-mod-ceph #MINVER#
- _ZGVN18SimpleRADOSStriper7biglockB5cxx11E@Base 15.2.0-1
- _ZGVN18SimpleRADOSStriper8lockdescB5cxx11E@Base 15.2.0-1
- _ZN18SimpleRADOSStriper10XATTR_EXCLE@Base 15.2.0-1
- _ZN18SimpleRADOSStriper10XATTR_SIZEE@Base 15.2.0-1
- _ZN18SimpleRADOSStriper12recover_lockEv@Base 15.2.0-1
- _ZN18SimpleRADOSStriper12set_metadataEmb@Base 15.2.0-1
- _ZN18SimpleRADOSStriper12shrink_allocEm@Base 15.2.0-1
- _ZN18SimpleRADOSStriper13XATTR_VERSIONE@Base 15.2.0-1
- _ZN18SimpleRADOSStriper13config_loggerEPN4ceph6common11CephContextESt17basic_string_viewIcSt11char_traitsIcEEPSt10shared_ptrINS1_12PerfCountersEE@Base 15.2.0-1
- _ZN18SimpleRADOSStriper13print_lockersERSo@Base 15.2.0-1
- _ZN18SimpleRADOSStriper13wait_for_aiosEb@Base 15.2.0-1
- _ZN18SimpleRADOSStriper15XATTR_ALLOCATEDE@Base 15.2.0-1
- _ZN18SimpleRADOSStriper16lock_keeper_mainEv@Base 15.2.0-1
- _ZN18SimpleRADOSStriper18maybe_shrink_allocEv@Base 15.2.0-1
- _ZN18SimpleRADOSStriper24XATTR_LAYOUT_OBJECT_SIZEE@Base 15.2.0-1
- _ZN18SimpleRADOSStriper24XATTR_LAYOUT_STRIPE_UNITE@Base 15.2.0-1
- _ZN18SimpleRADOSStriper25XATTR_LAYOUT_STRIPE_COUNTE@Base 15.2.0-1
- _ZN18SimpleRADOSStriper4lockEm@Base 15.2.0-1
- _ZN18SimpleRADOSStriper4openEv@Base 15.2.0-1
- _ZN18SimpleRADOSStriper4readEPvmm@Base 15.2.0-1
- _ZN18SimpleRADOSStriper4statEPm@Base 15.2.0-1
- _ZN18SimpleRADOSStriper5flushEv@Base 15.2.0-1
- _ZN18SimpleRADOSStriper5writeEPKvmm@Base 15.2.0-1
- _ZN18SimpleRADOSStriper6createEv@Base 15.2.0-1
- _ZN18SimpleRADOSStriper6removeEv@Base 15.2.0-1
- _ZN18SimpleRADOSStriper6str2blESt17basic_string_viewIcSt11char_traitsIcEE@Base 15.2.0-1
- _ZN18SimpleRADOSStriper6unlockEv@Base 15.2.0-1
- _ZN18SimpleRADOSStriper7biglockB5cxx11E@Base 15.2.0-1
- _ZN18SimpleRADOSStriper7uint2blEm@Base 15.2.0-1
- _ZN18SimpleRADOSStriper8lockdescB5cxx11E@Base 15.2.0-1
- _ZN18SimpleRADOSStriper8truncateEm@Base 15.2.0-1
- _ZN18SimpleRADOSStriperD1Ev@Base 15.2.0-1
- _ZN18SimpleRADOSStriperD2Ev@Base 15.2.0-1
- _ZNK18SimpleRADOSStriper15get_next_extentEmm@Base 15.2.0-1
- cephsqlite_setcct@Base 15.2.0-1
- sqlite3_cephsqlite_init@Base 15.2.0-1
diff --git a/debian/man/ceph-crush-location.1 b/debian/man/ceph-crush-location.1
new file mode 100644
index 000000000..d05d85c7b
--- /dev/null
+++ b/debian/man/ceph-crush-location.1
@@ -0,0 +1,24 @@
+.TH ceph-crush-location "1" "April 2014" "ceph-crush-location" "User Commands"
+.SH NAME
+ceph-crush-location \- get CRUSH location
+.SH DESCRIPTION
+Generate a CRUSH location for the given entity
+
+The CRUSH location consists of a list of key=value pairs, separated
+by spaces, all on a single line. This describes where in CRUSH
+hierarhcy this entity should be placed.
+
+.SH OPTIONS
+.TP 4
+\fB\-\-cluster\fR <clustername>
+name of the cluster (see /etc/ceph/$cluster.conf)
+.TP 4
+\fB\-\-type\fR <osd|mds|client>
+daemon/entity type
+.TP 4
+\fB\-\-id\fR <id>
+id (osd number, mds name, client name)
+
+.SH SEE ALSO
+.TP
+\fBceph-conf\fP(8)
diff --git a/debian/man/mount.fuse.ceph.8 b/debian/man/mount.fuse.ceph.8
new file mode 100644
index 000000000..718936578
--- /dev/null
+++ b/debian/man/mount.fuse.ceph.8
@@ -0,0 +1,30 @@
+.TH mount.fuse.ceph "8" "March 2014" "ceph-fuse" "User Commands"
+.SH NAME
+mount.fuse.ceph \- wrapper around ceph-fuse
+.SH DESCRIPTION
+Helper to mount ceph-fuse from /etc/fstab. To use, add an entry like:
+
+.nf
+# DEVICE PATH TYPE OPTIONS
+ mount.fuse.ceph#conf=/etc/ceph/ceph.conf,id=admin /mnt/ceph fuse _netdev,noatime,allow_other 0 0
+ mount.fuse.ceph#conf=/etc/ceph/foo.conf,id=myuser /mnt/ceph2 fuse _netdev,noatime,allow_other 0 0
+.fi
+
+where the device field is a comma-separated list of options to pass on
+the command line. The examples above, for example, specify that
+ceph-fuse will authenticated as client.admin and client.myuser
+(respectively), and the second example also sets the "conf" option to
+"/etc/ceph/foo.conf" via the ceph-fuse command line. Any valid
+ceph-fuse option can be passed in this way.
+
+.SH OPTIONS
+.TP 4
+\fB\-\-conf\fR
+path to ceph cponfiguration file, usually "/etc/ceph/ceph.conf"
+.TP 4
+\fB\-\-id\fR
+user name
+
+.SH SEE ALSO
+.TP
+\fBceph-fuse\fP(8)
diff --git a/debian/missing-sources/bootstrap.js b/debian/missing-sources/bootstrap.js
new file mode 100644
index 000000000..8a2e99a53
--- /dev/null
+++ b/debian/missing-sources/bootstrap.js
@@ -0,0 +1,2377 @@
+/*!
+ * Bootstrap v3.3.7 (http://getbootstrap.com)
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under the MIT license
+ */
+
+if (typeof jQuery === 'undefined') {
+ throw new Error('Bootstrap\'s JavaScript requires jQuery')
+}
+
++function ($) {
+ 'use strict';
+ var version = $.fn.jquery.split(' ')[0].split('.')
+ if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
+ throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
+ }
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: transition.js v3.3.7
+ * http://getbootstrap.com/javascript/#transitions
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
+ // ============================================================
+
+ function transitionEnd() {
+ var el = document.createElement('bootstrap')
+
+ var transEndEventNames = {
+ WebkitTransition : 'webkitTransitionEnd',
+ MozTransition : 'transitionend',
+ OTransition : 'oTransitionEnd otransitionend',
+ transition : 'transitionend'
+ }
+
+ for (var name in transEndEventNames) {
+ if (el.style[name] !== undefined) {
+ return { end: transEndEventNames[name] }
+ }
+ }
+
+ return false // explicit for ie8 ( ._.)
+ }
+
+ // http://blog.alexmaccaw.com/css-transitions
+ $.fn.emulateTransitionEnd = function (duration) {
+ var called = false
+ var $el = this
+ $(this).one('bsTransitionEnd', function () { called = true })
+ var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
+ setTimeout(callback, duration)
+ return this
+ }
+
+ $(function () {
+ $.support.transition = transitionEnd()
+
+ if (!$.support.transition) return
+
+ $.event.special.bsTransitionEnd = {
+ bindType: $.support.transition.end,
+ delegateType: $.support.transition.end,
+ handle: function (e) {
+ if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
+ }
+ }
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: alert.js v3.3.7
+ * http://getbootstrap.com/javascript/#alerts
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // ALERT CLASS DEFINITION
+ // ======================
+
+ var dismiss = '[data-dismiss="alert"]'
+ var Alert = function (el) {
+ $(el).on('click', dismiss, this.close)
+ }
+
+ Alert.VERSION = '3.3.7'
+
+ Alert.TRANSITION_DURATION = 150
+
+ Alert.prototype.close = function (e) {
+ var $this = $(this)
+ var selector = $this.attr('data-target')
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+ }
+
+ var $parent = $(selector === '#' ? [] : selector)
+
+ if (e) e.preventDefault()
+
+ if (!$parent.length) {
+ $parent = $this.closest('.alert')
+ }
+
+ $parent.trigger(e = $.Event('close.bs.alert'))
+
+ if (e.isDefaultPrevented()) return
+
+ $parent.removeClass('in')
+
+ function removeElement() {
+ // detach from parent, fire event then clean up data
+ $parent.detach().trigger('closed.bs.alert').remove()
+ }
+
+ $.support.transition && $parent.hasClass('fade') ?
+ $parent
+ .one('bsTransitionEnd', removeElement)
+ .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
+ removeElement()
+ }
+
+
+ // ALERT PLUGIN DEFINITION
+ // =======================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.alert')
+
+ if (!data) $this.data('bs.alert', (data = new Alert(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ var old = $.fn.alert
+
+ $.fn.alert = Plugin
+ $.fn.alert.Constructor = Alert
+
+
+ // ALERT NO CONFLICT
+ // =================
+
+ $.fn.alert.noConflict = function () {
+ $.fn.alert = old
+ return this
+ }
+
+
+ // ALERT DATA-API
+ // ==============
+
+ $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: button.js v3.3.7
+ * http://getbootstrap.com/javascript/#buttons
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // BUTTON PUBLIC CLASS DEFINITION
+ // ==============================
+
+ var Button = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, Button.DEFAULTS, options)
+ this.isLoading = false
+ }
+
+ Button.VERSION = '3.3.7'
+
+ Button.DEFAULTS = {
+ loadingText: 'loading...'
+ }
+
+ Button.prototype.setState = function (state) {
+ var d = 'disabled'
+ var $el = this.$element
+ var val = $el.is('input') ? 'val' : 'html'
+ var data = $el.data()
+
+ state += 'Text'
+
+ if (data.resetText == null) $el.data('resetText', $el[val]())
+
+ // push to event loop to allow forms to submit
+ setTimeout($.proxy(function () {
+ $el[val](data[state] == null ? this.options[state] : data[state])
+
+ if (state == 'loadingText') {
+ this.isLoading = true
+ $el.addClass(d).attr(d, d).prop(d, true)
+ } else if (this.isLoading) {
+ this.isLoading = false
+ $el.removeClass(d).removeAttr(d).prop(d, false)
+ }
+ }, this), 0)
+ }
+
+ Button.prototype.toggle = function () {
+ var changed = true
+ var $parent = this.$element.closest('[data-toggle="buttons"]')
+
+ if ($parent.length) {
+ var $input = this.$element.find('input')
+ if ($input.prop('type') == 'radio') {
+ if ($input.prop('checked')) changed = false
+ $parent.find('.active').removeClass('active')
+ this.$element.addClass('active')
+ } else if ($input.prop('type') == 'checkbox') {
+ if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
+ this.$element.toggleClass('active')
+ }
+ $input.prop('checked', this.$element.hasClass('active'))
+ if (changed) $input.trigger('change')
+ } else {
+ this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
+ this.$element.toggleClass('active')
+ }
+ }
+
+
+ // BUTTON PLUGIN DEFINITION
+ // ========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.button')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.button', (data = new Button(this, options)))
+
+ if (option == 'toggle') data.toggle()
+ else if (option) data.setState(option)
+ })
+ }
+
+ var old = $.fn.button
+
+ $.fn.button = Plugin
+ $.fn.button.Constructor = Button
+
+
+ // BUTTON NO CONFLICT
+ // ==================
+
+ $.fn.button.noConflict = function () {
+ $.fn.button = old
+ return this
+ }
+
+
+ // BUTTON DATA-API
+ // ===============
+
+ $(document)
+ .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
+ var $btn = $(e.target).closest('.btn')
+ Plugin.call($btn, 'toggle')
+ if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) {
+ // Prevent double click on radios, and the double selections (so cancellation) on checkboxes
+ e.preventDefault()
+ // The target component still receive the focus
+ if ($btn.is('input,button')) $btn.trigger('focus')
+ else $btn.find('input:visible,button:visible').first().trigger('focus')
+ }
+ })
+ .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
+ $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: carousel.js v3.3.7
+ * http://getbootstrap.com/javascript/#carousel
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // CAROUSEL CLASS DEFINITION
+ // =========================
+
+ var Carousel = function (element, options) {
+ this.$element = $(element)
+ this.$indicators = this.$element.find('.carousel-indicators')
+ this.options = options
+ this.paused = null
+ this.sliding = null
+ this.interval = null
+ this.$active = null
+ this.$items = null
+
+ this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
+
+ this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
+ .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
+ .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
+ }
+
+ Carousel.VERSION = '3.3.7'
+
+ Carousel.TRANSITION_DURATION = 600
+
+ Carousel.DEFAULTS = {
+ interval: 5000,
+ pause: 'hover',
+ wrap: true,
+ keyboard: true
+ }
+
+ Carousel.prototype.keydown = function (e) {
+ if (/input|textarea/i.test(e.target.tagName)) return
+ switch (e.which) {
+ case 37: this.prev(); break
+ case 39: this.next(); break
+ default: return
+ }
+
+ e.preventDefault()
+ }
+
+ Carousel.prototype.cycle = function (e) {
+ e || (this.paused = false)
+
+ this.interval && clearInterval(this.interval)
+
+ this.options.interval
+ && !this.paused
+ && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
+
+ return this
+ }
+
+ Carousel.prototype.getItemIndex = function (item) {
+ this.$items = item.parent().children('.item')
+ return this.$items.index(item || this.$active)
+ }
+
+ Carousel.prototype.getItemForDirection = function (direction, active) {
+ var activeIndex = this.getItemIndex(active)
+ var willWrap = (direction == 'prev' && activeIndex === 0)
+ || (direction == 'next' && activeIndex == (this.$items.length - 1))
+ if (willWrap && !this.options.wrap) return active
+ var delta = direction == 'prev' ? -1 : 1
+ var itemIndex = (activeIndex + delta) % this.$items.length
+ return this.$items.eq(itemIndex)
+ }
+
+ Carousel.prototype.to = function (pos) {
+ var that = this
+ var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
+
+ if (pos > (this.$items.length - 1) || pos < 0) return
+
+ if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
+ if (activeIndex == pos) return this.pause().cycle()
+
+ return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
+ }
+
+ Carousel.prototype.pause = function (e) {
+ e || (this.paused = true)
+
+ if (this.$element.find('.next, .prev').length && $.support.transition) {
+ this.$element.trigger($.support.transition.end)
+ this.cycle(true)
+ }
+
+ this.interval = clearInterval(this.interval)
+
+ return this
+ }
+
+ Carousel.prototype.next = function () {
+ if (this.sliding) return
+ return this.slide('next')
+ }
+
+ Carousel.prototype.prev = function () {
+ if (this.sliding) return
+ return this.slide('prev')
+ }
+
+ Carousel.prototype.slide = function (type, next) {
+ var $active = this.$element.find('.item.active')
+ var $next = next || this.getItemForDirection(type, $active)
+ var isCycling = this.interval
+ var direction = type == 'next' ? 'left' : 'right'
+ var that = this
+
+ if ($next.hasClass('active')) return (this.sliding = false)
+
+ var relatedTarget = $next[0]
+ var slideEvent = $.Event('slide.bs.carousel', {
+ relatedTarget: relatedTarget,
+ direction: direction
+ })
+ this.$element.trigger(slideEvent)
+ if (slideEvent.isDefaultPrevented()) return
+
+ this.sliding = true
+
+ isCycling && this.pause()
+
+ if (this.$indicators.length) {
+ this.$indicators.find('.active').removeClass('active')
+ var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
+ $nextIndicator && $nextIndicator.addClass('active')
+ }
+
+ var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
+ if ($.support.transition && this.$element.hasClass('slide')) {
+ $next.addClass(type)
+ $next[0].offsetWidth // force reflow
+ $active.addClass(direction)
+ $next.addClass(direction)
+ $active
+ .one('bsTransitionEnd', function () {
+ $next.removeClass([type, direction].join(' ')).addClass('active')
+ $active.removeClass(['active', direction].join(' '))
+ that.sliding = false
+ setTimeout(function () {
+ that.$element.trigger(slidEvent)
+ }, 0)
+ })
+ .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
+ } else {
+ $active.removeClass('active')
+ $next.addClass('active')
+ this.sliding = false
+ this.$element.trigger(slidEvent)
+ }
+
+ isCycling && this.cycle()
+
+ return this
+ }
+
+
+ // CAROUSEL PLUGIN DEFINITION
+ // ==========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.carousel')
+ var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
+ var action = typeof option == 'string' ? option : options.slide
+
+ if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
+ if (typeof option == 'number') data.to(option)
+ else if (action) data[action]()
+ else if (options.interval) data.pause().cycle()
+ })
+ }
+
+ var old = $.fn.carousel
+
+ $.fn.carousel = Plugin
+ $.fn.carousel.Constructor = Carousel
+
+
+ // CAROUSEL NO CONFLICT
+ // ====================
+
+ $.fn.carousel.noConflict = function () {
+ $.fn.carousel = old
+ return this
+ }
+
+
+ // CAROUSEL DATA-API
+ // =================
+
+ var clickHandler = function (e) {
+ var href
+ var $this = $(this)
+ var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
+ if (!$target.hasClass('carousel')) return
+ var options = $.extend({}, $target.data(), $this.data())
+ var slideIndex = $this.attr('data-slide-to')
+ if (slideIndex) options.interval = false
+
+ Plugin.call($target, options)
+
+ if (slideIndex) {
+ $target.data('bs.carousel').to(slideIndex)
+ }
+
+ e.preventDefault()
+ }
+
+ $(document)
+ .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
+ .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
+
+ $(window).on('load', function () {
+ $('[data-ride="carousel"]').each(function () {
+ var $carousel = $(this)
+ Plugin.call($carousel, $carousel.data())
+ })
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: collapse.js v3.3.7
+ * http://getbootstrap.com/javascript/#collapse
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+/* jshint latedef: false */
+
++function ($) {
+ 'use strict';
+
+ // COLLAPSE PUBLIC CLASS DEFINITION
+ // ================================
+
+ var Collapse = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, Collapse.DEFAULTS, options)
+ this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
+ '[data-toggle="collapse"][data-target="#' + element.id + '"]')
+ this.transitioning = null
+
+ if (this.options.parent) {
+ this.$parent = this.getParent()
+ } else {
+ this.addAriaAndCollapsedClass(this.$element, this.$trigger)
+ }
+
+ if (this.options.toggle) this.toggle()
+ }
+
+ Collapse.VERSION = '3.3.7'
+
+ Collapse.TRANSITION_DURATION = 350
+
+ Collapse.DEFAULTS = {
+ toggle: true
+ }
+
+ Collapse.prototype.dimension = function () {
+ var hasWidth = this.$element.hasClass('width')
+ return hasWidth ? 'width' : 'height'
+ }
+
+ Collapse.prototype.show = function () {
+ if (this.transitioning || this.$element.hasClass('in')) return
+
+ var activesData
+ var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
+
+ if (actives && actives.length) {
+ activesData = actives.data('bs.collapse')
+ if (activesData && activesData.transitioning) return
+ }
+
+ var startEvent = $.Event('show.bs.collapse')
+ this.$element.trigger(startEvent)
+ if (startEvent.isDefaultPrevented()) return
+
+ if (actives && actives.length) {
+ Plugin.call(actives, 'hide')
+ activesData || actives.data('bs.collapse', null)
+ }
+
+ var dimension = this.dimension()
+
+ this.$element
+ .removeClass('collapse')
+ .addClass('collapsing')[dimension](0)
+ .attr('aria-expanded', true)
+
+ this.$trigger
+ .removeClass('collapsed')
+ .attr('aria-expanded', true)
+
+ this.transitioning = 1
+
+ var complete = function () {
+ this.$element
+ .removeClass('collapsing')
+ .addClass('collapse in')[dimension]('')
+ this.transitioning = 0
+ this.$element
+ .trigger('shown.bs.collapse')
+ }
+
+ if (!$.support.transition) return complete.call(this)
+
+ var scrollSize = $.camelCase(['scroll', dimension].join('-'))
+
+ this.$element
+ .one('bsTransitionEnd', $.proxy(complete, this))
+ .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
+ }
+
+ Collapse.prototype.hide = function () {
+ if (this.transitioning || !this.$element.hasClass('in')) return
+
+ var startEvent = $.Event('hide.bs.collapse')
+ this.$element.trigger(startEvent)
+ if (startEvent.isDefaultPrevented()) return
+
+ var dimension = this.dimension()
+
+ this.$element[dimension](this.$element[dimension]())[0].offsetHeight
+
+ this.$element
+ .addClass('collapsing')
+ .removeClass('collapse in')
+ .attr('aria-expanded', false)
+
+ this.$trigger
+ .addClass('collapsed')
+ .attr('aria-expanded', false)
+
+ this.transitioning = 1
+
+ var complete = function () {
+ this.transitioning = 0
+ this.$element
+ .removeClass('collapsing')
+ .addClass('collapse')
+ .trigger('hidden.bs.collapse')
+ }
+
+ if (!$.support.transition) return complete.call(this)
+
+ this.$element
+ [dimension](0)
+ .one('bsTransitionEnd', $.proxy(complete, this))
+ .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
+ }
+
+ Collapse.prototype.toggle = function () {
+ this[this.$element.hasClass('in') ? 'hide' : 'show']()
+ }
+
+ Collapse.prototype.getParent = function () {
+ return $(this.options.parent)
+ .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
+ .each($.proxy(function (i, element) {
+ var $element = $(element)
+ this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
+ }, this))
+ .end()
+ }
+
+ Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
+ var isOpen = $element.hasClass('in')
+
+ $element.attr('aria-expanded', isOpen)
+ $trigger
+ .toggleClass('collapsed', !isOpen)
+ .attr('aria-expanded', isOpen)
+ }
+
+ function getTargetFromTrigger($trigger) {
+ var href
+ var target = $trigger.attr('data-target')
+ || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
+
+ return $(target)
+ }
+
+
+ // COLLAPSE PLUGIN DEFINITION
+ // ==========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.collapse')
+ var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
+
+ if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
+ if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.collapse
+
+ $.fn.collapse = Plugin
+ $.fn.collapse.Constructor = Collapse
+
+
+ // COLLAPSE NO CONFLICT
+ // ====================
+
+ $.fn.collapse.noConflict = function () {
+ $.fn.collapse = old
+ return this
+ }
+
+
+ // COLLAPSE DATA-API
+ // =================
+
+ $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
+ var $this = $(this)
+
+ if (!$this.attr('data-target')) e.preventDefault()
+
+ var $target = getTargetFromTrigger($this)
+ var data = $target.data('bs.collapse')
+ var option = data ? 'toggle' : $this.data()
+
+ Plugin.call($target, option)
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: dropdown.js v3.3.7
+ * http://getbootstrap.com/javascript/#dropdowns
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // DROPDOWN CLASS DEFINITION
+ // =========================
+
+ var backdrop = '.dropdown-backdrop'
+ var toggle = '[data-toggle="dropdown"]'
+ var Dropdown = function (element) {
+ $(element).on('click.bs.dropdown', this.toggle)
+ }
+
+ Dropdown.VERSION = '3.3.7'
+
+ function getParent($this) {
+ var selector = $this.attr('data-target')
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+ }
+
+ var $parent = selector && $(selector)
+
+ return $parent && $parent.length ? $parent : $this.parent()
+ }
+
+ function clearMenus(e) {
+ if (e && e.which === 3) return
+ $(backdrop).remove()
+ $(toggle).each(function () {
+ var $this = $(this)
+ var $parent = getParent($this)
+ var relatedTarget = { relatedTarget: this }
+
+ if (!$parent.hasClass('open')) return
+
+ if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
+
+ $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
+
+ if (e.isDefaultPrevented()) return
+
+ $this.attr('aria-expanded', 'false')
+ $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget))
+ })
+ }
+
+ Dropdown.prototype.toggle = function (e) {
+ var $this = $(this)
+
+ if ($this.is('.disabled, :disabled')) return
+
+ var $parent = getParent($this)
+ var isActive = $parent.hasClass('open')
+
+ clearMenus()
+
+ if (!isActive) {
+ if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
+ // if mobile we use a backdrop because click events don't delegate
+ $(document.createElement('div'))
+ .addClass('dropdown-backdrop')
+ .insertAfter($(this))
+ .on('click', clearMenus)
+ }
+
+ var relatedTarget = { relatedTarget: this }
+ $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
+
+ if (e.isDefaultPrevented()) return
+
+ $this
+ .trigger('focus')
+ .attr('aria-expanded', 'true')
+
+ $parent
+ .toggleClass('open')
+ .trigger($.Event('shown.bs.dropdown', relatedTarget))
+ }
+
+ return false
+ }
+
+ Dropdown.prototype.keydown = function (e) {
+ if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
+
+ var $this = $(this)
+
+ e.preventDefault()
+ e.stopPropagation()
+
+ if ($this.is('.disabled, :disabled')) return
+
+ var $parent = getParent($this)
+ var isActive = $parent.hasClass('open')
+
+ if (!isActive && e.which != 27 || isActive && e.which == 27) {
+ if (e.which == 27) $parent.find(toggle).trigger('focus')
+ return $this.trigger('click')
+ }
+
+ var desc = ' li:not(.disabled):visible a'
+ var $items = $parent.find('.dropdown-menu' + desc)
+
+ if (!$items.length) return
+
+ var index = $items.index(e.target)
+
+ if (e.which == 38 && index > 0) index-- // up
+ if (e.which == 40 && index < $items.length - 1) index++ // down
+ if (!~index) index = 0
+
+ $items.eq(index).trigger('focus')
+ }
+
+
+ // DROPDOWN PLUGIN DEFINITION
+ // ==========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.dropdown')
+
+ if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ var old = $.fn.dropdown
+
+ $.fn.dropdown = Plugin
+ $.fn.dropdown.Constructor = Dropdown
+
+
+ // DROPDOWN NO CONFLICT
+ // ====================
+
+ $.fn.dropdown.noConflict = function () {
+ $.fn.dropdown = old
+ return this
+ }
+
+
+ // APPLY TO STANDARD DROPDOWN ELEMENTS
+ // ===================================
+
+ $(document)
+ .on('click.bs.dropdown.data-api', clearMenus)
+ .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
+ .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
+ .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
+ .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: modal.js v3.3.7
+ * http://getbootstrap.com/javascript/#modals
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // MODAL CLASS DEFINITION
+ // ======================
+
+ var Modal = function (element, options) {
+ this.options = options
+ this.$body = $(document.body)
+ this.$element = $(element)
+ this.$dialog = this.$element.find('.modal-dialog')
+ this.$backdrop = null
+ this.isShown = null
+ this.originalBodyPad = null
+ this.scrollbarWidth = 0
+ this.ignoreBackdropClick = false
+
+ if (this.options.remote) {
+ this.$element
+ .find('.modal-content')
+ .load(this.options.remote, $.proxy(function () {
+ this.$element.trigger('loaded.bs.modal')
+ }, this))
+ }
+ }
+
+ Modal.VERSION = '3.3.7'
+
+ Modal.TRANSITION_DURATION = 300
+ Modal.BACKDROP_TRANSITION_DURATION = 150
+
+ Modal.DEFAULTS = {
+ backdrop: true,
+ keyboard: true,
+ show: true
+ }
+
+ Modal.prototype.toggle = function (_relatedTarget) {
+ return this.isShown ? this.hide() : this.show(_relatedTarget)
+ }
+
+ Modal.prototype.show = function (_relatedTarget) {
+ var that = this
+ var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
+
+ this.$element.trigger(e)
+
+ if (this.isShown || e.isDefaultPrevented()) return
+
+ this.isShown = true
+
+ this.checkScrollbar()
+ this.setScrollbar()
+ this.$body.addClass('modal-open')
+
+ this.escape()
+ this.resize()
+
+ this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
+
+ this.$dialog.on('mousedown.dismiss.bs.modal', function () {
+ that.$element.one('mouseup.dismiss.bs.modal', function (e) {
+ if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
+ })
+ })
+
+ this.backdrop(function () {
+ var transition = $.support.transition && that.$element.hasClass('fade')
+
+ if (!that.$element.parent().length) {
+ that.$element.appendTo(that.$body) // don't move modals dom position
+ }
+
+ that.$element
+ .show()
+ .scrollTop(0)
+
+ that.adjustDialog()
+
+ if (transition) {
+ that.$element[0].offsetWidth // force reflow
+ }
+
+ that.$element.addClass('in')
+
+ that.enforceFocus()
+
+ var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
+
+ transition ?
+ that.$dialog // wait for modal to slide in
+ .one('bsTransitionEnd', function () {
+ that.$element.trigger('focus').trigger(e)
+ })
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
+ that.$element.trigger('focus').trigger(e)
+ })
+ }
+
+ Modal.prototype.hide = function (e) {
+ if (e) e.preventDefault()
+
+ e = $.Event('hide.bs.modal')
+
+ this.$element.trigger(e)
+
+ if (!this.isShown || e.isDefaultPrevented()) return
+
+ this.isShown = false
+
+ this.escape()
+ this.resize()
+
+ $(document).off('focusin.bs.modal')
+
+ this.$element
+ .removeClass('in')
+ .off('click.dismiss.bs.modal')
+ .off('mouseup.dismiss.bs.modal')
+
+ this.$dialog.off('mousedown.dismiss.bs.modal')
+
+ $.support.transition && this.$element.hasClass('fade') ?
+ this.$element
+ .one('bsTransitionEnd', $.proxy(this.hideModal, this))
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
+ this.hideModal()
+ }
+
+ Modal.prototype.enforceFocus = function () {
+ $(document)
+ .off('focusin.bs.modal') // guard against infinite focus loop
+ .on('focusin.bs.modal', $.proxy(function (e) {
+ if (document !== e.target &&
+ this.$element[0] !== e.target &&
+ !this.$element.has(e.target).length) {
+ this.$element.trigger('focus')
+ }
+ }, this))
+ }
+
+ Modal.prototype.escape = function () {
+ if (this.isShown && this.options.keyboard) {
+ this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
+ e.which == 27 && this.hide()
+ }, this))
+ } else if (!this.isShown) {
+ this.$element.off('keydown.dismiss.bs.modal')
+ }
+ }
+
+ Modal.prototype.resize = function () {
+ if (this.isShown) {
+ $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
+ } else {
+ $(window).off('resize.bs.modal')
+ }
+ }
+
+ Modal.prototype.hideModal = function () {
+ var that = this
+ this.$element.hide()
+ this.backdrop(function () {
+ that.$body.removeClass('modal-open')
+ that.resetAdjustments()
+ that.resetScrollbar()
+ that.$element.trigger('hidden.bs.modal')
+ })
+ }
+
+ Modal.prototype.removeBackdrop = function () {
+ this.$backdrop && this.$backdrop.remove()
+ this.$backdrop = null
+ }
+
+ Modal.prototype.backdrop = function (callback) {
+ var that = this
+ var animate = this.$element.hasClass('fade') ? 'fade' : ''
+
+ if (this.isShown && this.options.backdrop) {
+ var doAnimate = $.support.transition && animate
+
+ this.$backdrop = $(document.createElement('div'))
+ .addClass('modal-backdrop ' + animate)
+ .appendTo(this.$body)
+
+ this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
+ if (this.ignoreBackdropClick) {
+ this.ignoreBackdropClick = false
+ return
+ }
+ if (e.target !== e.currentTarget) return
+ this.options.backdrop == 'static'
+ ? this.$element[0].focus()
+ : this.hide()
+ }, this))
+
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
+
+ this.$backdrop.addClass('in')
+
+ if (!callback) return
+
+ doAnimate ?
+ this.$backdrop
+ .one('bsTransitionEnd', callback)
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
+ callback()
+
+ } else if (!this.isShown && this.$backdrop) {
+ this.$backdrop.removeClass('in')
+
+ var callbackRemove = function () {
+ that.removeBackdrop()
+ callback && callback()
+ }
+ $.support.transition && this.$element.hasClass('fade') ?
+ this.$backdrop
+ .one('bsTransitionEnd', callbackRemove)
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
+ callbackRemove()
+
+ } else if (callback) {
+ callback()
+ }
+ }
+
+ // these following methods are used to handle overflowing modals
+
+ Modal.prototype.handleUpdate = function () {
+ this.adjustDialog()
+ }
+
+ Modal.prototype.adjustDialog = function () {
+ var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
+
+ this.$element.css({
+ paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
+ paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
+ })
+ }
+
+ Modal.prototype.resetAdjustments = function () {
+ this.$element.css({
+ paddingLeft: '',
+ paddingRight: ''
+ })
+ }
+
+ Modal.prototype.checkScrollbar = function () {
+ var fullWindowWidth = window.innerWidth
+ if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
+ var documentElementRect = document.documentElement.getBoundingClientRect()
+ fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
+ }
+ this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
+ this.scrollbarWidth = this.measureScrollbar()
+ }
+
+ Modal.prototype.setScrollbar = function () {
+ var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
+ this.originalBodyPad = document.body.style.paddingRight || ''
+ if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
+ }
+
+ Modal.prototype.resetScrollbar = function () {
+ this.$body.css('padding-right', this.originalBodyPad)
+ }
+
+ Modal.prototype.measureScrollbar = function () { // thx walsh
+ var scrollDiv = document.createElement('div')
+ scrollDiv.className = 'modal-scrollbar-measure'
+ this.$body.append(scrollDiv)
+ var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
+ this.$body[0].removeChild(scrollDiv)
+ return scrollbarWidth
+ }
+
+
+ // MODAL PLUGIN DEFINITION
+ // =======================
+
+ function Plugin(option, _relatedTarget) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.modal')
+ var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
+
+ if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
+ if (typeof option == 'string') data[option](_relatedTarget)
+ else if (options.show) data.show(_relatedTarget)
+ })
+ }
+
+ var old = $.fn.modal
+
+ $.fn.modal = Plugin
+ $.fn.modal.Constructor = Modal
+
+
+ // MODAL NO CONFLICT
+ // =================
+
+ $.fn.modal.noConflict = function () {
+ $.fn.modal = old
+ return this
+ }
+
+
+ // MODAL DATA-API
+ // ==============
+
+ $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
+ var $this = $(this)
+ var href = $this.attr('href')
+ var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
+ var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
+
+ if ($this.is('a')) e.preventDefault()
+
+ $target.one('show.bs.modal', function (showEvent) {
+ if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
+ $target.one('hidden.bs.modal', function () {
+ $this.is(':visible') && $this.trigger('focus')
+ })
+ })
+ Plugin.call($target, option, this)
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: tooltip.js v3.3.7
+ * http://getbootstrap.com/javascript/#tooltip
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // TOOLTIP PUBLIC CLASS DEFINITION
+ // ===============================
+
+ var Tooltip = function (element, options) {
+ this.type = null
+ this.options = null
+ this.enabled = null
+ this.timeout = null
+ this.hoverState = null
+ this.$element = null
+ this.inState = null
+
+ this.init('tooltip', element, options)
+ }
+
+ Tooltip.VERSION = '3.3.7'
+
+ Tooltip.TRANSITION_DURATION = 150
+
+ Tooltip.DEFAULTS = {
+ animation: true,
+ placement: 'top',
+ selector: false,
+ template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
+ trigger: 'hover focus',
+ title: '',
+ delay: 0,
+ html: false,
+ container: false,
+ viewport: {
+ selector: 'body',
+ padding: 0
+ }
+ }
+
+ Tooltip.prototype.init = function (type, element, options) {
+ this.enabled = true
+ this.type = type
+ this.$element = $(element)
+ this.options = this.getOptions(options)
+ this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
+ this.inState = { click: false, hover: false, focus: false }
+
+ if (this.$element[0] instanceof document.constructor && !this.options.selector) {
+ throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
+ }
+
+ var triggers = this.options.trigger.split(' ')
+
+ for (var i = triggers.length; i--;) {
+ var trigger = triggers[i]
+
+ if (trigger == 'click') {
+ this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
+ } else if (trigger != 'manual') {
+ var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
+ var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
+
+ this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
+ this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
+ }
+ }
+
+ this.options.selector ?
+ (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+ this.fixTitle()
+ }
+
+ Tooltip.prototype.getDefaults = function () {
+ return Tooltip.DEFAULTS
+ }
+
+ Tooltip.prototype.getOptions = function (options) {
+ options = $.extend({}, this.getDefaults(), this.$element.data(), options)
+
+ if (options.delay && typeof options.delay == 'number') {
+ options.delay = {
+ show: options.delay,
+ hide: options.delay
+ }
+ }
+
+ return options
+ }
+
+ Tooltip.prototype.getDelegateOptions = function () {
+ var options = {}
+ var defaults = this.getDefaults()
+
+ this._options && $.each(this._options, function (key, value) {
+ if (defaults[key] != value) options[key] = value
+ })
+
+ return options
+ }
+
+ Tooltip.prototype.enter = function (obj) {
+ var self = obj instanceof this.constructor ?
+ obj : $(obj.currentTarget).data('bs.' + this.type)
+
+ if (!self) {
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
+ $(obj.currentTarget).data('bs.' + this.type, self)
+ }
+
+ if (obj instanceof $.Event) {
+ self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
+ }
+
+ if (self.tip().hasClass('in') || self.hoverState == 'in') {
+ self.hoverState = 'in'
+ return
+ }
+
+ clearTimeout(self.timeout)
+
+ self.hoverState = 'in'
+
+ if (!self.options.delay || !self.options.delay.show) return self.show()
+
+ self.timeout = setTimeout(function () {
+ if (self.hoverState == 'in') self.show()
+ }, self.options.delay.show)
+ }
+
+ Tooltip.prototype.isInStateTrue = function () {
+ for (var key in this.inState) {
+ if (this.inState[key]) return true
+ }
+
+ return false
+ }
+
+ Tooltip.prototype.leave = function (obj) {
+ var self = obj instanceof this.constructor ?
+ obj : $(obj.currentTarget).data('bs.' + this.type)
+
+ if (!self) {
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
+ $(obj.currentTarget).data('bs.' + this.type, self)
+ }
+
+ if (obj instanceof $.Event) {
+ self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
+ }
+
+ if (self.isInStateTrue()) return
+
+ clearTimeout(self.timeout)
+
+ self.hoverState = 'out'
+
+ if (!self.options.delay || !self.options.delay.hide) return self.hide()
+
+ self.timeout = setTimeout(function () {
+ if (self.hoverState == 'out') self.hide()
+ }, self.options.delay.hide)
+ }
+
+ Tooltip.prototype.show = function () {
+ var e = $.Event('show.bs.' + this.type)
+
+ if (this.hasContent() && this.enabled) {
+ this.$element.trigger(e)
+
+ var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
+ if (e.isDefaultPrevented() || !inDom) return
+ var that = this
+
+ var $tip = this.tip()
+
+ var tipId = this.getUID(this.type)
+
+ this.setContent()
+ $tip.attr('id', tipId)
+ this.$element.attr('aria-describedby', tipId)
+
+ if (this.options.animation) $tip.addClass('fade')
+
+ var placement = typeof this.options.placement == 'function' ?
+ this.options.placement.call(this, $tip[0], this.$element[0]) :
+ this.options.placement
+
+ var autoToken = /\s?auto?\s?/i
+ var autoPlace = autoToken.test(placement)
+ if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
+
+ $tip
+ .detach()
+ .css({ top: 0, left: 0, display: 'block' })
+ .addClass(placement)
+ .data('bs.' + this.type, this)
+
+ this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
+ this.$element.trigger('inserted.bs.' + this.type)
+
+ var pos = this.getPosition()
+ var actualWidth = $tip[0].offsetWidth
+ var actualHeight = $tip[0].offsetHeight
+
+ if (autoPlace) {
+ var orgPlacement = placement
+ var viewportDim = this.getPosition(this.$viewport)
+
+ placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' :
+ placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' :
+ placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' :
+ placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' :
+ placement
+
+ $tip
+ .removeClass(orgPlacement)
+ .addClass(placement)
+ }
+
+ var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
+
+ this.applyPlacement(calculatedOffset, placement)
+
+ var complete = function () {
+ var prevHoverState = that.hoverState
+ that.$element.trigger('shown.bs.' + that.type)
+ that.hoverState = null
+
+ if (prevHoverState == 'out') that.leave(that)
+ }
+
+ $.support.transition && this.$tip.hasClass('fade') ?
+ $tip
+ .one('bsTransitionEnd', complete)
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
+ complete()
+ }
+ }
+
+ Tooltip.prototype.applyPlacement = function (offset, placement) {
+ var $tip = this.tip()
+ var width = $tip[0].offsetWidth
+ var height = $tip[0].offsetHeight
+
+ // manually read margins because getBoundingClientRect includes difference
+ var marginTop = parseInt($tip.css('margin-top'), 10)
+ var marginLeft = parseInt($tip.css('margin-left'), 10)
+
+ // we must check for NaN for ie 8/9
+ if (isNaN(marginTop)) marginTop = 0
+ if (isNaN(marginLeft)) marginLeft = 0
+
+ offset.top += marginTop
+ offset.left += marginLeft
+
+ // $.fn.offset doesn't round pixel values
+ // so we use setOffset directly with our own function B-0
+ $.offset.setOffset($tip[0], $.extend({
+ using: function (props) {
+ $tip.css({
+ top: Math.round(props.top),
+ left: Math.round(props.left)
+ })
+ }
+ }, offset), 0)
+
+ $tip.addClass('in')
+
+ // check to see if placing tip in new offset caused the tip to resize itself
+ var actualWidth = $tip[0].offsetWidth
+ var actualHeight = $tip[0].offsetHeight
+
+ if (placement == 'top' && actualHeight != height) {
+ offset.top = offset.top + height - actualHeight
+ }
+
+ var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
+
+ if (delta.left) offset.left += delta.left
+ else offset.top += delta.top
+
+ var isVertical = /top|bottom/.test(placement)
+ var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
+ var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
+
+ $tip.offset(offset)
+ this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
+ }
+
+ Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
+ this.arrow()
+ .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
+ .css(isVertical ? 'top' : 'left', '')
+ }
+
+ Tooltip.prototype.setContent = function () {
+ var $tip = this.tip()
+ var title = this.getTitle()
+
+ $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
+ $tip.removeClass('fade in top bottom left right')
+ }
+
+ Tooltip.prototype.hide = function (callback) {
+ var that = this
+ var $tip = $(this.$tip)
+ var e = $.Event('hide.bs.' + this.type)
+
+ function complete() {
+ if (that.hoverState != 'in') $tip.detach()
+ if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary.
+ that.$element
+ .removeAttr('aria-describedby')
+ .trigger('hidden.bs.' + that.type)
+ }
+ callback && callback()
+ }
+
+ this.$element.trigger(e)
+
+ if (e.isDefaultPrevented()) return
+
+ $tip.removeClass('in')
+
+ $.support.transition && $tip.hasClass('fade') ?
+ $tip
+ .one('bsTransitionEnd', complete)
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
+ complete()
+
+ this.hoverState = null
+
+ return this
+ }
+
+ Tooltip.prototype.fixTitle = function () {
+ var $e = this.$element
+ if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
+ $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
+ }
+ }
+
+ Tooltip.prototype.hasContent = function () {
+ return this.getTitle()
+ }
+
+ Tooltip.prototype.getPosition = function ($element) {
+ $element = $element || this.$element
+
+ var el = $element[0]
+ var isBody = el.tagName == 'BODY'
+
+ var elRect = el.getBoundingClientRect()
+ if (elRect.width == null) {
+ // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
+ elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
+ }
+ var isSvg = window.SVGElement && el instanceof window.SVGElement
+ // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3.
+ // See https://github.com/twbs/bootstrap/issues/20280
+ var elOffset = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset())
+ var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
+ var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
+
+ return $.extend({}, elRect, scroll, outerDims, elOffset)
+ }
+
+ Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
+ return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
+ placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
+ placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
+ /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
+
+ }
+
+ Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
+ var delta = { top: 0, left: 0 }
+ if (!this.$viewport) return delta
+
+ var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
+ var viewportDimensions = this.getPosition(this.$viewport)
+
+ if (/right|left/.test(placement)) {
+ var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
+ var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
+ if (topEdgeOffset < viewportDimensions.top) { // top overflow
+ delta.top = viewportDimensions.top - topEdgeOffset
+ } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
+ delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
+ }
+ } else {
+ var leftEdgeOffset = pos.left - viewportPadding
+ var rightEdgeOffset = pos.left + viewportPadding + actualWidth
+ if (leftEdgeOffset < viewportDimensions.left) { // left overflow
+ delta.left = viewportDimensions.left - leftEdgeOffset
+ } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
+ delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
+ }
+ }
+
+ return delta
+ }
+
+ Tooltip.prototype.getTitle = function () {
+ var title
+ var $e = this.$element
+ var o = this.options
+
+ title = $e.attr('data-original-title')
+ || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
+
+ return title
+ }
+
+ Tooltip.prototype.getUID = function (prefix) {
+ do prefix += ~~(Math.random() * 1000000)
+ while (document.getElementById(prefix))
+ return prefix
+ }
+
+ Tooltip.prototype.tip = function () {
+ if (!this.$tip) {
+ this.$tip = $(this.options.template)
+ if (this.$tip.length != 1) {
+ throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
+ }
+ }
+ return this.$tip
+ }
+
+ Tooltip.prototype.arrow = function () {
+ return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
+ }
+
+ Tooltip.prototype.enable = function () {
+ this.enabled = true
+ }
+
+ Tooltip.prototype.disable = function () {
+ this.enabled = false
+ }
+
+ Tooltip.prototype.toggleEnabled = function () {
+ this.enabled = !this.enabled
+ }
+
+ Tooltip.prototype.toggle = function (e) {
+ var self = this
+ if (e) {
+ self = $(e.currentTarget).data('bs.' + this.type)
+ if (!self) {
+ self = new this.constructor(e.currentTarget, this.getDelegateOptions())
+ $(e.currentTarget).data('bs.' + this.type, self)
+ }
+ }
+
+ if (e) {
+ self.inState.click = !self.inState.click
+ if (self.isInStateTrue()) self.enter(self)
+ else self.leave(self)
+ } else {
+ self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
+ }
+ }
+
+ Tooltip.prototype.destroy = function () {
+ var that = this
+ clearTimeout(this.timeout)
+ this.hide(function () {
+ that.$element.off('.' + that.type).removeData('bs.' + that.type)
+ if (that.$tip) {
+ that.$tip.detach()
+ }
+ that.$tip = null
+ that.$arrow = null
+ that.$viewport = null
+ that.$element = null
+ })
+ }
+
+
+ // TOOLTIP PLUGIN DEFINITION
+ // =========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.tooltip')
+ var options = typeof option == 'object' && option
+
+ if (!data && /destroy|hide/.test(option)) return
+ if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.tooltip
+
+ $.fn.tooltip = Plugin
+ $.fn.tooltip.Constructor = Tooltip
+
+
+ // TOOLTIP NO CONFLICT
+ // ===================
+
+ $.fn.tooltip.noConflict = function () {
+ $.fn.tooltip = old
+ return this
+ }
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: popover.js v3.3.7
+ * http://getbootstrap.com/javascript/#popovers
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // POPOVER PUBLIC CLASS DEFINITION
+ // ===============================
+
+ var Popover = function (element, options) {
+ this.init('popover', element, options)
+ }
+
+ if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
+
+ Popover.VERSION = '3.3.7'
+
+ Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
+ placement: 'right',
+ trigger: 'click',
+ content: '',
+ template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
+ })
+
+
+ // NOTE: POPOVER EXTENDS tooltip.js
+ // ================================
+
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
+
+ Popover.prototype.constructor = Popover
+
+ Popover.prototype.getDefaults = function () {
+ return Popover.DEFAULTS
+ }
+
+ Popover.prototype.setContent = function () {
+ var $tip = this.tip()
+ var title = this.getTitle()
+ var content = this.getContent()
+
+ $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
+ $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
+ this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
+ ](content)
+
+ $tip.removeClass('fade top bottom left right in')
+
+ // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
+ // this manually by checking the contents.
+ if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
+ }
+
+ Popover.prototype.hasContent = function () {
+ return this.getTitle() || this.getContent()
+ }
+
+ Popover.prototype.getContent = function () {
+ var $e = this.$element
+ var o = this.options
+
+ return $e.attr('data-content')
+ || (typeof o.content == 'function' ?
+ o.content.call($e[0]) :
+ o.content)
+ }
+
+ Popover.prototype.arrow = function () {
+ return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
+ }
+
+
+ // POPOVER PLUGIN DEFINITION
+ // =========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.popover')
+ var options = typeof option == 'object' && option
+
+ if (!data && /destroy|hide/.test(option)) return
+ if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.popover
+
+ $.fn.popover = Plugin
+ $.fn.popover.Constructor = Popover
+
+
+ // POPOVER NO CONFLICT
+ // ===================
+
+ $.fn.popover.noConflict = function () {
+ $.fn.popover = old
+ return this
+ }
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: scrollspy.js v3.3.7
+ * http://getbootstrap.com/javascript/#scrollspy
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // SCROLLSPY CLASS DEFINITION
+ // ==========================
+
+ function ScrollSpy(element, options) {
+ this.$body = $(document.body)
+ this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
+ this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
+ this.selector = (this.options.target || '') + ' .nav li > a'
+ this.offsets = []
+ this.targets = []
+ this.activeTarget = null
+ this.scrollHeight = 0
+
+ this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
+ this.refresh()
+ this.process()
+ }
+
+ ScrollSpy.VERSION = '3.3.7'
+
+ ScrollSpy.DEFAULTS = {
+ offset: 10
+ }
+
+ ScrollSpy.prototype.getScrollHeight = function () {
+ return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
+ }
+
+ ScrollSpy.prototype.refresh = function () {
+ var that = this
+ var offsetMethod = 'offset'
+ var offsetBase = 0
+
+ this.offsets = []
+ this.targets = []
+ this.scrollHeight = this.getScrollHeight()
+
+ if (!$.isWindow(this.$scrollElement[0])) {
+ offsetMethod = 'position'
+ offsetBase = this.$scrollElement.scrollTop()
+ }
+
+ this.$body
+ .find(this.selector)
+ .map(function () {
+ var $el = $(this)
+ var href = $el.data('target') || $el.attr('href')
+ var $href = /^#./.test(href) && $(href)
+
+ return ($href
+ && $href.length
+ && $href.is(':visible')
+ && [[$href[offsetMethod]().top + offsetBase, href]]) || null
+ })
+ .sort(function (a, b) { return a[0] - b[0] })
+ .each(function () {
+ that.offsets.push(this[0])
+ that.targets.push(this[1])
+ })
+ }
+
+ ScrollSpy.prototype.process = function () {
+ var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
+ var scrollHeight = this.getScrollHeight()
+ var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
+ var offsets = this.offsets
+ var targets = this.targets
+ var activeTarget = this.activeTarget
+ var i
+
+ if (this.scrollHeight != scrollHeight) {
+ this.refresh()
+ }
+
+ if (scrollTop >= maxScroll) {
+ return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
+ }
+
+ if (activeTarget && scrollTop < offsets[0]) {
+ this.activeTarget = null
+ return this.clear()
+ }
+
+ for (i = offsets.length; i--;) {
+ activeTarget != targets[i]
+ && scrollTop >= offsets[i]
+ && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
+ && this.activate(targets[i])
+ }
+ }
+
+ ScrollSpy.prototype.activate = function (target) {
+ this.activeTarget = target
+
+ this.clear()
+
+ var selector = this.selector +
+ '[data-target="' + target + '"],' +
+ this.selector + '[href="' + target + '"]'
+
+ var active = $(selector)
+ .parents('li')
+ .addClass('active')
+
+ if (active.parent('.dropdown-menu').length) {
+ active = active
+ .closest('li.dropdown')
+ .addClass('active')
+ }
+
+ active.trigger('activate.bs.scrollspy')
+ }
+
+ ScrollSpy.prototype.clear = function () {
+ $(this.selector)
+ .parentsUntil(this.options.target, '.active')
+ .removeClass('active')
+ }
+
+
+ // SCROLLSPY PLUGIN DEFINITION
+ // ===========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.scrollspy')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.scrollspy
+
+ $.fn.scrollspy = Plugin
+ $.fn.scrollspy.Constructor = ScrollSpy
+
+
+ // SCROLLSPY NO CONFLICT
+ // =====================
+
+ $.fn.scrollspy.noConflict = function () {
+ $.fn.scrollspy = old
+ return this
+ }
+
+
+ // SCROLLSPY DATA-API
+ // ==================
+
+ $(window).on('load.bs.scrollspy.data-api', function () {
+ $('[data-spy="scroll"]').each(function () {
+ var $spy = $(this)
+ Plugin.call($spy, $spy.data())
+ })
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: tab.js v3.3.7
+ * http://getbootstrap.com/javascript/#tabs
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // TAB CLASS DEFINITION
+ // ====================
+
+ var Tab = function (element) {
+ // jscs:disable requireDollarBeforejQueryAssignment
+ this.element = $(element)
+ // jscs:enable requireDollarBeforejQueryAssignment
+ }
+
+ Tab.VERSION = '3.3.7'
+
+ Tab.TRANSITION_DURATION = 150
+
+ Tab.prototype.show = function () {
+ var $this = this.element
+ var $ul = $this.closest('ul:not(.dropdown-menu)')
+ var selector = $this.data('target')
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+ }
+
+ if ($this.parent('li').hasClass('active')) return
+
+ var $previous = $ul.find('.active:last a')
+ var hideEvent = $.Event('hide.bs.tab', {
+ relatedTarget: $this[0]
+ })
+ var showEvent = $.Event('show.bs.tab', {
+ relatedTarget: $previous[0]
+ })
+
+ $previous.trigger(hideEvent)
+ $this.trigger(showEvent)
+
+ if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
+
+ var $target = $(selector)
+
+ this.activate($this.closest('li'), $ul)
+ this.activate($target, $target.parent(), function () {
+ $previous.trigger({
+ type: 'hidden.bs.tab',
+ relatedTarget: $this[0]
+ })
+ $this.trigger({
+ type: 'shown.bs.tab',
+ relatedTarget: $previous[0]
+ })
+ })
+ }
+
+ Tab.prototype.activate = function (element, container, callback) {
+ var $active = container.find('> .active')
+ var transition = callback
+ && $.support.transition
+ && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
+
+ function next() {
+ $active
+ .removeClass('active')
+ .find('> .dropdown-menu > .active')
+ .removeClass('active')
+ .end()
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', false)
+
+ element
+ .addClass('active')
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', true)
+
+ if (transition) {
+ element[0].offsetWidth // reflow for transition
+ element.addClass('in')
+ } else {
+ element.removeClass('fade')
+ }
+
+ if (element.parent('.dropdown-menu').length) {
+ element
+ .closest('li.dropdown')
+ .addClass('active')
+ .end()
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', true)
+ }
+
+ callback && callback()
+ }
+
+ $active.length && transition ?
+ $active
+ .one('bsTransitionEnd', next)
+ .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
+ next()
+
+ $active.removeClass('in')
+ }
+
+
+ // TAB PLUGIN DEFINITION
+ // =====================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.tab')
+
+ if (!data) $this.data('bs.tab', (data = new Tab(this)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.tab
+
+ $.fn.tab = Plugin
+ $.fn.tab.Constructor = Tab
+
+
+ // TAB NO CONFLICT
+ // ===============
+
+ $.fn.tab.noConflict = function () {
+ $.fn.tab = old
+ return this
+ }
+
+
+ // TAB DATA-API
+ // ============
+
+ var clickHandler = function (e) {
+ e.preventDefault()
+ Plugin.call($(this), 'show')
+ }
+
+ $(document)
+ .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
+ .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: affix.js v3.3.7
+ * http://getbootstrap.com/javascript/#affix
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // AFFIX CLASS DEFINITION
+ // ======================
+
+ var Affix = function (element, options) {
+ this.options = $.extend({}, Affix.DEFAULTS, options)
+
+ this.$target = $(this.options.target)
+ .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
+ .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
+
+ this.$element = $(element)
+ this.affixed = null
+ this.unpin = null
+ this.pinnedOffset = null
+
+ this.checkPosition()
+ }
+
+ Affix.VERSION = '3.3.7'
+
+ Affix.RESET = 'affix affix-top affix-bottom'
+
+ Affix.DEFAULTS = {
+ offset: 0,
+ target: window
+ }
+
+ Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
+ var scrollTop = this.$target.scrollTop()
+ var position = this.$element.offset()
+ var targetHeight = this.$target.height()
+
+ if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
+
+ if (this.affixed == 'bottom') {
+ if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
+ return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
+ }
+
+ var initializing = this.affixed == null
+ var colliderTop = initializing ? scrollTop : position.top
+ var colliderHeight = initializing ? targetHeight : height
+
+ if (offsetTop != null && scrollTop <= offsetTop) return 'top'
+ if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
+
+ return false
+ }
+
+ Affix.prototype.getPinnedOffset = function () {
+ if (this.pinnedOffset) return this.pinnedOffset
+ this.$element.removeClass(Affix.RESET).addClass('affix')
+ var scrollTop = this.$target.scrollTop()
+ var position = this.$element.offset()
+ return (this.pinnedOffset = position.top - scrollTop)
+ }
+
+ Affix.prototype.checkPositionWithEventLoop = function () {
+ setTimeout($.proxy(this.checkPosition, this), 1)
+ }
+
+ Affix.prototype.checkPosition = function () {
+ if (!this.$element.is(':visible')) return
+
+ var height = this.$element.height()
+ var offset = this.options.offset
+ var offsetTop = offset.top
+ var offsetBottom = offset.bottom
+ var scrollHeight = Math.max($(document).height(), $(document.body).height())
+
+ if (typeof offset != 'object') offsetBottom = offsetTop = offset
+ if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
+ if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
+
+ var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
+
+ if (this.affixed != affix) {
+ if (this.unpin != null) this.$element.css('top', '')
+
+ var affixType = 'affix' + (affix ? '-' + affix : '')
+ var e = $.Event(affixType + '.bs.affix')
+
+ this.$element.trigger(e)
+
+ if (e.isDefaultPrevented()) return
+
+ this.affixed = affix
+ this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
+
+ this.$element
+ .removeClass(Affix.RESET)
+ .addClass(affixType)
+ .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
+ }
+
+ if (affix == 'bottom') {
+ this.$element.offset({
+ top: scrollHeight - height - offsetBottom
+ })
+ }
+ }
+
+
+ // AFFIX PLUGIN DEFINITION
+ // =======================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.affix')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.affix
+
+ $.fn.affix = Plugin
+ $.fn.affix.Constructor = Affix
+
+
+ // AFFIX NO CONFLICT
+ // =================
+
+ $.fn.affix.noConflict = function () {
+ $.fn.affix = old
+ return this
+ }
+
+
+ // AFFIX DATA-API
+ // ==============
+
+ $(window).on('load', function () {
+ $('[data-spy="affix"]').each(function () {
+ var $spy = $(this)
+ var data = $spy.data()
+
+ data.offset = data.offset || {}
+
+ if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
+ if (data.offsetTop != null) data.offset.top = data.offsetTop
+
+ Plugin.call($spy, data)
+ })
+ })
+
+}(jQuery);
diff --git a/debian/missing-sources/two.js b/debian/missing-sources/two.js
new file mode 100644
index 000000000..859d3b418
--- /dev/null
+++ b/debian/missing-sources/two.js
@@ -0,0 +1,10244 @@
+/**
+ * two.js
+ * a two-dimensional drawing api meant for modern browsers. It is renderer
+ * agnostic enabling the same api for rendering in multiple contexts: webgl,
+ * canvas2d, and svg.
+ *
+ * Copyright (c) 2012 - 2017 jonobr1 / http://jonobr1.com
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+this.Two = (function(previousTwo) {
+
+ var root = typeof window != 'undefined' ? window : typeof global != 'undefined' ? global : null;
+ var toString = Object.prototype.toString;
+ var _ = {
+ // http://underscorejs.org/ • 1.8.3
+ _indexAmount: 0,
+ natural: {
+ slice: Array.prototype.slice,
+ indexOf: Array.prototype.indexOf,
+ keys: Object.keys,
+ bind: Function.prototype.bind,
+ create: Object.create
+ },
+ identity: function(value) {
+ return value;
+ },
+ isArguments: function(obj) {
+ return toString.call(obj) === '[object Arguments]';
+ },
+ isFunction: function(obj) {
+ return toString.call(obj) === '[object Function]';
+ },
+ isString: function(obj) {
+ return toString.call(obj) === '[object String]';
+ },
+ isNumber: function(obj) {
+ return toString.call(obj) === '[object Number]';
+ },
+ isDate: function(obj) {
+ return toString.call(obj) === '[object Date]';
+ },
+ isRegExp: function(obj) {
+ return toString.call(obj) === '[object RegExp]';
+ },
+ isError: function(obj) {
+ return toString.call(obj) === '[object Error]';
+ },
+ isFinite: function(obj) {
+ return isFinite(obj) && !isNaN(parseFloat(obj));
+ },
+ isNaN: function(obj) {
+ return _.isNumber(obj) && obj !== +obj;
+ },
+ isBoolean: function(obj) {
+ return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
+ },
+ isNull: function(obj) {
+ return obj === null;
+ },
+ isUndefined: function(obj) {
+ return obj === void 0;
+ },
+ isEmpty: function(obj) {
+ if (obj == null) return true;
+ if (isArrayLike && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
+ return _.keys(obj).length === 0;
+ },
+ isElement: function(obj) {
+ return !!(obj && obj.nodeType === 1);
+ },
+ isArray: Array.isArray || function(obj) {
+ return toString.call(obj) === '[object Array]';
+ },
+ isObject: function(obj) {
+ var type = typeof obj;
+ return type === 'function' || type === 'object' && !!obj;
+ },
+ toArray: function(obj) {
+ if (!obj) {
+ return [];
+ }
+ if (_.isArray(obj)) {
+ return slice.call(obj);
+ }
+ if (isArrayLike(obj)) {
+ return _.map(obj, _.identity);
+ }
+ return _.values(obj);
+ },
+ range: function(start, stop, step) {
+ if (stop == null) {
+ stop = start || 0;
+ start = 0;
+ }
+ step = step || 1;
+
+ var length = Math.max(Math.ceil((stop - start) / step), 0);
+ var range = Array(length);
+
+ for (var idx = 0; idx < length; idx++, start += step) {
+ range[idx] = start;
+ }
+
+ return range;
+ },
+ indexOf: function(list, item) {
+ if (!!_.natural.indexOf) {
+ return _.natural.indexOf.call(list, item);
+ }
+ for (var i = 0; i < list.length; i++) {
+ if (list[i] === item) {
+ return i;
+ }
+ }
+ return -1;
+ },
+ has: function(obj, key) {
+ return obj != null && hasOwnProperty.call(obj, key);
+ },
+ bind: function(func, ctx) {
+ var natural = _.natural.bind;
+ if (natural && func.bind === natural) {
+ return natural.apply(func, slice.call(arguments, 1));
+ }
+ var args = slice.call(arguments, 2);
+ return function() {
+ func.apply(ctx, args);
+ };
+ },
+ extend: function(base) {
+ var sources = slice.call(arguments, 1);
+ for (var i = 0; i < sources.length; i++) {
+ var obj = sources[i];
+ for (var k in obj) {
+ base[k] = obj[k];
+ }
+ }
+ return base;
+ },
+ defaults: function(base) {
+ var sources = slice.call(arguments, 1);
+ for (var i = 0; i < sources.length; i++) {
+ var obj = sources[i];
+ for (var k in obj) {
+ if (base[k] === void 0) {
+ base[k] = obj[k];
+ }
+ }
+ }
+ return base;
+ },
+ keys: function(obj) {
+ if (!_.isObject(obj)) {
+ return [];
+ }
+ if (_.natural.keys) {
+ return _.natural.keys(obj);
+ }
+ var keys = [];
+ for (var k in obj) {
+ if (_.has(obj, k)) {
+ keys.push(k);
+ }
+ }
+ return keys;
+ },
+ values: function(obj) {
+ var keys = _.keys(obj);
+ var values = [];
+ for (var i = 0; i < keys.length; i++) {
+ var k = keys[i];
+ values.push(obj[k]);
+ }
+ return values;
+ },
+ each: function(obj, iteratee, context) {
+ var ctx = context || this;
+ var keys = !isArrayLike(obj) && _.keys(obj);
+ var length = (keys || obj).length;
+ for (var i = 0; i < length; i++) {
+ var k = keys ? keys[i] : i;
+ iteratee.call(ctx, obj[k], k, obj);
+ }
+ return obj;
+ },
+ map: function(obj, iteratee, context) {
+ var ctx = context || this;
+ var keys = !isArrayLike(obj) && _.keys(obj);
+ var length = (keys || obj).length;
+ var result = [];
+ for (var i = 0; i < length; i++) {
+ var k = keys ? keys[i] : i;
+ result[i] = iteratee.call(ctx, obj[k], k, obj);
+ }
+ return result;
+ },
+ once: function(func) {
+ var init = false;
+ return function() {
+ if (!!init) {
+ return func;
+ }
+ init = true;
+ return func.apply(this, arguments);
+ }
+ },
+ after: function(times, func) {
+ return function() {
+ while (--times < 1) {
+ return func.apply(this, arguments);
+ }
+ }
+ },
+ uniqueId: function(prefix) {
+ var id = ++_._indexAmount + '';
+ return prefix ? prefix + id : id;
+ }
+ };
+
+ /**
+ * Constants
+ */
+
+ var sin = Math.sin,
+ cos = Math.cos,
+ atan2 = Math.atan2,
+ sqrt = Math.sqrt,
+ round = Math.round,
+ abs = Math.abs,
+ PI = Math.PI,
+ TWO_PI = PI * 2,
+ HALF_PI = PI / 2,
+ pow = Math.pow,
+ min = Math.min,
+ max = Math.max;
+
+ /**
+ * Localized variables
+ */
+
+ var count = 0;
+ var slice = _.natural.slice;
+ var perf = ((root.performance && root.performance.now) ? root.performance : Date);
+ var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
+ var getLength = function(obj) {
+ return obj == null ? void 0 : obj['length'];
+ };
+ var isArrayLike = function(collection) {
+ var length = getLength(collection);
+ return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
+ };
+
+ /**
+ * Cross browser dom events.
+ */
+ var dom = {
+
+ temp: (root.document ? root.document.createElement('div') : {}),
+
+ hasEventListeners: _.isFunction(root.addEventListener),
+
+ bind: function(elem, event, func, bool) {
+ if (this.hasEventListeners) {
+ elem.addEventListener(event, func, !!bool);
+ } else {
+ elem.attachEvent('on' + event, func);
+ }
+ return dom;
+ },
+
+ unbind: function(elem, event, func, bool) {
+ if (dom.hasEventListeners) {
+ elem.removeEventListeners(event, func, !!bool);
+ } else {
+ elem.detachEvent('on' + event, func);
+ }
+ return dom;
+ },
+
+ getRequestAnimationFrame: function() {
+
+ var lastTime = 0;
+ var vendors = ['ms', 'moz', 'webkit', 'o'];
+ var request = root.requestAnimationFrame, cancel;
+
+ if(!request) {
+ for (var i = 0; i < vendors.length; i++) {
+ request = root[vendors[i] + 'RequestAnimationFrame'] || request;
+ cancel = root[vendors[i] + 'CancelAnimationFrame']
+ || root[vendors[i] + 'CancelRequestAnimationFrame'] || cancel;
+ }
+
+ request = request || function(callback, element) {
+ var currTime = new Date().getTime();
+ var timeToCall = Math.max(0, 16 - (currTime - lastTime));
+ var id = root.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall);
+ lastTime = currTime + timeToCall;
+ return id;
+ };
+ // cancel = cancel || function(id) {
+ // clearTimeout(id);
+ // };
+ }
+
+ request.init = _.once(loop);
+
+ return request;
+
+ }
+
+ };
+
+ /**
+ * @class
+ */
+ var Two = root.Two = function(options) {
+
+ // Determine what Renderer to use and setup a scene.
+
+ var params = _.defaults(options || {}, {
+ fullscreen: false,
+ width: 640,
+ height: 480,
+ type: Two.Types.svg,
+ autostart: false
+ });
+
+ _.each(params, function(v, k) {
+ if (k === 'fullscreen' || k === 'autostart') {
+ return;
+ }
+ this[k] = v;
+ }, this);
+
+ // Specified domElement overrides type declaration only if the element does not support declared renderer type.
+ if (_.isElement(params.domElement)) {
+ var tagName = params.domElement.tagName.toLowerCase();
+ // TODO: Reconsider this if statement's logic.
+ if (!/^(CanvasRenderer-canvas|WebGLRenderer-canvas|SVGRenderer-svg)$/.test(this.type+'-'+tagName)) {
+ this.type = Two.Types[tagName];
+ }
+ }
+
+ this.renderer = new Two[this.type](this);
+ Two.Utils.setPlaying.call(this, params.autostart);
+ this.frameCount = 0;
+
+ if (params.fullscreen) {
+
+ var fitted = _.bind(fitToWindow, this);
+ _.extend(document.body.style, {
+ overflow: 'hidden',
+ margin: 0,
+ padding: 0,
+ top: 0,
+ left: 0,
+ right: 0,
+ bottom: 0,
+ position: 'fixed'
+ });
+ _.extend(this.renderer.domElement.style, {
+ display: 'block',
+ top: 0,
+ left: 0,
+ right: 0,
+ bottom: 0,
+ position: 'fixed'
+ });
+ dom.bind(root, 'resize', fitted);
+ fitted();
+
+
+ } else if (!_.isElement(params.domElement)) {
+
+ this.renderer.setSize(params.width, params.height, this.ratio);
+ this.width = params.width;
+ this.height = params.height;
+
+ }
+
+ this.scene = this.renderer.scene;
+
+ Two.Instances.push(this);
+ raf.init();
+
+ };
+
+ _.extend(Two, {
+
+ /**
+ * Access to root in other files.
+ */
+
+ root: root,
+
+ /**
+ * Primitive
+ */
+
+ Array: root.Float32Array || Array,
+
+ Types: {
+ webgl: 'WebGLRenderer',
+ svg: 'SVGRenderer',
+ canvas: 'CanvasRenderer'
+ },
+
+ Version: 'v0.7.0',
+
+ Identifier: 'two_',
+
+ Properties: {
+ hierarchy: 'hierarchy',
+ demotion: 'demotion'
+ },
+
+ Events: {
+ play: 'play',
+ pause: 'pause',
+ update: 'update',
+ render: 'render',
+ resize: 'resize',
+ change: 'change',
+ remove: 'remove',
+ insert: 'insert',
+ order: 'order',
+ load: 'load'
+ },
+
+ Commands: {
+ move: 'M',
+ line: 'L',
+ curve: 'C',
+ close: 'Z'
+ },
+
+ Resolution: 8,
+
+ Instances: [],
+
+ noConflict: function() {
+ root.Two = previousTwo;
+ return this;
+ },
+
+ uniqueId: function() {
+ var id = count;
+ count++;
+ return id;
+ },
+
+ Utils: _.extend(_, {
+
+ performance: perf,
+
+ defineProperty: function(property) {
+
+ var object = this;
+ var secret = '_' + property;
+ var flag = '_flag' + property.charAt(0).toUpperCase() + property.slice(1);
+
+ Object.defineProperty(object, property, {
+ enumerable: true,
+ get: function() {
+ return this[secret];
+ },
+ set: function(v) {
+ this[secret] = v;
+ this[flag] = true;
+ }
+ });
+
+ },
+
+ /**
+ * Release an arbitrary class' events from the two.js corpus and recurse
+ * through its children and or vertices.
+ */
+ release: function(obj) {
+
+ if (!_.isObject(obj)) {
+ return;
+ }
+
+ if (_.isFunction(obj.unbind)) {
+ obj.unbind();
+ }
+
+ if (obj.vertices) {
+ if (_.isFunction(obj.vertices.unbind)) {
+ obj.vertices.unbind();
+ }
+ _.each(obj.vertices, function(v) {
+ if (_.isFunction(v.unbind)) {
+ v.unbind();
+ }
+ });
+ }
+
+ if (obj.children) {
+ _.each(obj.children, function(obj) {
+ Two.Utils.release(obj);
+ });
+ }
+
+ },
+
+ xhr: function(path, callback) {
+
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', path);
+
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === 4 && xhr.status === 200) {
+ callback(xhr.responseText);
+ }
+ };
+
+ xhr.send();
+ return xhr;
+
+ },
+
+ Curve: {
+
+ CollinearityEpsilon: pow(10, -30),
+
+ RecursionLimit: 16,
+
+ CuspLimit: 0,
+
+ Tolerance: {
+ distance: 0.25,
+ angle: 0,
+ epsilon: 0.01
+ },
+
+ // Lookup tables for abscissas and weights with values for n = 2 .. 16.
+ // As values are symmetric, only store half of them and adapt algorithm
+ // to factor in symmetry.
+ abscissas: [
+ [ 0.5773502691896257645091488],
+ [0,0.7745966692414833770358531],
+ [ 0.3399810435848562648026658,0.8611363115940525752239465],
+ [0,0.5384693101056830910363144,0.9061798459386639927976269],
+ [ 0.2386191860831969086305017,0.6612093864662645136613996,0.9324695142031520278123016],
+ [0,0.4058451513773971669066064,0.7415311855993944398638648,0.9491079123427585245261897],
+ [ 0.1834346424956498049394761,0.5255324099163289858177390,0.7966664774136267395915539,0.9602898564975362316835609],
+ [0,0.3242534234038089290385380,0.6133714327005903973087020,0.8360311073266357942994298,0.9681602395076260898355762],
+ [ 0.1488743389816312108848260,0.4333953941292471907992659,0.6794095682990244062343274,0.8650633666889845107320967,0.9739065285171717200779640],
+ [0,0.2695431559523449723315320,0.5190961292068118159257257,0.7301520055740493240934163,0.8870625997680952990751578,0.9782286581460569928039380],
+ [ 0.1252334085114689154724414,0.3678314989981801937526915,0.5873179542866174472967024,0.7699026741943046870368938,0.9041172563704748566784659,0.9815606342467192506905491],
+ [0,0.2304583159551347940655281,0.4484927510364468528779129,0.6423493394403402206439846,0.8015780907333099127942065,0.9175983992229779652065478,0.9841830547185881494728294],
+ [ 0.1080549487073436620662447,0.3191123689278897604356718,0.5152486363581540919652907,0.6872929048116854701480198,0.8272013150697649931897947,0.9284348836635735173363911,0.9862838086968123388415973],
+ [0,0.2011940939974345223006283,0.3941513470775633698972074,0.5709721726085388475372267,0.7244177313601700474161861,0.8482065834104272162006483,0.9372733924007059043077589,0.9879925180204854284895657],
+ [ 0.0950125098376374401853193,0.2816035507792589132304605,0.4580167776572273863424194,0.6178762444026437484466718,0.7554044083550030338951012,0.8656312023878317438804679,0.9445750230732325760779884,0.9894009349916499325961542]
+ ],
+
+ weights: [
+ [1],
+ [0.8888888888888888888888889,0.5555555555555555555555556],
+ [0.6521451548625461426269361,0.3478548451374538573730639],
+ [0.5688888888888888888888889,0.4786286704993664680412915,0.2369268850561890875142640],
+ [0.4679139345726910473898703,0.3607615730481386075698335,0.1713244923791703450402961],
+ [0.4179591836734693877551020,0.3818300505051189449503698,0.2797053914892766679014678,0.1294849661688696932706114],
+ [0.3626837833783619829651504,0.3137066458778872873379622,0.2223810344533744705443560,0.1012285362903762591525314],
+ [0.3302393550012597631645251,0.3123470770400028400686304,0.2606106964029354623187429,0.1806481606948574040584720,0.0812743883615744119718922],
+ [0.2955242247147528701738930,0.2692667193099963550912269,0.2190863625159820439955349,0.1494513491505805931457763,0.0666713443086881375935688],
+ [0.2729250867779006307144835,0.2628045445102466621806889,0.2331937645919904799185237,0.1862902109277342514260976,0.1255803694649046246346943,0.0556685671161736664827537],
+ [0.2491470458134027850005624,0.2334925365383548087608499,0.2031674267230659217490645,0.1600783285433462263346525,0.1069393259953184309602547,0.0471753363865118271946160],
+ [0.2325515532308739101945895,0.2262831802628972384120902,0.2078160475368885023125232,0.1781459807619457382800467,0.1388735102197872384636018,0.0921214998377284479144218,0.0404840047653158795200216],
+ [0.2152638534631577901958764,0.2051984637212956039659241,0.1855383974779378137417166,0.1572031671581935345696019,0.1215185706879031846894148,0.0801580871597602098056333,0.0351194603317518630318329],
+ [0.2025782419255612728806202,0.1984314853271115764561183,0.1861610000155622110268006,0.1662692058169939335532009,0.1395706779261543144478048,0.1071592204671719350118695,0.0703660474881081247092674,0.0307532419961172683546284],
+ [0.1894506104550684962853967,0.1826034150449235888667637,0.1691565193950025381893121,0.1495959888165767320815017,0.1246289712555338720524763,0.0951585116824927848099251,0.0622535239386478928628438,0.0271524594117540948517806]
+ ]
+
+ },
+
+ /**
+ * Account for high dpi rendering.
+ * http://www.html5rocks.com/en/tutorials/canvas/hidpi/
+ */
+
+ devicePixelRatio: root.devicePixelRatio || 1,
+
+ getBackingStoreRatio: function(ctx) {
+ return ctx.webkitBackingStorePixelRatio ||
+ ctx.mozBackingStorePixelRatio ||
+ ctx.msBackingStorePixelRatio ||
+ ctx.oBackingStorePixelRatio ||
+ ctx.backingStorePixelRatio || 1;
+ },
+
+ getRatio: function(ctx) {
+ return Two.Utils.devicePixelRatio / getBackingStoreRatio(ctx);
+ },
+
+ /**
+ * Properly defer play calling until after all objects
+ * have been updated with their newest styles.
+ */
+ setPlaying: function(b) {
+
+ this.playing = !!b;
+ return this;
+
+ },
+
+ /**
+ * Return the computed matrix of a nested object.
+ * TODO: Optimize traversal.
+ */
+ getComputedMatrix: function(object, matrix) {
+
+ matrix = (matrix && matrix.identity()) || new Two.Matrix();
+ var parent = object, matrices = [];
+
+ while (parent && parent._matrix) {
+ matrices.push(parent._matrix);
+ parent = parent.parent;
+ }
+
+ matrices.reverse();
+
+ _.each(matrices, function(m) {
+
+ var e = m.elements;
+ matrix.multiply(
+ e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7], e[8], e[9]);
+
+ });
+
+ return matrix;
+
+ },
+
+ deltaTransformPoint: function(matrix, x, y) {
+
+ var dx = x * matrix.a + y * matrix.c + 0;
+ var dy = x * matrix.b + y * matrix.d + 0;
+
+ return new Two.Vector(dx, dy);
+
+ },
+
+ /**
+ * https://gist.github.com/2052247
+ */
+ decomposeMatrix: function(matrix) {
+
+ // calculate delta transform point
+ var px = Two.Utils.deltaTransformPoint(matrix, 0, 1);
+ var py = Two.Utils.deltaTransformPoint(matrix, 1, 0);
+
+ // calculate skew
+ var skewX = ((180 / Math.PI) * Math.atan2(px.y, px.x) - 90);
+ var skewY = ((180 / Math.PI) * Math.atan2(py.y, py.x));
+
+ return {
+ translateX: matrix.e,
+ translateY: matrix.f,
+ scaleX: Math.sqrt(matrix.a * matrix.a + matrix.b * matrix.b),
+ scaleY: Math.sqrt(matrix.c * matrix.c + matrix.d * matrix.d),
+ skewX: skewX,
+ skewY: skewY,
+ rotation: skewX // rotation is the same as skew x
+ };
+
+ },
+
+ /**
+ * Walk through item properties and pick the ones of interest.
+ * Will try to resolve styles applied via CSS
+ *
+ * TODO: Reverse calculate `Two.Gradient`s for fill / stroke
+ * of any given path.
+ */
+ applySvgAttributes: function(node, elem) {
+
+ var attributes = {}, styles = {}, i, key, value, attr;
+
+ // Not available in non browser environments
+ if (getComputedStyle) {
+ // Convert CSSStyleDeclaration to a normal object
+ var computedStyles = getComputedStyle(node);
+ i = computedStyles.length;
+
+ while (i--) {
+ key = computedStyles[i];
+ value = computedStyles[key];
+ // Gecko returns undefined for unset properties
+ // Webkit returns the default value
+ if (value !== undefined) {
+ styles[key] = value;
+ }
+ }
+ }
+
+ // Convert NodeMap to a normal object
+ i = node.attributes.length;
+ while (i--) {
+ attr = node.attributes[i];
+ attributes[attr.nodeName] = attr.value;
+ }
+
+ // Getting the correct opacity is a bit tricky, since SVG path elements don't
+ // support opacity as an attribute, but you can apply it via CSS.
+ // So we take the opacity and set (stroke/fill)-opacity to the same value.
+ if (!_.isUndefined(styles.opacity)) {
+ styles['stroke-opacity'] = styles.opacity;
+ styles['fill-opacity'] = styles.opacity;
+ }
+
+ // Merge attributes and applied styles (attributes take precedence)
+ _.extend(styles, attributes);
+
+ // Similarly visibility is influenced by the value of both display and visibility.
+ // Calculate a unified value here which defaults to `true`.
+ styles.visible = !(_.isUndefined(styles.display) && styles.display === 'none')
+ || (_.isUndefined(styles.visibility) && styles.visibility === 'hidden');
+
+ // Now iterate the whole thing
+ for (key in styles) {
+ value = styles[key];
+
+ switch (key) {
+ case 'transform':
+ // TODO: Check this out https://github.com/paperjs/paper.js/blob/master/src/svg/SVGImport.js#L313
+ if (value === 'none') break;
+ var m = node.getCTM ? node.getCTM() : null;
+
+ // Might happen when transform string is empty or not valid.
+ if (m === null) break;
+
+ // // Option 1: edit the underlying matrix and don't force an auto calc.
+ // var m = node.getCTM();
+ // elem._matrix.manual = true;
+ // elem._matrix.set(m.a, m.b, m.c, m.d, m.e, m.f);
+
+ // Option 2: Decompose and infer Two.js related properties.
+ var transforms = Two.Utils.decomposeMatrix(node.getCTM());
+
+ elem.translation.set(transforms.translateX, transforms.translateY);
+ elem.rotation = transforms.rotation;
+ // Warning: Two.js elements only support uniform scalars...
+ elem.scale = transforms.scaleX;
+
+ var x = parseFloat((styles.x + '').replace('px'));
+ var y = parseFloat((styles.y + '').replace('px'));
+
+ // Override based on attributes.
+ if (x) {
+ elem.translation.x = x;
+ }
+
+ if (y) {
+ elem.translation.y = y;
+ }
+
+ break;
+ case 'visible':
+ elem.visible = value;
+ break;
+ case 'stroke-linecap':
+ elem.cap = value;
+ break;
+ case 'stroke-linejoin':
+ elem.join = value;
+ break;
+ case 'stroke-miterlimit':
+ elem.miter = value;
+ break;
+ case 'stroke-width':
+ elem.linewidth = parseFloat(value);
+ break;
+ case 'stroke-opacity':
+ case 'fill-opacity':
+ case 'opacity':
+ elem.opacity = parseFloat(value);
+ break;
+ case 'fill':
+ case 'stroke':
+ if (/url\(\#.*\)/i.test(value)) {
+ elem[key] = this.getById(
+ value.replace(/url\(\#(.*)\)/i, '$1'));
+ } else {
+ elem[key] = (value === 'none') ? 'transparent' : value;
+ }
+ break;
+ case 'id':
+ elem.id = value;
+ break;
+ case 'class':
+ elem.classList = value.split(' ');
+ break;
+ }
+ }
+
+ return elem;
+
+ },
+
+ /**
+ * Read any number of SVG node types and create Two equivalents of them.
+ */
+ read: {
+
+ svg: function() {
+ return Two.Utils.read.g.apply(this, arguments);
+ },
+
+ g: function(node) {
+
+ var group = new Two.Group();
+
+ // Switched up order to inherit more specific styles
+ Two.Utils.applySvgAttributes.call(this, node, group);
+
+ for (var i = 0, l = node.childNodes.length; i < l; i++) {
+ var n = node.childNodes[i];
+ var tag = n.nodeName;
+ if (!tag) return;
+
+ var tagName = tag.replace(/svg\:/ig, '').toLowerCase();
+
+ if (tagName in Two.Utils.read) {
+ var o = Two.Utils.read[tagName].call(group, n);
+ group.add(o);
+ }
+ }
+
+ return group;
+
+ },
+
+ polygon: function(node, open) {
+
+ var points = node.getAttribute('points');
+
+ var verts = [];
+ points.replace(/(-?[\d\.?]+)[,|\s](-?[\d\.?]+)/g, function(match, p1, p2) {
+ verts.push(new Two.Anchor(parseFloat(p1), parseFloat(p2)));
+ });
+
+ var poly = new Two.Path(verts, !open).noStroke();
+ poly.fill = 'black';
+
+ return Two.Utils.applySvgAttributes.call(this, node, poly);
+
+ },
+
+ polyline: function(node) {
+ return Two.Utils.read.polygon.call(this, node, true);
+ },
+
+ path: function(node) {
+
+ var path = node.getAttribute('d');
+
+ // Create a Two.Path from the paths.
+
+ var coord = new Two.Anchor();
+ var control, coords;
+ var closed = false, relative = false;
+ var commands = path.match(/[a-df-z][^a-df-z]*/ig);
+ var last = commands.length - 1;
+
+ // Split up polybeziers
+
+ _.each(commands.slice(0), function(command, i) {
+
+ var type = command[0];
+ var lower = type.toLowerCase();
+ var items = command.slice(1).trim().split(/[\s,]+|(?=\s?[+\-])/);
+ var pre, post, result = [], bin;
+
+ if (i <= 0) {
+ commands = [];
+ }
+
+ switch (lower) {
+ case 'h':
+ case 'v':
+ if (items.length > 1) {
+ bin = 1;
+ }
+ break;
+ case 'm':
+ case 'l':
+ case 't':
+ if (items.length > 2) {
+ bin = 2;
+ }
+ break;
+ case 's':
+ case 'q':
+ if (items.length > 4) {
+ bin = 4;
+ }
+ break;
+ case 'c':
+ if (items.length > 6) {
+ bin = 6;
+ }
+ break;
+ case 'a':
+ // TODO: Handle Ellipses
+ break;
+ }
+
+ if (bin) {
+
+ for (var j = 0, l = items.length, times = 0; j < l; j+=bin) {
+
+ var ct = type;
+ if (times > 0) {
+
+ switch (type) {
+ case 'm':
+ ct = 'l';
+ break;
+ case 'M':
+ ct = 'L';
+ break;
+ }
+
+ }
+
+ result.push([ct].concat(items.slice(j, j + bin)).join(' '));
+ times++;
+
+ }
+
+ commands = Array.prototype.concat.apply(commands, result);
+
+ } else {
+
+ commands.push(command);
+
+ }
+
+ });
+
+ // Create the vertices for our Two.Path
+
+ var points = [];
+ _.each(commands, function(command, i) {
+
+ var result, x, y;
+ var type = command[0];
+ var lower = type.toLowerCase();
+
+ coords = command.slice(1).trim();
+ coords = coords.replace(/(-?\d+(?:\.\d*)?)[eE]([+\-]?\d+)/g, function(match, n1, n2) {
+ return parseFloat(n1) * pow(10, n2);
+ });
+ coords = coords.split(/[\s,]+|(?=\s?[+\-])/);
+ relative = type === lower;
+
+ var x1, y1, x2, y2, x3, y3, x4, y4, reflection;
+
+ switch (lower) {
+
+ case 'z':
+ if (i >= last) {
+ closed = true;
+ } else {
+ x = coord.x;
+ y = coord.y;
+ result = new Two.Anchor(
+ x, y,
+ undefined, undefined,
+ undefined, undefined,
+ Two.Commands.close
+ );
+ }
+ break;
+
+ case 'm':
+ case 'l':
+
+ x = parseFloat(coords[0]);
+ y = parseFloat(coords[1]);
+
+ result = new Two.Anchor(
+ x, y,
+ undefined, undefined,
+ undefined, undefined,
+ lower === 'm' ? Two.Commands.move : Two.Commands.line
+ );
+
+ if (relative) {
+ result.addSelf(coord);
+ }
+
+ // result.controls.left.copy(result);
+ // result.controls.right.copy(result);
+
+ coord = result;
+ break;
+
+ case 'h':
+ case 'v':
+
+ var a = lower === 'h' ? 'x' : 'y';
+ var b = a === 'x' ? 'y' : 'x';
+
+ result = new Two.Anchor(
+ undefined, undefined,
+ undefined, undefined,
+ undefined, undefined,
+ Two.Commands.line
+ );
+ result[a] = parseFloat(coords[0]);
+ result[b] = coord[b];
+
+ if (relative) {
+ result[a] += coord[a];
+ }
+
+ // result.controls.left.copy(result);
+ // result.controls.right.copy(result);
+
+ coord = result;
+ break;
+
+ case 'c':
+ case 's':
+
+ x1 = coord.x;
+ y1 = coord.y;
+
+ if (!control) {
+ control = new Two.Vector();//.copy(coord);
+ }
+
+ if (lower === 'c') {
+
+ x2 = parseFloat(coords[0]);
+ y2 = parseFloat(coords[1]);
+ x3 = parseFloat(coords[2]);
+ y3 = parseFloat(coords[3]);
+ x4 = parseFloat(coords[4]);
+ y4 = parseFloat(coords[5]);
+
+ } else {
+
+ // Calculate reflection control point for proper x2, y2
+ // inclusion.
+
+ reflection = getReflection(coord, control, relative);
+
+ x2 = reflection.x;
+ y2 = reflection.y;
+ x3 = parseFloat(coords[0]);
+ y3 = parseFloat(coords[1]);
+ x4 = parseFloat(coords[2]);
+ y4 = parseFloat(coords[3]);
+
+ }
+
+ if (relative) {
+ x2 += x1;
+ y2 += y1;
+ x3 += x1;
+ y3 += y1;
+ x4 += x1;
+ y4 += y1;
+ }
+
+ if (!_.isObject(coord.controls)) {
+ Two.Anchor.AppendCurveProperties(coord);
+ }
+
+ coord.controls.right.set(x2 - coord.x, y2 - coord.y);
+ result = new Two.Anchor(
+ x4, y4,
+ x3 - x4, y3 - y4,
+ undefined, undefined,
+ Two.Commands.curve
+ );
+
+ coord = result;
+ control = result.controls.left;
+
+ break;
+
+ case 't':
+ case 'q':
+
+ x1 = coord.x;
+ y1 = coord.y;
+
+ if (!control) {
+ control = new Two.Vector();//.copy(coord);
+ }
+
+ if (control.isZero()) {
+ x2 = x1;
+ y2 = y1;
+ } else {
+ x2 = control.x;
+ y1 = control.y;
+ }
+
+ if (lower === 'q') {
+
+ x3 = parseFloat(coords[0]);
+ y3 = parseFloat(coords[1]);
+ x4 = parseFloat(coords[1]);
+ y4 = parseFloat(coords[2]);
+
+ } else {
+
+ reflection = getReflection(coord, control, relative);
+
+ x3 = reflection.x;
+ y3 = reflection.y;
+ x4 = parseFloat(coords[0]);
+ y4 = parseFloat(coords[1]);
+
+ }
+
+ if (relative) {
+ x2 += x1;
+ y2 += y1;
+ x3 += x1;
+ y3 += y1;
+ x4 += x1;
+ y4 += y1;
+ }
+
+ if (!_.isObject(coord.controls)) {
+ Two.Anchor.AppendCurveProperties(coord);
+ }
+
+ coord.controls.right.set(x2 - coord.x, y2 - coord.y);
+ result = new Two.Anchor(
+ x4, y4,
+ x3 - x4, y3 - y4,
+ undefined, undefined,
+ Two.Commands.curve
+ );
+
+ coord = result;
+ control = result.controls.left;
+
+ break;
+
+ case 'a':
+
+ // throw new Two.Utils.Error('not yet able to interpret Elliptical Arcs.');
+ x1 = coord.x;
+ y1 = coord.y;
+
+ var rx = parseFloat(coords[0]);
+ var ry = parseFloat(coords[1]);
+ var xAxisRotation = parseFloat(coords[2]) * Math.PI / 180;
+ var largeArcFlag = parseFloat(coords[3]);
+ var sweepFlag = parseFloat(coords[4]);
+
+ x4 = parseFloat(coords[5]);
+ y4 = parseFloat(coords[6]);
+
+ if (relative) {
+ x4 += x1;
+ y4 += y1;
+ }
+
+ // http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter
+
+ // Calculate midpoint mx my
+ var mx = (x4 - x1) / 2;
+ var my = (y4 - y1) / 2;
+
+ // Calculate x1' y1' F.6.5.1
+ var _x = mx * Math.cos(xAxisRotation) + my * Math.sin(xAxisRotation);
+ var _y = - mx * Math.sin(xAxisRotation) + my * Math.cos(xAxisRotation);
+
+ var rx2 = rx * rx;
+ var ry2 = ry * ry;
+ var _x2 = _x * _x;
+ var _y2 = _y * _y;
+
+ // adjust radii
+ var l = _x2 / rx2 + _y2 / ry2;
+ if (l > 1) {
+ rx *= Math.sqrt(l);
+ ry *= Math.sqrt(l);
+ }
+
+ var amp = Math.sqrt((rx2 * ry2 - rx2 * _y2 - ry2 * _x2) / (rx2 * _y2 + ry2 * _x2));
+
+ if (_.isNaN(amp)) {
+ amp = 0;
+ } else if (largeArcFlag != sweepFlag && amp > 0) {
+ amp *= -1;
+ }
+
+ // Calculate cx' cy' F.6.5.2
+ var _cx = amp * rx * _y / ry;
+ var _cy = - amp * ry * _x / rx;
+
+ // Calculate cx cy F.6.5.3
+ var cx = _cx * Math.cos(xAxisRotation) - _cy * Math.sin(xAxisRotation) + (x1 + x4) / 2;
+ var cy = _cx * Math.sin(xAxisRotation) + _cy * Math.cos(xAxisRotation) + (y1 + y4) / 2;
+
+ // vector magnitude
+ var m = function(v) { return Math.sqrt(Math.pow(v[0], 2) + Math.pow(v[1], 2)); }
+ // ratio between two vectors
+ var r = function(u, v) { return (u[0] * v[0] + u[1] * v[1]) / (m(u) * m(v)) }
+ // angle between two vectors
+ var a = function(u, v) { return (u[0] * v[1] < u[1] * v[0] ? - 1 : 1) * Math.acos(r(u,v)); }
+
+ // Calculate theta1 and delta theta F.6.5.4 + F.6.5.5
+ var t1 = a([1, 0], [(_x - _cx) / rx, (_y - _cy) / ry]);
+ var u = [(_x - _cx) / rx, (_y - _cy) / ry];
+ var v = [( - _x - _cx) / rx, ( - _y - _cy) / ry];
+ var dt = a(u, v);
+
+ if (r(u, v) <= -1) dt = Math.PI;
+ if (r(u, v) >= 1) dt = 0;
+
+ // F.6.5.6
+ if (largeArcFlag) {
+ dt = mod(dt, Math.PI * 2);
+ }
+
+ if (sweepFlag && dt > 0) {
+ dt -= Math.PI * 2;
+ }
+
+ var length = Two.Resolution;
+
+ // Save a projection of our rotation and translation to apply
+ // to the set of points.
+ var projection = new Two.Matrix()
+ .translate(cx, cy)
+ .rotate(xAxisRotation);
+
+ // Create a resulting array of Two.Anchor's to export to the
+ // the path.
+ result = _.map(_.range(length), function(i) {
+ var pct = 1 - (i / (length - 1));
+ var theta = pct * dt + t1;
+ var x = rx * Math.cos(theta);
+ var y = ry * Math.sin(theta);
+ var projected = projection.multiply(x, y, 1);
+ return new Two.Anchor(projected.x, projected.y, false, false, false, false, Two.Commands.line);;
+ });
+
+ result.push(new Two.Anchor(x4, y4, false, false, false, false, Two.Commands.line));
+
+ coord = result[result.length - 1];
+ control = coord.controls.left;
+
+ break;
+
+ }
+
+ if (result) {
+ if (_.isArray(result)) {
+ points = points.concat(result);
+ } else {
+ points.push(result);
+ }
+ }
+
+ });
+
+ if (points.length <= 1) {
+ return;
+ }
+
+ var path = new Two.Path(points, closed, undefined, true).noStroke();
+ path.fill = 'black';
+
+ var rect = path.getBoundingClientRect(true);
+
+ // Center objects to stay consistent
+ // with the rest of the Two.js API.
+ rect.centroid = {
+ x: rect.left + rect.width / 2,
+ y: rect.top + rect.height / 2
+ };
+
+ _.each(path.vertices, function(v) {
+ v.subSelf(rect.centroid);
+ });
+
+ path.translation.addSelf(rect.centroid);
+
+ return Two.Utils.applySvgAttributes.call(this, node, path);
+
+ },
+
+ circle: function(node) {
+
+ var x = parseFloat(node.getAttribute('cx'));
+ var y = parseFloat(node.getAttribute('cy'));
+ var r = parseFloat(node.getAttribute('r'));
+
+ var circle = new Two.Circle(x, y, r).noStroke();
+ circle.fill = 'black';
+
+ return Two.Utils.applySvgAttributes.call(this, node, circle);
+
+ },
+
+ ellipse: function(node) {
+
+ var x = parseFloat(node.getAttribute('cx'));
+ var y = parseFloat(node.getAttribute('cy'));
+ var width = parseFloat(node.getAttribute('rx'));
+ var height = parseFloat(node.getAttribute('ry'));
+
+ var ellipse = new Two.Ellipse(x, y, width, height).noStroke();
+ ellipse.fill = 'black';
+
+ return Two.Utils.applySvgAttributes.call(this, node, ellipse);
+
+ },
+
+ rect: function(node) {
+
+ var x = parseFloat(node.getAttribute('x')) || 0;
+ var y = parseFloat(node.getAttribute('y')) || 0;
+ var width = parseFloat(node.getAttribute('width'));
+ var height = parseFloat(node.getAttribute('height'));
+
+ var w2 = width / 2;
+ var h2 = height / 2;
+
+ var rect = new Two.Rectangle(x + w2, y + h2, width, height)
+ .noStroke();
+ rect.fill = 'black';
+
+ return Two.Utils.applySvgAttributes.call(this, node, rect);
+
+ },
+
+ line: function(node) {
+
+ var x1 = parseFloat(node.getAttribute('x1'));
+ var y1 = parseFloat(node.getAttribute('y1'));
+ var x2 = parseFloat(node.getAttribute('x2'));
+ var y2 = parseFloat(node.getAttribute('y2'));
+
+ var line = new Two.Line(x1, y1, x2, y2).noFill();
+
+ return Two.Utils.applySvgAttributes.call(this, node, line);
+
+ },
+
+ lineargradient: function(node) {
+
+ var x1 = parseFloat(node.getAttribute('x1'));
+ var y1 = parseFloat(node.getAttribute('y1'));
+ var x2 = parseFloat(node.getAttribute('x2'));
+ var y2 = parseFloat(node.getAttribute('y2'));
+
+ var ox = (x2 + x1) / 2;
+ var oy = (y2 + y1) / 2;
+
+ var stops = [];
+ for (var i = 0; i < node.children.length; i++) {
+
+ var child = node.children[i];
+
+ var offset = parseFloat(child.getAttribute('offset'));
+ var color = child.getAttribute('stop-color');
+ var opacity = child.getAttribute('stop-opacity');
+ var style = child.getAttribute('style');
+
+ if (_.isNull(color)) {
+ var matches = style ? style.match(/stop\-color\:\s?([\#a-fA-F0-9]*)/) : false;
+ color = matches && matches.length > 1 ? matches[1] : undefined;
+ }
+
+ if (_.isNull(opacity)) {
+ var matches = style ? style.match(/stop\-opacity\:\s?([0-9\.\-]*)/) : false;
+ opacity = matches && matches.length > 1 ? parseFloat(matches[1]) : 1;
+ }
+
+ stops.push(new Two.Gradient.Stop(offset, color, opacity));
+
+ }
+
+ var gradient = new Two.LinearGradient(x1 - ox, y1 - oy, x2 - ox,
+ y2 - oy, stops);
+
+ return Two.Utils.applySvgAttributes.call(this, node, gradient);
+
+ },
+
+ radialgradient: function(node) {
+
+ var cx = parseFloat(node.getAttribute('cx')) || 0;
+ var cy = parseFloat(node.getAttribute('cy')) || 0;
+ var r = parseFloat(node.getAttribute('r'));
+
+ var fx = parseFloat(node.getAttribute('fx'));
+ var fy = parseFloat(node.getAttribute('fy'));
+
+ if (_.isNaN(fx)) {
+ fx = cx;
+ }
+
+ if (_.isNaN(fy)) {
+ fy = cy;
+ }
+
+ var ox = Math.abs(cx + fx) / 2;
+ var oy = Math.abs(cy + fy) / 2;
+
+ var stops = [];
+ for (var i = 0; i < node.children.length; i++) {
+
+ var child = node.children[i];
+
+ var offset = parseFloat(child.getAttribute('offset'));
+ var color = child.getAttribute('stop-color');
+ var opacity = child.getAttribute('stop-opacity');
+ var style = child.getAttribute('style');
+
+ if (_.isNull(color)) {
+ var matches = style ? style.match(/stop\-color\:\s?([\#a-fA-F0-9]*)/) : false;
+ color = matches && matches.length > 1 ? matches[1] : undefined;
+ }
+
+ if (_.isNull(opacity)) {
+ var matches = style ? style.match(/stop\-opacity\:\s?([0-9\.\-]*)/) : false;
+ opacity = matches && matches.length > 1 ? parseFloat(matches[1]) : 1;
+ }
+
+ stops.push(new Two.Gradient.Stop(offset, color, opacity));
+
+ }
+
+ var gradient = new Two.RadialGradient(cx - ox, cy - oy, r,
+ stops, fx - ox, fy - oy);
+
+ return Two.Utils.applySvgAttributes.call(this, node, gradient);
+
+ }
+
+ },
+
+ /**
+ * Given 2 points (a, b) and corresponding control point for each
+ * return an array of points that represent points plotted along
+ * the curve. Number points determined by limit.
+ */
+ subdivide: function(x1, y1, x2, y2, x3, y3, x4, y4, limit) {
+
+ limit = limit || Two.Utils.Curve.RecursionLimit;
+ var amount = limit + 1;
+
+ // TODO: Issue 73
+ // Don't recurse if the end points are identical
+ if (x1 === x4 && y1 === y4) {
+ return [new Two.Anchor(x4, y4)];
+ }
+
+ return _.map(_.range(0, amount), function(i) {
+
+ var t = i / amount;
+ var x = getPointOnCubicBezier(t, x1, x2, x3, x4);
+ var y = getPointOnCubicBezier(t, y1, y2, y3, y4);
+
+ return new Two.Anchor(x, y);
+
+ });
+
+ },
+
+ getPointOnCubicBezier: function(t, a, b, c, d) {
+ var k = 1 - t;
+ return (k * k * k * a) + (3 * k * k * t * b) + (3 * k * t * t * c) +
+ (t * t * t * d);
+ },
+
+ /**
+ * Given 2 points (a, b) and corresponding control point for each
+ * return a float that represents the length of the curve using
+ * Gauss-Legendre algorithm. Limit iterations of calculation by `limit`.
+ */
+ getCurveLength: function(x1, y1, x2, y2, x3, y3, x4, y4, limit) {
+
+ // TODO: Better / fuzzier equality check
+ // Linear calculation
+ if (x1 === x2 && y1 === y2 && x3 === x4 && y3 === y4) {
+ var dx = x4 - x1;
+ var dy = y4 - y1;
+ return sqrt(dx * dx + dy * dy);
+ }
+
+ // Calculate the coefficients of a Bezier derivative.
+ var ax = 9 * (x2 - x3) + 3 * (x4 - x1),
+ bx = 6 * (x1 + x3) - 12 * x2,
+ cx = 3 * (x2 - x1),
+
+ ay = 9 * (y2 - y3) + 3 * (y4 - y1),
+ by = 6 * (y1 + y3) - 12 * y2,
+ cy = 3 * (y2 - y1);
+
+ var integrand = function(t) {
+ // Calculate quadratic equations of derivatives for x and y
+ var dx = (ax * t + bx) * t + cx,
+ dy = (ay * t + by) * t + cy;
+ return sqrt(dx * dx + dy * dy);
+ };
+
+ return integrate(
+ integrand, 0, 1, limit || Two.Utils.Curve.RecursionLimit
+ );
+
+ },
+
+ /**
+ * Integration for `getCurveLength` calculations. Referenced from
+ * Paper.js: https://github.com/paperjs/paper.js/blob/master/src/util/Numerical.js#L101
+ */
+ integrate: function(f, a, b, n) {
+ var x = Two.Utils.Curve.abscissas[n - 2],
+ w = Two.Utils.Curve.weights[n - 2],
+ A = 0.5 * (b - a),
+ B = A + a,
+ i = 0,
+ m = (n + 1) >> 1,
+ sum = n & 1 ? w[i++] * f(B) : 0; // Handle odd n
+ while (i < m) {
+ var Ax = A * x[i];
+ sum += w[i++] * (f(B + Ax) + f(B - Ax));
+ }
+ return A * sum;
+ },
+
+ /**
+ * Creates a set of points that have u, v values for anchor positions
+ */
+ getCurveFromPoints: function(points, closed) {
+
+ var l = points.length, last = l - 1;
+
+ for (var i = 0; i < l; i++) {
+
+ var point = points[i];
+
+ if (!_.isObject(point.controls)) {
+ Two.Anchor.AppendCurveProperties(point);
+ }
+
+ var prev = closed ? mod(i - 1, l) : max(i - 1, 0);
+ var next = closed ? mod(i + 1, l) : min(i + 1, last);
+
+ var a = points[prev];
+ var b = point;
+ var c = points[next];
+ getControlPoints(a, b, c);
+
+ b._command = i === 0 ? Two.Commands.move : Two.Commands.curve;
+
+ b.controls.left.x = _.isNumber(b.controls.left.x) ? b.controls.left.x : b.x;
+ b.controls.left.y = _.isNumber(b.controls.left.y) ? b.controls.left.y : b.y;
+
+ b.controls.right.x = _.isNumber(b.controls.right.x) ? b.controls.right.x : b.x;
+ b.controls.right.y = _.isNumber(b.controls.right.y) ? b.controls.right.y : b.y;
+
+ }
+
+ },
+
+ /**
+ * Given three coordinates return the control points for the middle, b,
+ * vertex.
+ */
+ getControlPoints: function(a, b, c) {
+
+ var a1 = angleBetween(a, b);
+ var a2 = angleBetween(c, b);
+
+ var d1 = distanceBetween(a, b);
+ var d2 = distanceBetween(c, b);
+
+ var mid = (a1 + a2) / 2;
+
+ // So we know which angle corresponds to which side.
+
+ b.u = _.isObject(b.controls.left) ? b.controls.left : new Two.Vector(0, 0);
+ b.v = _.isObject(b.controls.right) ? b.controls.right : new Two.Vector(0, 0);
+
+ // TODO: Issue 73
+ if (d1 < 0.0001 || d2 < 0.0001) {
+ if (!b._relative) {
+ b.controls.left.copy(b);
+ b.controls.right.copy(b);
+ }
+ return b;
+ }
+
+ d1 *= 0.33; // Why 0.33?
+ d2 *= 0.33;
+
+ if (a2 < a1) {
+ mid += HALF_PI;
+ } else {
+ mid -= HALF_PI;
+ }
+
+ b.controls.left.x = cos(mid) * d1;
+ b.controls.left.y = sin(mid) * d1;
+
+ mid -= PI;
+
+ b.controls.right.x = cos(mid) * d2;
+ b.controls.right.y = sin(mid) * d2;
+
+ if (!b._relative) {
+ b.controls.left.x += b.x;
+ b.controls.left.y += b.y;
+ b.controls.right.x += b.x;
+ b.controls.right.y += b.y;
+ }
+
+ return b;
+
+ },
+
+ /**
+ * Get the reflection of a point "b" about point "a". Where "a" is in
+ * absolute space and "b" is relative to "a".
+ *
+ * http://www.w3.org/TR/SVG11/implnote.html#PathElementImplementationNotes
+ */
+ getReflection: function(a, b, relative) {
+
+ return new Two.Vector(
+ 2 * a.x - (b.x + a.x) - (relative ? a.x : 0),
+ 2 * a.y - (b.y + a.y) - (relative ? a.y : 0)
+ );
+
+ },
+
+ getAnchorsFromArcData: function(center, xAxisRotation, rx, ry, ts, td, ccw) {
+
+ var matrix = new Two.Matrix()
+ .translate(center.x, center.y)
+ .rotate(xAxisRotation);
+
+ var l = Two.Resolution;
+
+ return _.map(_.range(l), function(i) {
+
+ var pct = (i + 1) / l;
+ if (!!ccw) {
+ pct = 1 - pct;
+ }
+
+ var theta = pct * td + ts;
+ var x = rx * Math.cos(theta);
+ var y = ry * Math.sin(theta);
+
+ // x += center.x;
+ // y += center.y;
+
+ var anchor = new Two.Anchor(x, y);
+ Two.Anchor.AppendCurveProperties(anchor);
+ anchor.command = Two.Commands.line;
+
+ // TODO: Calculate control points here...
+
+ return anchor;
+
+ });
+
+ },
+
+ ratioBetween: function(A, B) {
+
+ return (A.x * B.x + A.y * B.y) / (A.length() * B.length());
+
+ },
+
+ angleBetween: function(A, B) {
+
+ var dx, dy;
+
+ if (arguments.length >= 4) {
+
+ dx = arguments[0] - arguments[2];
+ dy = arguments[1] - arguments[3];
+
+ return atan2(dy, dx);
+
+ }
+
+ dx = A.x - B.x;
+ dy = A.y - B.y;
+
+ return atan2(dy, dx);
+
+ },
+
+ distanceBetweenSquared: function(p1, p2) {
+
+ var dx = p1.x - p2.x;
+ var dy = p1.y - p2.y;
+
+ return dx * dx + dy * dy;
+
+ },
+
+ distanceBetween: function(p1, p2) {
+
+ return sqrt(distanceBetweenSquared(p1, p2));
+
+ },
+
+ lerp: function(a, b, t) {
+ return t * (b - a) + a;
+ },
+
+ // A pretty fast toFixed(3) alternative
+ // See http://jsperf.com/parsefloat-tofixed-vs-math-round/18
+ toFixed: function(v) {
+ return Math.floor(v * 1000) / 1000;
+ },
+
+ mod: function(v, l) {
+
+ while (v < 0) {
+ v += l;
+ }
+
+ return v % l;
+
+ },
+
+ /**
+ * Array like collection that triggers inserted and removed events
+ * removed : pop / shift / splice
+ * inserted : push / unshift / splice (with > 2 arguments)
+ */
+ Collection: function() {
+
+ Array.call(this);
+
+ if (arguments.length > 1) {
+ Array.prototype.push.apply(this, arguments);
+ } else if (arguments[0] && Array.isArray(arguments[0])) {
+ Array.prototype.push.apply(this, arguments[0]);
+ }
+
+ },
+
+ // Custom Error Throwing for Two.js
+
+ Error: function(message) {
+ this.name = 'two.js';
+ this.message = message;
+ },
+
+ Events: {
+
+ on: function(name, callback) {
+
+ this._events || (this._events = {});
+ var list = this._events[name] || (this._events[name] = []);
+
+ list.push(callback);
+
+ return this;
+
+ },
+
+ off: function(name, callback) {
+
+ if (!this._events) {
+ return this;
+ }
+ if (!name && !callback) {
+ this._events = {};
+ return this;
+ }
+
+ var names = name ? [name] : _.keys(this._events);
+ for (var i = 0, l = names.length; i < l; i++) {
+
+ var name = names[i];
+ var list = this._events[name];
+
+ if (!!list) {
+ var events = [];
+ if (callback) {
+ for (var j = 0, k = list.length; j < k; j++) {
+ var ev = list[j];
+ ev = ev.callback ? ev.callback : ev;
+ if (callback && callback !== ev) {
+ events.push(ev);
+ }
+ }
+ }
+ this._events[name] = events;
+ }
+ }
+
+ return this;
+ },
+
+ trigger: function(name) {
+ if (!this._events) return this;
+ var args = slice.call(arguments, 1);
+ var events = this._events[name];
+ if (events) trigger(this, events, args);
+ return this;
+ },
+
+ listen: function (obj, name, callback) {
+
+ var bound = this;
+
+ if (obj) {
+ var ev = function () {
+ callback.apply(bound, arguments);
+ };
+
+ // add references about the object that assigned this listener
+ ev.obj = obj;
+ ev.name = name;
+ ev.callback = callback;
+
+ obj.on(name, ev);
+ }
+
+ return this;
+
+ },
+
+ ignore: function (obj, name, callback) {
+
+ obj.off(name, callback);
+
+ return this;
+
+ }
+
+ }
+
+ })
+
+ });
+
+ Two.Utils.Events.bind = Two.Utils.Events.on;
+ Two.Utils.Events.unbind = Two.Utils.Events.off;
+
+ var trigger = function(obj, events, args) {
+ var method;
+ switch (args.length) {
+ case 0:
+ method = function(i) {
+ events[i].call(obj, args[0]);
+ };
+ break;
+ case 1:
+ method = function(i) {
+ events[i].call(obj, args[0], args[1]);
+ };
+ break;
+ case 2:
+ method = function(i) {
+ events[i].call(obj, args[0], args[1], args[2]);
+ };
+ break;
+ case 3:
+ method = function(i) {
+ events[i].call(obj, args[0], args[1], args[2], args[3]);
+ };
+ break;
+ default:
+ method = function(i) {
+ events[i].apply(obj, args);
+ };
+ }
+ for (var i = 0; i < events.length; i++) {
+ method(i);
+ }
+ };
+
+ Two.Utils.Error.prototype = new Error();
+ Two.Utils.Error.prototype.constructor = Two.Utils.Error;
+
+ Two.Utils.Collection.prototype = new Array();
+ Two.Utils.Collection.prototype.constructor = Two.Utils.Collection;
+
+ _.extend(Two.Utils.Collection.prototype, Two.Utils.Events, {
+
+ pop: function() {
+ var popped = Array.prototype.pop.apply(this, arguments);
+ this.trigger(Two.Events.remove, [popped]);
+ return popped;
+ },
+
+ shift: function() {
+ var shifted = Array.prototype.shift.apply(this, arguments);
+ this.trigger(Two.Events.remove, [shifted]);
+ return shifted;
+ },
+
+ push: function() {
+ var pushed = Array.prototype.push.apply(this, arguments);
+ this.trigger(Two.Events.insert, arguments);
+ return pushed;
+ },
+
+ unshift: function() {
+ var unshifted = Array.prototype.unshift.apply(this, arguments);
+ this.trigger(Two.Events.insert, arguments);
+ return unshifted;
+ },
+
+ splice: function() {
+ var spliced = Array.prototype.splice.apply(this, arguments);
+ var inserted;
+
+ this.trigger(Two.Events.remove, spliced);
+
+ if (arguments.length > 2) {
+ inserted = this.slice(arguments[0], arguments[0] + arguments.length - 2);
+ this.trigger(Two.Events.insert, inserted);
+ this.trigger(Two.Events.order);
+ }
+ return spliced;
+ },
+
+ sort: function() {
+ Array.prototype.sort.apply(this, arguments);
+ this.trigger(Two.Events.order);
+ return this;
+ },
+
+ reverse: function() {
+ Array.prototype.reverse.apply(this, arguments);
+ this.trigger(Two.Events.order);
+ return this;
+ }
+
+ });
+
+ // Localize utils
+
+ var distanceBetween = Two.Utils.distanceBetween,
+ getAnchorsFromArcData = Two.Utils.getAnchorsFromArcData,
+ distanceBetweenSquared = Two.Utils.distanceBetweenSquared,
+ ratioBetween = Two.Utils.ratioBetween,
+ angleBetween = Two.Utils.angleBetween,
+ getControlPoints = Two.Utils.getControlPoints,
+ getCurveFromPoints = Two.Utils.getCurveFromPoints,
+ solveSegmentIntersection = Two.Utils.solveSegmentIntersection,
+ decoupleShapes = Two.Utils.decoupleShapes,
+ mod = Two.Utils.mod,
+ getBackingStoreRatio = Two.Utils.getBackingStoreRatio,
+ getPointOnCubicBezier = Two.Utils.getPointOnCubicBezier,
+ getCurveLength = Two.Utils.getCurveLength,
+ integrate = Two.Utils.integrate,
+ getReflection = Two.Utils.getReflection;
+
+ _.extend(Two.prototype, Two.Utils.Events, {
+
+ appendTo: function(elem) {
+
+ elem.appendChild(this.renderer.domElement);
+ return this;
+
+ },
+
+ play: function() {
+
+ Two.Utils.setPlaying.call(this, true);
+ return this.trigger(Two.Events.play);
+
+ },
+
+ pause: function() {
+
+ this.playing = false;
+ return this.trigger(Two.Events.pause);
+
+ },
+
+ /**
+ * Update positions and calculations in one pass before rendering.
+ */
+ update: function() {
+
+ var animated = !!this._lastFrame;
+ var now = perf.now();
+
+ this.frameCount++;
+
+ if (animated) {
+ this.timeDelta = parseFloat((now - this._lastFrame).toFixed(3));
+ }
+ this._lastFrame = now;
+
+ var width = this.width;
+ var height = this.height;
+ var renderer = this.renderer;
+
+ // Update width / height for the renderer
+ if (width !== renderer.width || height !== renderer.height) {
+ renderer.setSize(width, height, this.ratio);
+ }
+
+ this.trigger(Two.Events.update, this.frameCount, this.timeDelta);
+
+ return this.render();
+
+ },
+
+ /**
+ * Render all drawable - visible objects of the scene.
+ */
+ render: function() {
+
+ this.renderer.render();
+ return this.trigger(Two.Events.render, this.frameCount);
+
+ },
+
+ /**
+ * Convenience Methods
+ */
+
+ add: function(o) {
+
+ var objects = o;
+ if (!(objects instanceof Array)) {
+ objects = _.toArray(arguments);
+ }
+
+ this.scene.add(objects);
+ return this;
+
+ },
+
+ remove: function(o) {
+
+ var objects = o;
+ if (!(objects instanceof Array)) {
+ objects = _.toArray(arguments);
+ }
+
+ this.scene.remove(objects);
+
+ return this;
+
+ },
+
+ clear: function() {
+
+ this.scene.remove(_.toArray(this.scene.children));
+ return this;
+
+ },
+
+ makeLine: function(x1, y1, x2, y2) {
+
+ var line = new Two.Line(x1, y1, x2, y2);
+ this.scene.add(line);
+
+ return line;
+
+ },
+
+ makeRectangle: function(x, y, width, height) {
+
+ var rect = new Two.Rectangle(x, y, width, height);
+ this.scene.add(rect);
+
+ return rect;
+
+ },
+
+ makeRoundedRectangle: function(x, y, width, height, sides) {
+
+ var rect = new Two.RoundedRectangle(x, y, width, height, sides);
+ this.scene.add(rect);
+
+ return rect;
+
+ },
+
+ makeCircle: function(ox, oy, r) {
+
+ var circle = new Two.Circle(ox, oy, r);
+ this.scene.add(circle);
+
+ return circle;
+
+ },
+
+ makeEllipse: function(ox, oy, rx, ry) {
+
+ var ellipse = new Two.Ellipse(ox, oy, rx, ry);
+ this.scene.add(ellipse);
+
+ return ellipse;
+
+ },
+
+ makeStar: function(ox, oy, or, ir, sides) {
+
+ var star = new Two.Star(ox, oy, or, ir, sides);
+ this.scene.add(star);
+
+ return star;
+
+ },
+
+ makeCurve: function(p) {
+
+ var l = arguments.length, points = p;
+ if (!_.isArray(p)) {
+ points = [];
+ for (var i = 0; i < l; i+=2) {
+ var x = arguments[i];
+ if (!_.isNumber(x)) {
+ break;
+ }
+ var y = arguments[i + 1];
+ points.push(new Two.Anchor(x, y));
+ }
+ }
+
+ var last = arguments[l - 1];
+ var curve = new Two.Path(points, !(_.isBoolean(last) ? last : undefined), true);
+ var rect = curve.getBoundingClientRect();
+ curve.center().translation
+ .set(rect.left + rect.width / 2, rect.top + rect.height / 2);
+
+ this.scene.add(curve);
+
+ return curve;
+
+ },
+
+ makePolygon: function(ox, oy, r, sides) {
+
+ var poly = new Two.Polygon(ox, oy, r, sides);
+ this.scene.add(poly);
+
+ return poly;
+
+ },
+
+ /*
+ * Make an Arc Segment
+ */
+
+ makeArcSegment: function(ox, oy, ir, or, sa, ea, res) {
+ var arcSegment = new Two.ArcSegment(ox, oy, ir, or, sa, ea, res);
+ this.scene.add(arcSegment);
+ return arcSegment;
+ },
+
+ /**
+ * Convenience method to make and draw a Two.Path.
+ */
+ makePath: function(p) {
+
+ var l = arguments.length, points = p;
+ if (!_.isArray(p)) {
+ points = [];
+ for (var i = 0; i < l; i+=2) {
+ var x = arguments[i];
+ if (!_.isNumber(x)) {
+ break;
+ }
+ var y = arguments[i + 1];
+ points.push(new Two.Anchor(x, y));
+ }
+ }
+
+ var last = arguments[l - 1];
+ var path = new Two.Path(points, !(_.isBoolean(last) ? last : undefined));
+ var rect = path.getBoundingClientRect();
+ path.center().translation
+ .set(rect.left + rect.width / 2, rect.top + rect.height / 2);
+
+ this.scene.add(path);
+
+ return path;
+
+ },
+
+ /**
+ * Convenience method to make and add a Two.Text.
+ */
+ makeText: function(message, x, y, styles) {
+ var text = new Two.Text(message, x, y, styles);
+ this.add(text);
+ return text;
+ },
+
+ /**
+ * Convenience method to make and add a Two.LinearGradient.
+ */
+ makeLinearGradient: function(x1, y1, x2, y2 /* stops */) {
+
+ var stops = slice.call(arguments, 4);
+ var gradient = new Two.LinearGradient(x1, y1, x2, y2, stops);
+
+ this.add(gradient);
+
+ return gradient;
+
+ },
+
+ /**
+ * Convenience method to make and add a Two.RadialGradient.
+ */
+ makeRadialGradient: function(x1, y1, r /* stops */) {
+
+ var stops = slice.call(arguments, 3);
+ var gradient = new Two.RadialGradient(x1, y1, r, stops);
+
+ this.add(gradient);
+
+ return gradient;
+
+ },
+
+ makeSprite: function(path, x, y, cols, rows, frameRate, autostart) {
+
+ var sprite = new Two.Sprite(path, x, y, cols, rows, frameRate);
+ if (!!autostart) {
+ sprite.play();
+ }
+ this.add(sprite);
+
+ return sprite;
+
+ },
+
+ makeImageSequence: function(paths, x, y, frameRate, autostart) {
+
+ var imageSequence = new Two.ImageSequence(paths, x, y, frameRate);
+ if (!!autostart) {
+ imageSequence.play();
+ }
+ this.add(imageSequence);
+
+ return imageSequence;
+
+ },
+
+ makeTexture: function(path, callback) {
+
+ var texture = new Two.Texture(path, callback);
+ return texture;
+
+ },
+
+ makeGroup: function(o) {
+
+ var objects = o;
+ if (!(objects instanceof Array)) {
+ objects = _.toArray(arguments);
+ }
+
+ var group = new Two.Group();
+ this.scene.add(group);
+ group.add(objects);
+
+ return group;
+
+ },
+
+ /**
+ * Interpret an SVG Node and add it to this instance's scene. The
+ * distinction should be made that this doesn't `import` svg's, it solely
+ * interprets them into something compatible for Two.js — this is slightly
+ * different than a direct transcription.
+ *
+ * @param {Object} svgNode - The node to be parsed
+ * @param {Boolean} shallow - Don't create a top-most group but
+ * append all contents directly
+ */
+ interpret: function(svgNode, shallow) {
+
+ var tag = svgNode.tagName.toLowerCase();
+
+ if (!(tag in Two.Utils.read)) {
+ return null;
+ }
+
+ var node = Two.Utils.read[tag].call(this, svgNode);
+
+ if (shallow && node instanceof Two.Group) {
+ this.add(node.children);
+ } else {
+ this.add(node);
+ }
+
+ return node;
+
+ },
+
+ /**
+ * Load an SVG file / text and interpret.
+ */
+ load: function(text, callback) {
+
+ var nodes = [], elem, i;
+
+ if (/.*\.svg/ig.test(text)) {
+
+ Two.Utils.xhr(text, _.bind(function(data) {
+
+ dom.temp.innerHTML = data;
+ for (i = 0; i < dom.temp.children.length; i++) {
+ elem = dom.temp.children[i];
+ nodes.push(this.interpret(elem));
+ }
+
+ callback(nodes.length <= 1 ? nodes[0] : nodes,
+ dom.temp.children.length <= 1 ? dom.temp.children[0] : dom.temp.children);
+
+ }, this));
+
+ return this;
+
+ }
+
+ dom.temp.innerHTML = text;
+ for (i = 0; i < dom.temp.children.length; i++) {
+ elem = dom.temp.children[i];
+ nodes.push(this.interpret(elem));
+ }
+
+ callback(nodes.length <= 1 ? nodes[0] : nodes,
+ dom.temp.children.length <= 1 ? dom.temp.children[0] : dom.temp.children);
+
+ return this;
+
+ }
+
+ });
+
+ function fitToWindow() {
+
+ var wr = document.body.getBoundingClientRect();
+
+ var width = this.width = wr.width;
+ var height = this.height = wr.height;
+
+ this.renderer.setSize(width, height, this.ratio);
+ this.trigger(Two.Events.resize, width, height);
+
+ }
+
+ // Request Animation Frame
+
+ var raf = dom.getRequestAnimationFrame();
+
+ function loop() {
+
+ raf(loop);
+
+ for (var i = 0; i < Two.Instances.length; i++) {
+ var t = Two.Instances[i];
+ if (t.playing) {
+ t.update();
+ }
+ }
+
+ }
+
+ if (typeof define === 'function' && define.amd) {
+ define('two', [], function() {
+ return Two;
+ });
+ } else if (typeof module != 'undefined' && module.exports) {
+ module.exports = Two;
+ }
+
+ return Two;
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ var _ = Two.Utils;
+
+ var Registry = Two.Registry = function() {
+
+ this.map = {};
+
+ };
+
+ _.extend(Registry, {
+
+ });
+
+ _.extend(Registry.prototype, {
+
+ add: function(id, obj) {
+ this.map[id] = obj;
+ return this;
+ },
+
+ remove: function(id) {
+ delete this.map[id];
+ return this;
+ },
+
+ get: function(id) {
+ return this.map[id];
+ },
+
+ contains: function(id) {
+ return id in this.map;
+ }
+
+ });
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ var _ = Two.Utils;
+
+ var Vector = Two.Vector = function(x, y) {
+
+ this.x = x || 0;
+ this.y = y || 0;
+
+ };
+
+ _.extend(Vector, {
+
+ zero: new Two.Vector()
+
+ });
+
+ _.extend(Vector.prototype, Two.Utils.Events, {
+
+ set: function(x, y) {
+ this.x = x;
+ this.y = y;
+ return this;
+ },
+
+ copy: function(v) {
+ this.x = v.x;
+ this.y = v.y;
+ return this;
+ },
+
+ clear: function() {
+ this.x = 0;
+ this.y = 0;
+ return this;
+ },
+
+ clone: function() {
+ return new Vector(this.x, this.y);
+ },
+
+ add: function(v1, v2) {
+ this.x = v1.x + v2.x;
+ this.y = v1.y + v2.y;
+ return this;
+ },
+
+ addSelf: function(v) {
+ this.x += v.x;
+ this.y += v.y;
+ return this;
+ },
+
+ sub: function(v1, v2) {
+ this.x = v1.x - v2.x;
+ this.y = v1.y - v2.y;
+ return this;
+ },
+
+ subSelf: function(v) {
+ this.x -= v.x;
+ this.y -= v.y;
+ return this;
+ },
+
+ multiplySelf: function(v) {
+ this.x *= v.x;
+ this.y *= v.y;
+ return this;
+ },
+
+ multiplyScalar: function(s) {
+ this.x *= s;
+ this.y *= s;
+ return this;
+ },
+
+ divideScalar: function(s) {
+ if (s) {
+ this.x /= s;
+ this.y /= s;
+ } else {
+ this.set(0, 0);
+ }
+ return this;
+ },
+
+ negate: function() {
+ return this.multiplyScalar(-1);
+ },
+
+ dot: function(v) {
+ return this.x * v.x + this.y * v.y;
+ },
+
+ lengthSquared: function() {
+ return this.x * this.x + this.y * this.y;
+ },
+
+ length: function() {
+ return Math.sqrt(this.lengthSquared());
+ },
+
+ normalize: function() {
+ return this.divideScalar(this.length());
+ },
+
+ distanceTo: function(v) {
+ return Math.sqrt(this.distanceToSquared(v));
+ },
+
+ distanceToSquared: function(v) {
+ var dx = this.x - v.x,
+ dy = this.y - v.y;
+ return dx * dx + dy * dy;
+ },
+
+ setLength: function(l) {
+ return this.normalize().multiplyScalar(l);
+ },
+
+ equals: function(v, eps) {
+ eps = (typeof eps === 'undefined') ? 0.0001 : eps;
+ return (this.distanceTo(v) < eps);
+ },
+
+ lerp: function(v, t) {
+ var x = (v.x - this.x) * t + this.x;
+ var y = (v.y - this.y) * t + this.y;
+ return this.set(x, y);
+ },
+
+ isZero: function(eps) {
+ eps = (typeof eps === 'undefined') ? 0.0001 : eps;
+ return (this.length() < eps);
+ },
+
+ toString: function() {
+ return this.x + ', ' + this.y;
+ },
+
+ toObject: function() {
+ return { x: this.x, y: this.y };
+ },
+
+ rotate: function (radians) {
+ var cos = Math.cos(radians);
+ var sin = Math.sin(radians);
+ this.x = this.x * cos - this.y * sin;
+ this.y = this.x * sin + this.y * cos;
+ return this;
+ }
+
+ });
+
+ var BoundProto = {
+
+ set: function(x, y) {
+ this._x = x;
+ this._y = y;
+ return this.trigger(Two.Events.change);
+ },
+
+ copy: function(v) {
+ this._x = v.x;
+ this._y = v.y;
+ return this.trigger(Two.Events.change);
+ },
+
+ clear: function() {
+ this._x = 0;
+ this._y = 0;
+ return this.trigger(Two.Events.change);
+ },
+
+ clone: function() {
+ return new Vector(this._x, this._y);
+ },
+
+ add: function(v1, v2) {
+ this._x = v1.x + v2.x;
+ this._y = v1.y + v2.y;
+ return this.trigger(Two.Events.change);
+ },
+
+ addSelf: function(v) {
+ this._x += v.x;
+ this._y += v.y;
+ return this.trigger(Two.Events.change);
+ },
+
+ sub: function(v1, v2) {
+ this._x = v1.x - v2.x;
+ this._y = v1.y - v2.y;
+ return this.trigger(Two.Events.change);
+ },
+
+ subSelf: function(v) {
+ this._x -= v.x;
+ this._y -= v.y;
+ return this.trigger(Two.Events.change);
+ },
+
+ multiplySelf: function(v) {
+ this._x *= v.x;
+ this._y *= v.y;
+ return this.trigger(Two.Events.change);
+ },
+
+ multiplyScalar: function(s) {
+ this._x *= s;
+ this._y *= s;
+ return this.trigger(Two.Events.change);
+ },
+
+ divideScalar: function(s) {
+ if (s) {
+ this._x /= s;
+ this._y /= s;
+ return this.trigger(Two.Events.change);
+ }
+ return this.clear();
+ },
+
+ negate: function() {
+ return this.multiplyScalar(-1);
+ },
+
+ dot: function(v) {
+ return this._x * v.x + this._y * v.y;
+ },
+
+ lengthSquared: function() {
+ return this._x * this._x + this._y * this._y;
+ },
+
+ length: function() {
+ return Math.sqrt(this.lengthSquared());
+ },
+
+ normalize: function() {
+ return this.divideScalar(this.length());
+ },
+
+ distanceTo: function(v) {
+ return Math.sqrt(this.distanceToSquared(v));
+ },
+
+ distanceToSquared: function(v) {
+ var dx = this._x - v.x,
+ dy = this._y - v.y;
+ return dx * dx + dy * dy;
+ },
+
+ setLength: function(l) {
+ return this.normalize().multiplyScalar(l);
+ },
+
+ equals: function(v, eps) {
+ eps = (typeof eps === 'undefined') ? 0.0001 : eps;
+ return (this.distanceTo(v) < eps);
+ },
+
+ lerp: function(v, t) {
+ var x = (v.x - this._x) * t + this._x;
+ var y = (v.y - this._y) * t + this._y;
+ return this.set(x, y);
+ },
+
+ isZero: function(eps) {
+ eps = (typeof eps === 'undefined') ? 0.0001 : eps;
+ return (this.length() < eps);
+ },
+
+ toString: function() {
+ return this._x + ', ' + this._y;
+ },
+
+ toObject: function() {
+ return { x: this._x, y: this._y };
+ },
+
+ rotate: function (radians) {
+ var cos = Math.cos(radians);
+ var sin = Math.sin(radians);
+ this._x = this._x * cos - this._y * sin;
+ this._y = this._x * sin + this._y * cos;
+ return this;
+ }
+
+ };
+
+ var xgs = {
+ enumerable: true,
+ get: function() {
+ return this._x;
+ },
+ set: function(v) {
+ this._x = v;
+ this.trigger(Two.Events.change, 'x');
+ }
+ };
+
+ var ygs = {
+ enumerable: true,
+ get: function() {
+ return this._y;
+ },
+ set: function(v) {
+ this._y = v;
+ this.trigger(Two.Events.change, 'y');
+ }
+ };
+
+ /**
+ * Override Backbone bind / on in order to add properly broadcasting.
+ * This allows Two.Vector to not broadcast events unless event listeners
+ * are explicity bound to it.
+ */
+
+ Two.Vector.prototype.bind = Two.Vector.prototype.on = function() {
+
+ if (!this._bound) {
+ this._x = this.x;
+ this._y = this.y;
+ Object.defineProperty(this, 'x', xgs);
+ Object.defineProperty(this, 'y', ygs);
+ _.extend(this, BoundProto);
+ this._bound = true; // Reserved for event initialization check
+ }
+
+ Two.Utils.Events.bind.apply(this, arguments);
+
+ return this;
+
+ };
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ // Localized variables
+ var commands = Two.Commands;
+ var _ = Two.Utils;
+
+ /**
+ * An object that holds 3 `Two.Vector`s, the anchor point and its
+ * corresponding handles: `left` and `right`.
+ */
+ var Anchor = Two.Anchor = function(x, y, ux, uy, vx, vy, command) {
+
+ Two.Vector.call(this, x, y);
+
+ this._broadcast = _.bind(function() {
+ this.trigger(Two.Events.change);
+ }, this);
+
+ this._command = command || commands.move;
+ this._relative = true;
+
+ if (!command) {
+ return this;
+ }
+
+ Anchor.AppendCurveProperties(this);
+
+ if (_.isNumber(ux)) {
+ this.controls.left.x = ux;
+ }
+ if (_.isNumber(uy)) {
+ this.controls.left.y = uy;
+ }
+ if (_.isNumber(vx)) {
+ this.controls.right.x = vx;
+ }
+ if (_.isNumber(vy)) {
+ this.controls.right.y = vy;
+ }
+
+ };
+
+ _.extend(Anchor, {
+
+ AppendCurveProperties: function(anchor) {
+ anchor.controls = {
+ left: new Two.Vector(0, 0),
+ right: new Two.Vector(0, 0)
+ };
+ }
+
+ });
+
+ var AnchorProto = {
+
+ listen: function() {
+
+ if (!_.isObject(this.controls)) {
+ Anchor.AppendCurveProperties(this);
+ }
+
+ this.controls.left.bind(Two.Events.change, this._broadcast);
+ this.controls.right.bind(Two.Events.change, this._broadcast);
+
+ return this;
+
+ },
+
+ ignore: function() {
+
+ this.controls.left.unbind(Two.Events.change, this._broadcast);
+ this.controls.right.unbind(Two.Events.change, this._broadcast);
+
+ return this;
+
+ },
+
+ clone: function() {
+
+ var controls = this.controls;
+
+ var clone = new Two.Anchor(
+ this.x,
+ this.y,
+ controls && controls.left.x,
+ controls && controls.left.y,
+ controls && controls.right.x,
+ controls && controls.right.y,
+ this.command
+ );
+ clone.relative = this._relative;
+ return clone;
+
+ },
+
+ toObject: function() {
+ var o = {
+ x: this.x,
+ y: this.y
+ };
+ if (this._command) {
+ o.command = this._command;
+ }
+ if (this._relative) {
+ o.relative = this._relative;
+ }
+ if (this.controls) {
+ o.controls = {
+ left: this.controls.left.toObject(),
+ right: this.controls.right.toObject()
+ };
+ }
+ return o;
+ },
+
+ toString: function() {
+ if (!this.controls) {
+ return [this._x, this._y].join(', ');
+ }
+ return [this._x, this._y, this.controls.left.x, this.controls.left.y,
+ this.controls.right.x, this.controls.right.y].join(', ');
+ }
+
+ };
+
+ Object.defineProperty(Anchor.prototype, 'command', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._command;
+ },
+
+ set: function(c) {
+ this._command = c;
+ if (this._command === commands.curve && !_.isObject(this.controls)) {
+ Anchor.AppendCurveProperties(this);
+ }
+ return this.trigger(Two.Events.change);
+ }
+
+ });
+
+ Object.defineProperty(Anchor.prototype, 'relative', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._relative;
+ },
+
+ set: function(b) {
+ if (this._relative == b) {
+ return this;
+ }
+ this._relative = !!b;
+ return this.trigger(Two.Events.change);
+ }
+
+ });
+
+ _.extend(Anchor.prototype, Two.Vector.prototype, AnchorProto);
+
+ // Make it possible to bind and still have the Anchor specific
+ // inheritance from Two.Vector
+ Two.Anchor.prototype.bind = Two.Anchor.prototype.on = function() {
+ Two.Vector.prototype.bind.apply(this, arguments);
+ _.extend(this, AnchorProto);
+ };
+
+ Two.Anchor.prototype.unbind = Two.Anchor.prototype.off = function() {
+ Two.Vector.prototype.unbind.apply(this, arguments);
+ _.extend(this, AnchorProto);
+ };
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ /**
+ * Constants
+ */
+ var cos = Math.cos, sin = Math.sin, tan = Math.tan;
+ var _ = Two.Utils;
+
+ /**
+ * Two.Matrix contains an array of elements that represent
+ * the two dimensional 3 x 3 matrix as illustrated below:
+ *
+ * =====
+ * a b c
+ * d e f
+ * g h i // this row is not really used in 2d transformations
+ * =====
+ *
+ * String order is for transform strings: a, d, b, e, c, f
+ *
+ * @class
+ */
+ var Matrix = Two.Matrix = function(a, b, c, d, e, f) {
+
+ this.elements = new Two.Array(9);
+
+ var elements = a;
+ if (!_.isArray(elements)) {
+ elements = _.toArray(arguments);
+ }
+
+ // initialize the elements with default values.
+
+ this.identity().set(elements);
+
+ };
+
+ _.extend(Matrix, {
+
+ Identity: [
+ 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1
+ ],
+
+ /**
+ * Multiply two matrix 3x3 arrays
+ */
+ Multiply: function(A, B, C) {
+
+ if (B.length <= 3) { // Multiply Vector
+
+ var x, y, z, e = A;
+
+ var a = B[0] || 0,
+ b = B[1] || 0,
+ c = B[2] || 0;
+
+ // Go down rows first
+ // a, d, g, b, e, h, c, f, i
+
+ x = e[0] * a + e[1] * b + e[2] * c;
+ y = e[3] * a + e[4] * b + e[5] * c;
+ z = e[6] * a + e[7] * b + e[8] * c;
+
+ return { x: x, y: y, z: z };
+
+ }
+
+ var A0 = A[0], A1 = A[1], A2 = A[2];
+ var A3 = A[3], A4 = A[4], A5 = A[5];
+ var A6 = A[6], A7 = A[7], A8 = A[8];
+
+ var B0 = B[0], B1 = B[1], B2 = B[2];
+ var B3 = B[3], B4 = B[4], B5 = B[5];
+ var B6 = B[6], B7 = B[7], B8 = B[8];
+
+ C = C || new Two.Array(9);
+
+ C[0] = A0 * B0 + A1 * B3 + A2 * B6;
+ C[1] = A0 * B1 + A1 * B4 + A2 * B7;
+ C[2] = A0 * B2 + A1 * B5 + A2 * B8;
+ C[3] = A3 * B0 + A4 * B3 + A5 * B6;
+ C[4] = A3 * B1 + A4 * B4 + A5 * B7;
+ C[5] = A3 * B2 + A4 * B5 + A5 * B8;
+ C[6] = A6 * B0 + A7 * B3 + A8 * B6;
+ C[7] = A6 * B1 + A7 * B4 + A8 * B7;
+ C[8] = A6 * B2 + A7 * B5 + A8 * B8;
+
+ return C;
+
+ }
+
+ });
+
+ _.extend(Matrix.prototype, Two.Utils.Events, {
+
+ /**
+ * Takes an array of elements or the arguments list itself to
+ * set and update the current matrix's elements. Only updates
+ * specified values.
+ */
+ set: function(a) {
+
+ var elements = a;
+ if (!_.isArray(elements)) {
+ elements = _.toArray(arguments);
+ }
+
+ _.extend(this.elements, elements);
+
+ return this.trigger(Two.Events.change);
+
+ },
+
+ /**
+ * Turn matrix to identity, like resetting.
+ */
+ identity: function() {
+
+ this.set(Matrix.Identity);
+
+ return this;
+
+ },
+
+ /**
+ * Multiply scalar or multiply by another matrix.
+ */
+ multiply: function(a, b, c, d, e, f, g, h, i) {
+
+ var elements = arguments, l = elements.length;
+
+ // Multiply scalar
+
+ if (l <= 1) {
+
+ _.each(this.elements, function(v, i) {
+ this.elements[i] = v * a;
+ }, this);
+
+ return this.trigger(Two.Events.change);
+
+ }
+
+ if (l <= 3) { // Multiply Vector
+
+ var x, y, z;
+ a = a || 0;
+ b = b || 0;
+ c = c || 0;
+ e = this.elements;
+
+ // Go down rows first
+ // a, d, g, b, e, h, c, f, i
+
+ x = e[0] * a + e[1] * b + e[2] * c;
+ y = e[3] * a + e[4] * b + e[5] * c;
+ z = e[6] * a + e[7] * b + e[8] * c;
+
+ return { x: x, y: y, z: z };
+
+ }
+
+ // Multiple matrix
+
+ var A = this.elements;
+ var B = elements;
+
+ var A0 = A[0], A1 = A[1], A2 = A[2];
+ var A3 = A[3], A4 = A[4], A5 = A[5];
+ var A6 = A[6], A7 = A[7], A8 = A[8];
+
+ var B0 = B[0], B1 = B[1], B2 = B[2];
+ var B3 = B[3], B4 = B[4], B5 = B[5];
+ var B6 = B[6], B7 = B[7], B8 = B[8];
+
+ this.elements[0] = A0 * B0 + A1 * B3 + A2 * B6;
+ this.elements[1] = A0 * B1 + A1 * B4 + A2 * B7;
+ this.elements[2] = A0 * B2 + A1 * B5 + A2 * B8;
+
+ this.elements[3] = A3 * B0 + A4 * B3 + A5 * B6;
+ this.elements[4] = A3 * B1 + A4 * B4 + A5 * B7;
+ this.elements[5] = A3 * B2 + A4 * B5 + A5 * B8;
+
+ this.elements[6] = A6 * B0 + A7 * B3 + A8 * B6;
+ this.elements[7] = A6 * B1 + A7 * B4 + A8 * B7;
+ this.elements[8] = A6 * B2 + A7 * B5 + A8 * B8;
+
+ return this.trigger(Two.Events.change);
+
+ },
+
+ inverse: function(out) {
+
+ var a = this.elements;
+ out = out || new Two.Matrix();
+
+ var a00 = a[0], a01 = a[1], a02 = a[2];
+ var a10 = a[3], a11 = a[4], a12 = a[5];
+ var a20 = a[6], a21 = a[7], a22 = a[8];
+
+ var b01 = a22 * a11 - a12 * a21;
+ var b11 = -a22 * a10 + a12 * a20;
+ var b21 = a21 * a10 - a11 * a20;
+
+ // Calculate the determinant
+ var det = a00 * b01 + a01 * b11 + a02 * b21;
+
+ if (!det) {
+ return null;
+ }
+
+ det = 1.0 / det;
+
+ out.elements[0] = b01 * det;
+ out.elements[1] = (-a22 * a01 + a02 * a21) * det;
+ out.elements[2] = (a12 * a01 - a02 * a11) * det;
+ out.elements[3] = b11 * det;
+ out.elements[4] = (a22 * a00 - a02 * a20) * det;
+ out.elements[5] = (-a12 * a00 + a02 * a10) * det;
+ out.elements[6] = b21 * det;
+ out.elements[7] = (-a21 * a00 + a01 * a20) * det;
+ out.elements[8] = (a11 * a00 - a01 * a10) * det;
+
+ return out;
+
+ },
+
+ /**
+ * Set a scalar onto the matrix.
+ */
+ scale: function(sx, sy) {
+
+ var l = arguments.length;
+ if (l <= 1) {
+ sy = sx;
+ }
+
+ return this.multiply(sx, 0, 0, 0, sy, 0, 0, 0, 1);
+
+ },
+
+ /**
+ * Rotate the matrix.
+ */
+ rotate: function(radians) {
+
+ var c = cos(radians);
+ var s = sin(radians);
+
+ return this.multiply(c, -s, 0, s, c, 0, 0, 0, 1);
+
+ },
+
+ /**
+ * Translate the matrix.
+ */
+ translate: function(x, y) {
+
+ return this.multiply(1, 0, x, 0, 1, y, 0, 0, 1);
+
+ },
+
+ /*
+ * Skew the matrix by an angle in the x axis direction.
+ */
+ skewX: function(radians) {
+
+ var a = tan(radians);
+
+ return this.multiply(1, a, 0, 0, 1, 0, 0, 0, 1);
+
+ },
+
+ /*
+ * Skew the matrix by an angle in the y axis direction.
+ */
+ skewY: function(radians) {
+
+ var a = tan(radians);
+
+ return this.multiply(1, 0, 0, a, 1, 0, 0, 0, 1);
+
+ },
+
+ /**
+ * Create a transform string to be used with rendering apis.
+ */
+ toString: function(fullMatrix) {
+ var temp = [];
+
+ this.toArray(fullMatrix, temp);
+
+ return temp.join(' ');
+
+ },
+
+ /**
+ * Create a transform array to be used with rendering apis.
+ */
+ toArray: function(fullMatrix, output) {
+
+ var elements = this.elements;
+ var hasOutput = !!output;
+
+ var a = parseFloat(elements[0].toFixed(3));
+ var b = parseFloat(elements[1].toFixed(3));
+ var c = parseFloat(elements[2].toFixed(3));
+ var d = parseFloat(elements[3].toFixed(3));
+ var e = parseFloat(elements[4].toFixed(3));
+ var f = parseFloat(elements[5].toFixed(3));
+
+ if (!!fullMatrix) {
+
+ var g = parseFloat(elements[6].toFixed(3));
+ var h = parseFloat(elements[7].toFixed(3));
+ var i = parseFloat(elements[8].toFixed(3));
+
+ if (hasOutput) {
+ output[0] = a;
+ output[1] = d;
+ output[2] = g;
+ output[3] = b;
+ output[4] = e;
+ output[5] = h;
+ output[6] = c;
+ output[7] = f;
+ output[8] = i;
+ return;
+ }
+
+ return [
+ a, d, g, b, e, h, c, f, i
+ ];
+ }
+
+ if (hasOutput) {
+ output[0] = a;
+ output[1] = d;
+ output[2] = b;
+ output[3] = e;
+ output[4] = c;
+ output[5] = f;
+ return;
+ }
+
+ return [
+ a, d, b, e, c, f // Specific format see LN:19
+ ];
+
+ },
+
+ /**
+ * Clone the current matrix.
+ */
+ clone: function() {
+ var a, b, c, d, e, f, g, h, i;
+
+ a = this.elements[0];
+ b = this.elements[1];
+ c = this.elements[2];
+ d = this.elements[3];
+ e = this.elements[4];
+ f = this.elements[5];
+ g = this.elements[6];
+ h = this.elements[7];
+ i = this.elements[8];
+
+ return new Two.Matrix(a, b, c, d, e, f, g, h, i);
+
+ }
+
+ });
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ // Localize variables
+ var mod = Two.Utils.mod, toFixed = Two.Utils.toFixed;
+ var _ = Two.Utils;
+
+ var svg = {
+
+ version: 1.1,
+
+ ns: 'http://www.w3.org/2000/svg',
+ xlink: 'http://www.w3.org/1999/xlink',
+
+ alignments: {
+ left: 'start',
+ center: 'middle',
+ right: 'end'
+ },
+
+ /**
+ * Create an svg namespaced element.
+ */
+ createElement: function(name, attrs) {
+ var tag = name;
+ var elem = document.createElementNS(svg.ns, tag);
+ if (tag === 'svg') {
+ attrs = _.defaults(attrs || {}, {
+ version: svg.version
+ });
+ }
+ if (!_.isEmpty(attrs)) {
+ svg.setAttributes(elem, attrs);
+ }
+ return elem;
+ },
+
+ /**
+ * Add attributes from an svg element.
+ */
+ setAttributes: function(elem, attrs) {
+ var keys = Object.keys(attrs);
+ for (var i = 0; i < keys.length; i++) {
+ if (/href/.test(keys[i])) {
+ elem.setAttributeNS(svg.xlink, keys[i], attrs[keys[i]]);
+ } else {
+ elem.setAttribute(keys[i], attrs[keys[i]]);
+ }
+ }
+ return this;
+ },
+
+ /**
+ * Remove attributes from an svg element.
+ */
+ removeAttributes: function(elem, attrs) {
+ for (var key in attrs) {
+ elem.removeAttribute(key);
+ }
+ return this;
+ },
+
+ /**
+ * Turn a set of vertices into a string for the d property of a path
+ * element. It is imperative that the string collation is as fast as
+ * possible, because this call will be happening multiple times a
+ * second.
+ */
+ toString: function(points, closed) {
+
+ var l = points.length,
+ last = l - 1,
+ d, // The elusive last Two.Commands.move point
+ ret = '';
+
+ for (var i = 0; i < l; i++) {
+ var b = points[i];
+ var command;
+ var prev = closed ? mod(i - 1, l) : Math.max(i - 1, 0);
+ var next = closed ? mod(i + 1, l) : Math.min(i + 1, last);
+
+ var a = points[prev];
+ var c = points[next];
+
+ var vx, vy, ux, uy, ar, bl, br, cl;
+
+ // Access x and y directly,
+ // bypassing the getter
+ var x = toFixed(b._x);
+ var y = toFixed(b._y);
+
+ switch (b._command) {
+
+ case Two.Commands.close:
+ command = Two.Commands.close;
+ break;
+
+ case Two.Commands.curve:
+
+ ar = (a.controls && a.controls.right) || Two.Vector.zero;
+ bl = (b.controls && b.controls.left) || Two.Vector.zero;
+
+ if (a._relative) {
+ vx = toFixed((ar.x + a.x));
+ vy = toFixed((ar.y + a.y));
+ } else {
+ vx = toFixed(ar.x);
+ vy = toFixed(ar.y);
+ }
+
+ if (b._relative) {
+ ux = toFixed((bl.x + b.x));
+ uy = toFixed((bl.y + b.y));
+ } else {
+ ux = toFixed(bl.x);
+ uy = toFixed(bl.y);
+ }
+
+ command = ((i === 0) ? Two.Commands.move : Two.Commands.curve) +
+ ' ' + vx + ' ' + vy + ' ' + ux + ' ' + uy + ' ' + x + ' ' + y;
+ break;
+
+ case Two.Commands.move:
+ d = b;
+ command = Two.Commands.move + ' ' + x + ' ' + y;
+ break;
+
+ default:
+ command = b._command + ' ' + x + ' ' + y;
+
+ }
+
+ // Add a final point and close it off
+
+ if (i >= last && closed) {
+
+ if (b._command === Two.Commands.curve) {
+
+ // Make sure we close to the most previous Two.Commands.move
+ c = d;
+
+ br = (b.controls && b.controls.right) || b;
+ cl = (c.controls && c.controls.left) || c;
+
+ if (b._relative) {
+ vx = toFixed((br.x + b.x));
+ vy = toFixed((br.y + b.y));
+ } else {
+ vx = toFixed(br.x);
+ vy = toFixed(br.y);
+ }
+
+ if (c._relative) {
+ ux = toFixed((cl.x + c.x));
+ uy = toFixed((cl.y + c.y));
+ } else {
+ ux = toFixed(cl.x);
+ uy = toFixed(cl.y);
+ }
+
+ x = toFixed(c.x);
+ y = toFixed(c.y);
+
+ command +=
+ ' C ' + vx + ' ' + vy + ' ' + ux + ' ' + uy + ' ' + x + ' ' + y;
+ }
+
+ command += ' Z';
+
+ }
+
+ ret += command + ' ';
+
+ }
+
+ return ret;
+
+ },
+
+ getClip: function(shape) {
+
+ var clip = shape._renderer.clip;
+
+ if (!clip) {
+
+ var root = shape;
+
+ while (root.parent) {
+ root = root.parent;
+ }
+
+ clip = shape._renderer.clip = svg.createElement('clipPath');
+ root.defs.appendChild(clip);
+
+ }
+
+ return clip;
+
+ },
+
+ group: {
+
+ // TODO: Can speed up.
+ // TODO: How does this effect a f
+ appendChild: function(object) {
+
+ var elem = object._renderer.elem;
+
+ if (!elem) {
+ return;
+ }
+
+ var tag = elem.nodeName;
+
+ if (!tag || /(radial|linear)gradient/i.test(tag) || object._clip) {
+ return;
+ }
+
+ this.elem.appendChild(elem);
+
+ },
+
+ removeChild: function(object) {
+
+ var elem = object._renderer.elem;
+
+ if (!elem || elem.parentNode != this.elem) {
+ return;
+ }
+
+ var tag = elem.nodeName;
+
+ if (!tag) {
+ return;
+ }
+
+ // Defer subtractions while clipping.
+ if (object._clip) {
+ return;
+ }
+
+ this.elem.removeChild(elem);
+
+ },
+
+ orderChild: function(object) {
+ this.elem.appendChild(object._renderer.elem);
+ },
+
+ renderChild: function(child) {
+ svg[child._renderer.type].render.call(child, this);
+ },
+
+ render: function(domElement) {
+
+ this._update();
+
+ // Shortcut for hidden objects.
+ // Doesn't reset the flags, so changes are stored and
+ // applied once the object is visible again
+ if (this._opacity === 0 && !this._flagOpacity) {
+ return this;
+ }
+
+ if (!this._renderer.elem) {
+ this._renderer.elem = svg.createElement('g', {
+ id: this.id
+ });
+ domElement.appendChild(this._renderer.elem);
+ }
+
+ // _Update styles for the <g>
+ var flagMatrix = this._matrix.manual || this._flagMatrix;
+ var context = {
+ domElement: domElement,
+ elem: this._renderer.elem
+ };
+
+ if (flagMatrix) {
+ this._renderer.elem.setAttribute('transform', 'matrix(' + this._matrix.toString() + ')');
+ }
+
+ for (var i = 0; i < this.children.length; i++) {
+ var child = this.children[i];
+ svg[child._renderer.type].render.call(child, domElement);
+ }
+
+ if (this._flagOpacity) {
+ this._renderer.elem.setAttribute('opacity', this._opacity);
+ }
+
+ if (this._flagAdditions) {
+ this.additions.forEach(svg.group.appendChild, context);
+ }
+
+ if (this._flagSubtractions) {
+ this.subtractions.forEach(svg.group.removeChild, context);
+ }
+
+ if (this._flagOrder) {
+ this.children.forEach(svg.group.orderChild, context);
+ }
+
+ /**
+ * Commented two-way functionality of clips / masks with groups and
+ * polygons. Uncomment when this bug is fixed:
+ * https://code.google.com/p/chromium/issues/detail?id=370951
+ */
+
+ // if (this._flagClip) {
+
+ // clip = svg.getClip(this);
+ // elem = this._renderer.elem;
+
+ // if (this._clip) {
+ // elem.removeAttribute('id');
+ // clip.setAttribute('id', this.id);
+ // clip.appendChild(elem);
+ // } else {
+ // clip.removeAttribute('id');
+ // elem.setAttribute('id', this.id);
+ // this.parent._renderer.elem.appendChild(elem); // TODO: should be insertBefore
+ // }
+
+ // }
+
+ if (this._flagMask) {
+ if (this._mask) {
+ this._renderer.elem.setAttribute('clip-path', 'url(#' + this._mask.id + ')');
+ } else {
+ this._renderer.elem.removeAttribute('clip-path');
+ }
+ }
+
+ return this.flagReset();
+
+ }
+
+ },
+
+ path: {
+
+ render: function(domElement) {
+
+ this._update();
+
+ // Shortcut for hidden objects.
+ // Doesn't reset the flags, so changes are stored and
+ // applied once the object is visible again
+ if (this._opacity === 0 && !this._flagOpacity) {
+ return this;
+ }
+
+ // Collect any attribute that needs to be changed here
+ var changed = {};
+
+ var flagMatrix = this._matrix.manual || this._flagMatrix;
+
+ if (flagMatrix) {
+ changed.transform = 'matrix(' + this._matrix.toString() + ')';
+ }
+
+ if (this._flagVertices) {
+ var vertices = svg.toString(this._vertices, this._closed);
+ changed.d = vertices;
+ }
+
+ if (this._fill && this._fill._renderer) {
+ this._fill._update();
+ svg[this._fill._renderer.type].render.call(this._fill, domElement, true);
+ }
+
+ if (this._flagFill) {
+ changed.fill = this._fill && this._fill.id
+ ? 'url(#' + this._fill.id + ')' : this._fill;
+ }
+
+ if (this._stroke && this._stroke._renderer) {
+ this._stroke._update();
+ svg[this._stroke._renderer.type].render.call(this._stroke, domElement, true);
+ }
+
+ if (this._flagStroke) {
+ changed.stroke = this._stroke && this._stroke.id
+ ? 'url(#' + this._stroke.id + ')' : this._stroke;
+ }
+
+ if (this._flagLinewidth) {
+ changed['stroke-width'] = this._linewidth;
+ }
+
+ if (this._flagOpacity) {
+ changed['stroke-opacity'] = this._opacity;
+ changed['fill-opacity'] = this._opacity;
+ }
+
+ if (this._flagVisible) {
+ changed.visibility = this._visible ? 'visible' : 'hidden';
+ }
+
+ if (this._flagCap) {
+ changed['stroke-linecap'] = this._cap;
+ }
+
+ if (this._flagJoin) {
+ changed['stroke-linejoin'] = this._join;
+ }
+
+ if (this._flagMiter) {
+ changed['stroke-miterlimit'] = this._miter;
+ }
+
+ // If there is no attached DOM element yet,
+ // create it with all necessary attributes.
+ if (!this._renderer.elem) {
+
+ changed.id = this.id;
+ this._renderer.elem = svg.createElement('path', changed);
+ domElement.appendChild(this._renderer.elem);
+
+ // Otherwise apply all pending attributes
+ } else {
+ svg.setAttributes(this._renderer.elem, changed);
+ }
+
+ if (this._flagClip) {
+
+ var clip = svg.getClip(this);
+ var elem = this._renderer.elem;
+
+ if (this._clip) {
+ elem.removeAttribute('id');
+ clip.setAttribute('id', this.id);
+ clip.appendChild(elem);
+ } else {
+ clip.removeAttribute('id');
+ elem.setAttribute('id', this.id);
+ this.parent._renderer.elem.appendChild(elem); // TODO: should be insertBefore
+ }
+
+ }
+
+ /**
+ * Commented two-way functionality of clips / masks with groups and
+ * polygons. Uncomment when this bug is fixed:
+ * https://code.google.com/p/chromium/issues/detail?id=370951
+ */
+
+ // if (this._flagMask) {
+ // if (this._mask) {
+ // elem.setAttribute('clip-path', 'url(#' + this._mask.id + ')');
+ // } else {
+ // elem.removeAttribute('clip-path');
+ // }
+ // }
+
+ return this.flagReset();
+
+ }
+
+ },
+
+ text: {
+
+ render: function(domElement) {
+
+ this._update();
+
+ var changed = {};
+
+ var flagMatrix = this._matrix.manual || this._flagMatrix;
+
+ if (flagMatrix) {
+ changed.transform = 'matrix(' + this._matrix.toString() + ')';
+ }
+
+ if (this._flagFamily) {
+ changed['font-family'] = this._family;
+ }
+ if (this._flagSize) {
+ changed['font-size'] = this._size;
+ }
+ if (this._flagLeading) {
+ changed['line-height'] = this._leading;
+ }
+ if (this._flagAlignment) {
+ changed['text-anchor'] = svg.alignments[this._alignment] || this._alignment;
+ }
+ if (this._flagBaseline) {
+ changed['alignment-baseline'] = changed['dominant-baseline'] = this._baseline;
+ }
+ if (this._flagStyle) {
+ changed['font-style'] = this._style;
+ }
+ if (this._flagWeight) {
+ changed['font-weight'] = this._weight;
+ }
+ if (this._flagDecoration) {
+ changed['text-decoration'] = this._decoration;
+ }
+ if (this._fill && this._fill._renderer) {
+ this._fill._update();
+ svg[this._fill._renderer.type].render.call(this._fill, domElement, true);
+ }
+ if (this._flagFill) {
+ changed.fill = this._fill && this._fill.id
+ ? 'url(#' + this._fill.id + ')' : this._fill;
+ }
+ if (this._stroke && this._stroke._renderer) {
+ this._stroke._update();
+ svg[this._stroke._renderer.type].render.call(this._stroke, domElement, true);
+ }
+ if (this._flagStroke) {
+ changed.stroke = this._stroke && this._stroke.id
+ ? 'url(#' + this._stroke.id + ')' : this._stroke;
+ }
+ if (this._flagLinewidth) {
+ changed['stroke-width'] = this._linewidth;
+ }
+ if (this._flagOpacity) {
+ changed.opacity = this._opacity;
+ }
+ if (this._flagVisible) {
+ changed.visibility = this._visible ? 'visible' : 'hidden';
+ }
+
+ if (!this._renderer.elem) {
+
+ changed.id = this.id;
+
+ this._renderer.elem = svg.createElement('text', changed);
+ domElement.defs.appendChild(this._renderer.elem);
+
+ } else {
+
+ svg.setAttributes(this._renderer.elem, changed);
+
+ }
+
+ if (this._flagClip) {
+
+ var clip = svg.getClip(this);
+ var elem = this._renderer.elem;
+
+ if (this._clip) {
+ elem.removeAttribute('id');
+ clip.setAttribute('id', this.id);
+ clip.appendChild(elem);
+ } else {
+ clip.removeAttribute('id');
+ elem.setAttribute('id', this.id);
+ this.parent._renderer.elem.appendChild(elem); // TODO: should be insertBefore
+ }
+
+ }
+
+ if (this._flagValue) {
+ this._renderer.elem.textContent = this._value;
+ }
+
+ return this.flagReset();
+
+ }
+
+ },
+
+ 'linear-gradient': {
+
+ render: function(domElement, silent) {
+
+ if (!silent) {
+ this._update();
+ }
+
+ var changed = {};
+
+ if (this._flagEndPoints) {
+ changed.x1 = this.left._x;
+ changed.y1 = this.left._y;
+ changed.x2 = this.right._x;
+ changed.y2 = this.right._y;
+ }
+
+ if (this._flagSpread) {
+ changed.spreadMethod = this._spread;
+ }
+
+ // If there is no attached DOM element yet,
+ // create it with all necessary attributes.
+ if (!this._renderer.elem) {
+
+ changed.id = this.id;
+ changed.gradientUnits = 'userSpaceOnUse';
+ this._renderer.elem = svg.createElement('linearGradient', changed);
+ domElement.defs.appendChild(this._renderer.elem);
+
+ // Otherwise apply all pending attributes
+ } else {
+
+ svg.setAttributes(this._renderer.elem, changed);
+
+ }
+
+ if (this._flagStops) {
+
+ var lengthChanged = this._renderer.elem.childNodes.length
+ !== this.stops.length;
+
+ if (lengthChanged) {
+ this._renderer.elem.childNodes.length = 0;
+ }
+
+ for (var i = 0; i < this.stops.length; i++) {
+
+ var stop = this.stops[i];
+ var attrs = {};
+
+ if (stop._flagOffset) {
+ attrs.offset = 100 * stop._offset + '%';
+ }
+ if (stop._flagColor) {
+ attrs['stop-color'] = stop._color;
+ }
+ if (stop._flagOpacity) {
+ attrs['stop-opacity'] = stop._opacity;
+ }
+
+ if (!stop._renderer.elem) {
+ stop._renderer.elem = svg.createElement('stop', attrs);
+ } else {
+ svg.setAttributes(stop._renderer.elem, attrs);
+ }
+
+ if (lengthChanged) {
+ this._renderer.elem.appendChild(stop._renderer.elem);
+ }
+ stop.flagReset();
+
+ }
+
+ }
+
+ return this.flagReset();
+
+ }
+
+ },
+
+ 'radial-gradient': {
+
+ render: function(domElement, silent) {
+
+ if (!silent) {
+ this._update();
+ }
+
+ var changed = {};
+
+ if (this._flagCenter) {
+ changed.cx = this.center._x;
+ changed.cy = this.center._y;
+ }
+ if (this._flagFocal) {
+ changed.fx = this.focal._x;
+ changed.fy = this.focal._y;
+ }
+
+ if (this._flagRadius) {
+ changed.r = this._radius;
+ }
+
+ if (this._flagSpread) {
+ changed.spreadMethod = this._spread;
+ }
+
+ // If there is no attached DOM element yet,
+ // create it with all necessary attributes.
+ if (!this._renderer.elem) {
+
+ changed.id = this.id;
+ changed.gradientUnits = 'userSpaceOnUse';
+ this._renderer.elem = svg.createElement('radialGradient', changed);
+ domElement.defs.appendChild(this._renderer.elem);
+
+ // Otherwise apply all pending attributes
+ } else {
+
+ svg.setAttributes(this._renderer.elem, changed);
+
+ }
+
+ if (this._flagStops) {
+
+ var lengthChanged = this._renderer.elem.childNodes.length
+ !== this.stops.length;
+
+ if (lengthChanged) {
+ this._renderer.elem.childNodes.length = 0;
+ }
+
+ for (var i = 0; i < this.stops.length; i++) {
+
+ var stop = this.stops[i];
+ var attrs = {};
+
+ if (stop._flagOffset) {
+ attrs.offset = 100 * stop._offset + '%';
+ }
+ if (stop._flagColor) {
+ attrs['stop-color'] = stop._color;
+ }
+ if (stop._flagOpacity) {
+ attrs['stop-opacity'] = stop._opacity;
+ }
+
+ if (!stop._renderer.elem) {
+ stop._renderer.elem = svg.createElement('stop', attrs);
+ } else {
+ svg.setAttributes(stop._renderer.elem, attrs);
+ }
+
+ if (lengthChanged) {
+ this._renderer.elem.appendChild(stop._renderer.elem);
+ }
+ stop.flagReset();
+
+ }
+
+ }
+
+ return this.flagReset();
+
+ }
+
+ },
+
+ texture: {
+
+ render: function(domElement, silent) {
+
+ if (!silent) {
+ this._update();
+ }
+
+ var changed = {};
+ var styles = { x: 0, y: 0 };
+ var image = this.image;
+
+ if (this._flagLoaded && this.loaded) {
+
+ switch (image.nodeName.toLowerCase()) {
+
+ case 'canvas':
+ styles.href = styles['xlink:href'] = image.toDataURL('image/png');
+ break;
+ case 'img':
+ case 'image':
+ styles.href = styles['xlink:href'] = this.src;
+ break;
+
+ }
+
+ }
+
+ if (this._flagOffset || this._flagLoaded || this._flagScale) {
+
+ changed.x = this._offset.x;
+ changed.y = this._offset.y;
+
+ if (image) {
+
+ changed.x -= image.width / 2;
+ changed.y -= image.height / 2;
+
+ if (this._scale instanceof Two.Vector) {
+ changed.x *= this._scale.x;
+ changed.y *= this._scale.y;
+ } else {
+ changed.x *= this._scale;
+ changed.y *= this._scale;
+ }
+ }
+
+ if (changed.x > 0) {
+ changed.x *= - 1;
+ }
+ if (changed.y > 0) {
+ changed.y *= - 1;
+ }
+
+ }
+
+ if (this._flagScale || this._flagLoaded || this._flagRepeat) {
+
+ changed.width = 0;
+ changed.height = 0;
+
+ if (image) {
+
+ styles.width = changed.width = image.width;
+ styles.height = changed.height = image.height;
+
+ // TODO: Hack / Bandaid
+ switch (this._repeat) {
+ case 'no-repeat':
+ changed.width += 1;
+ changed.height += 1;
+ break;
+ }
+
+ if (this._scale instanceof Two.Vector) {
+ changed.width *= this._scale.x;
+ changed.height *= this._scale.y;
+ } else {
+ changed.width *= this._scale;
+ changed.height *= this._scale;
+ }
+ }
+
+ }
+
+ if (this._flagScale || this._flagLoaded) {
+ if (!this._renderer.image) {
+ this._renderer.image = svg.createElement('image', styles);
+ } else if (!_.isEmpty(styles)) {
+ svg.setAttributes(this._renderer.image, styles);
+ }
+ }
+
+ if (!this._renderer.elem) {
+
+ changed.id = this.id;
+ changed.patternUnits = 'userSpaceOnUse';
+ this._renderer.elem = svg.createElement('pattern', changed);
+ domElement.defs.appendChild(this._renderer.elem);
+
+ } else if (!_.isEmpty(changed)) {
+
+ svg.setAttributes(this._renderer.elem, changed);
+
+ }
+
+ if (this._renderer.elem && this._renderer.image && !this._renderer.appended) {
+ this._renderer.elem.appendChild(this._renderer.image);
+ this._renderer.appended = true;
+ }
+
+ return this.flagReset();
+
+ }
+
+ }
+
+ };
+
+ /**
+ * @class
+ */
+ var Renderer = Two[Two.Types.svg] = function(params) {
+
+ this.domElement = params.domElement || svg.createElement('svg');
+
+ this.scene = new Two.Group();
+ this.scene.parent = this;
+
+ this.defs = svg.createElement('defs');
+ this.domElement.appendChild(this.defs);
+ this.domElement.defs = this.defs;
+ this.domElement.style.overflow = 'hidden';
+
+ };
+
+ _.extend(Renderer, {
+
+ Utils: svg
+
+ });
+
+ _.extend(Renderer.prototype, Two.Utils.Events, {
+
+ setSize: function(width, height) {
+
+ this.width = width;
+ this.height = height;
+
+ svg.setAttributes(this.domElement, {
+ width: width,
+ height: height
+ });
+
+ return this;
+
+ },
+
+ render: function() {
+
+ svg.group.render.call(this.scene, this.domElement);
+
+ return this;
+
+ }
+
+ });
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ /**
+ * Constants
+ */
+ var mod = Two.Utils.mod, toFixed = Two.Utils.toFixed;
+ var getRatio = Two.Utils.getRatio;
+ var _ = Two.Utils;
+
+ // Returns true if this is a non-transforming matrix
+ var isDefaultMatrix = function (m) {
+ return (m[0] == 1 && m[3] == 0 && m[1] == 0 && m[4] == 1 && m[2] == 0 && m[5] == 0);
+ };
+
+ var canvas = {
+
+ isHidden: /(none|transparent)/i,
+
+ alignments: {
+ left: 'start',
+ middle: 'center',
+ right: 'end'
+ },
+
+ shim: function(elem) {
+ elem.tagName = 'canvas';
+ elem.nodeType = 1;
+ return elem;
+ },
+
+ group: {
+
+ renderChild: function(child) {
+ canvas[child._renderer.type].render.call(child, this.ctx, true, this.clip);
+ },
+
+ render: function(ctx) {
+
+ // TODO: Add a check here to only invoke _update if need be.
+ this._update();
+
+ var matrix = this._matrix.elements;
+ var parent = this.parent;
+ this._renderer.opacity = this._opacity * (parent && parent._renderer ? parent._renderer.opacity : 1);
+
+ var defaultMatrix = isDefaultMatrix(matrix);
+
+ var mask = this._mask;
+ // var clip = this._clip;
+
+ if (!this._renderer.context) {
+ this._renderer.context = {};
+ }
+
+ this._renderer.context.ctx = ctx;
+ // this._renderer.context.clip = clip;
+
+ if (!defaultMatrix) {
+ ctx.save();
+ ctx.transform(matrix[0], matrix[3], matrix[1], matrix[4], matrix[2], matrix[5]);
+ }
+
+ if (mask) {
+ canvas[mask._renderer.type].render.call(mask, ctx, true);
+ }
+
+ if (this.opacity > 0 && this.scale !== 0) {
+ for (var i = 0; i < this.children.length; i++) {
+ var child = this.children[i];
+ canvas[child._renderer.type].render.call(child, ctx);
+ }
+ }
+
+ if (!defaultMatrix) {
+ ctx.restore();
+ }
+
+ /**
+ * Commented two-way functionality of clips / masks with groups and
+ * polygons. Uncomment when this bug is fixed:
+ * https://code.google.com/p/chromium/issues/detail?id=370951
+ */
+
+ // if (clip) {
+ // ctx.clip();
+ // }
+
+ return this.flagReset();
+
+ }
+
+ },
+
+ path: {
+
+ render: function(ctx, forced, parentClipped) {
+
+ var matrix, stroke, linewidth, fill, opacity, visible, cap, join, miter,
+ closed, commands, length, last, next, prev, a, b, c, d, ux, uy, vx, vy,
+ ar, bl, br, cl, x, y, mask, clip, defaultMatrix, isOffset;
+
+ // TODO: Add a check here to only invoke _update if need be.
+ this._update();
+
+ matrix = this._matrix.elements;
+ stroke = this._stroke;
+ linewidth = this._linewidth;
+ fill = this._fill;
+ opacity = this._opacity * this.parent._renderer.opacity;
+ visible = this._visible;
+ cap = this._cap;
+ join = this._join;
+ miter = this._miter;
+ closed = this._closed;
+ commands = this._vertices; // Commands
+ length = commands.length;
+ last = length - 1;
+ defaultMatrix = isDefaultMatrix(matrix);
+
+ // mask = this._mask;
+ clip = this._clip;
+
+ if (!forced && (!visible || clip)) {
+ return this;
+ }
+
+ // Transform
+ if (!defaultMatrix) {
+ ctx.save();
+ ctx.transform(matrix[0], matrix[3], matrix[1], matrix[4], matrix[2], matrix[5]);
+ }
+
+ /**
+ * Commented two-way functionality of clips / masks with groups and
+ * polygons. Uncomment when this bug is fixed:
+ * https://code.google.com/p/chromium/issues/detail?id=370951
+ */
+
+ // if (mask) {
+ // canvas[mask._renderer.type].render.call(mask, ctx, true);
+ // }
+
+ // Styles
+ if (fill) {
+ if (_.isString(fill)) {
+ ctx.fillStyle = fill;
+ } else {
+ canvas[fill._renderer.type].render.call(fill, ctx);
+ ctx.fillStyle = fill._renderer.effect;
+ }
+ }
+ if (stroke) {
+ if (_.isString(stroke)) {
+ ctx.strokeStyle = stroke;
+ } else {
+ canvas[stroke._renderer.type].render.call(stroke, ctx);
+ ctx.strokeStyle = stroke._renderer.effect;
+ }
+ }
+ if (linewidth) {
+ ctx.lineWidth = linewidth;
+ }
+ if (miter) {
+ ctx.miterLimit = miter;
+ }
+ if (join) {
+ ctx.lineJoin = join;
+ }
+ if (cap) {
+ ctx.lineCap = cap;
+ }
+ if (_.isNumber(opacity)) {
+ ctx.globalAlpha = opacity;
+ }
+
+ ctx.beginPath();
+
+ for (var i = 0; i < commands.length; i++) {
+
+ b = commands[i];
+
+ x = toFixed(b._x);
+ y = toFixed(b._y);
+
+ switch (b._command) {
+
+ case Two.Commands.close:
+ ctx.closePath();
+ break;
+
+ case Two.Commands.curve:
+
+ prev = closed ? mod(i - 1, length) : Math.max(i - 1, 0);
+ next = closed ? mod(i + 1, length) : Math.min(i + 1, last);
+
+ a = commands[prev];
+ c = commands[next];
+ ar = (a.controls && a.controls.right) || Two.Vector.zero;
+ bl = (b.controls && b.controls.left) || Two.Vector.zero;
+
+ if (a._relative) {
+ vx = (ar.x + toFixed(a._x));
+ vy = (ar.y + toFixed(a._y));
+ } else {
+ vx = toFixed(ar.x);
+ vy = toFixed(ar.y);
+ }
+
+ if (b._relative) {
+ ux = (bl.x + toFixed(b._x));
+ uy = (bl.y + toFixed(b._y));
+ } else {
+ ux = toFixed(bl.x);
+ uy = toFixed(bl.y);
+ }
+
+ ctx.bezierCurveTo(vx, vy, ux, uy, x, y);
+
+ if (i >= last && closed) {
+
+ c = d;
+
+ br = (b.controls && b.controls.right) || Two.Vector.zero;
+ cl = (c.controls && c.controls.left) || Two.Vector.zero;
+
+ if (b._relative) {
+ vx = (br.x + toFixed(b._x));
+ vy = (br.y + toFixed(b._y));
+ } else {
+ vx = toFixed(br.x);
+ vy = toFixed(br.y);
+ }
+
+ if (c._relative) {
+ ux = (cl.x + toFixed(c._x));
+ uy = (cl.y + toFixed(c._y));
+ } else {
+ ux = toFixed(cl.x);
+ uy = toFixed(cl.y);
+ }
+
+ x = toFixed(c._x);
+ y = toFixed(c._y);
+
+ ctx.bezierCurveTo(vx, vy, ux, uy, x, y);
+
+ }
+
+ break;
+
+ case Two.Commands.line:
+ ctx.lineTo(x, y);
+ break;
+
+ case Two.Commands.move:
+ d = b;
+ ctx.moveTo(x, y);
+ break;
+
+ }
+ }
+
+ // Loose ends
+
+ if (closed) {
+ ctx.closePath();
+ }
+
+ if (!clip && !parentClipped) {
+ if (!canvas.isHidden.test(fill)) {
+ isOffset = fill._renderer && fill._renderer.offset
+ if (isOffset) {
+ ctx.save();
+ ctx.translate(
+ - fill._renderer.offset.x, - fill._renderer.offset.y);
+ ctx.scale(fill._renderer.scale.x, fill._renderer.scale.y);
+ }
+ ctx.fill();
+ if (isOffset) {
+ ctx.restore();
+ }
+ }
+ if (!canvas.isHidden.test(stroke)) {
+ isOffset = stroke._renderer && stroke._renderer.offset;
+ if (isOffset) {
+ ctx.save();
+ ctx.translate(
+ - stroke._renderer.offset.x, - stroke._renderer.offset.y);
+ ctx.scale(stroke._renderer.scale.x, stroke._renderer.scale.y);
+ ctx.lineWidth = linewidth / stroke._renderer.scale.x;
+ }
+ ctx.stroke();
+ if (isOffset) {
+ ctx.restore();
+ }
+ }
+ }
+
+ if (!defaultMatrix) {
+ ctx.restore();
+ }
+
+ if (clip && !parentClipped) {
+ ctx.clip();
+ }
+
+ return this.flagReset();
+
+ }
+
+ },
+
+ text: {
+
+ render: function(ctx, forced, parentClipped) {
+
+ // TODO: Add a check here to only invoke _update if need be.
+ this._update();
+
+ var matrix = this._matrix.elements;
+ var stroke = this._stroke;
+ var linewidth = this._linewidth;
+ var fill = this._fill;
+ var opacity = this._opacity * this.parent._renderer.opacity;
+ var visible = this._visible;
+ var defaultMatrix = isDefaultMatrix(matrix);
+ var isOffset = fill._renderer && fill._renderer.offset
+ && stroke._renderer && stroke._renderer.offset;
+
+ var a, b, c, d, e, sx, sy;
+
+ // mask = this._mask;
+ var clip = this._clip;
+
+ if (!forced && (!visible || clip)) {
+ return this;
+ }
+
+ // Transform
+ if (!defaultMatrix) {
+ ctx.save();
+ ctx.transform(matrix[0], matrix[3], matrix[1], matrix[4], matrix[2], matrix[5]);
+ }
+
+ /**
+ * Commented two-way functionality of clips / masks with groups and
+ * polygons. Uncomment when this bug is fixed:
+ * https://code.google.com/p/chromium/issues/detail?id=370951
+ */
+
+ // if (mask) {
+ // canvas[mask._renderer.type].render.call(mask, ctx, true);
+ // }
+
+ if (!isOffset) {
+ ctx.font = [this._style, this._weight, this._size + 'px/' +
+ this._leading + 'px', this._family].join(' ');
+ }
+
+ ctx.textAlign = canvas.alignments[this._alignment] || this._alignment;
+ ctx.textBaseline = this._baseline;
+
+ // Styles
+ if (fill) {
+ if (_.isString(fill)) {
+ ctx.fillStyle = fill;
+ } else {
+ canvas[fill._renderer.type].render.call(fill, ctx);
+ ctx.fillStyle = fill._renderer.effect;
+ }
+ }
+ if (stroke) {
+ if (_.isString(stroke)) {
+ ctx.strokeStyle = stroke;
+ } else {
+ canvas[stroke._renderer.type].render.call(stroke, ctx);
+ ctx.strokeStyle = stroke._renderer.effect;
+ }
+ }
+ if (linewidth) {
+ ctx.lineWidth = linewidth;
+ }
+ if (_.isNumber(opacity)) {
+ ctx.globalAlpha = opacity;
+ }
+
+ if (!clip && !parentClipped) {
+
+ if (!canvas.isHidden.test(fill)) {
+
+ if (fill._renderer && fill._renderer.offset) {
+
+ sx = toFixed(fill._renderer.scale.x);
+ sy = toFixed(fill._renderer.scale.y);
+
+ ctx.save();
+ ctx.translate( - toFixed(fill._renderer.offset.x),
+ - toFixed(fill._renderer.offset.y));
+ ctx.scale(sx, sy);
+
+ a = this._size / fill._renderer.scale.y;
+ b = this._leading / fill._renderer.scale.y;
+ ctx.font = [this._style, this._weight, toFixed(a) + 'px/',
+ toFixed(b) + 'px', this._family].join(' ');
+
+ c = fill._renderer.offset.x / fill._renderer.scale.x;
+ d = fill._renderer.offset.y / fill._renderer.scale.y;
+
+ ctx.fillText(this.value, toFixed(c), toFixed(d));
+ ctx.restore();
+
+ } else {
+ ctx.fillText(this.value, 0, 0);
+ }
+
+ }
+
+ if (!canvas.isHidden.test(stroke)) {
+
+ if (stroke._renderer && stroke._renderer.offset) {
+
+ sx = toFixed(stroke._renderer.scale.x);
+ sy = toFixed(stroke._renderer.scale.y);
+
+ ctx.save();
+ ctx.translate(- toFixed(stroke._renderer.offset.x),
+ - toFixed(stroke._renderer.offset.y));
+ ctx.scale(sx, sy);
+
+ a = this._size / stroke._renderer.scale.y;
+ b = this._leading / stroke._renderer.scale.y;
+ ctx.font = [this._style, this._weight, toFixed(a) + 'px/',
+ toFixed(b) + 'px', this._family].join(' ');
+
+ c = stroke._renderer.offset.x / stroke._renderer.scale.x;
+ d = stroke._renderer.offset.y / stroke._renderer.scale.y;
+ e = linewidth / stroke._renderer.scale.x;
+
+ ctx.lineWidth = toFixed(e);
+ ctx.strokeText(this.value, toFixed(c), toFixed(d));
+ ctx.restore();
+
+ } else {
+ ctx.strokeText(this.value, 0, 0);
+ }
+ }
+ }
+
+ if (!defaultMatrix) {
+ ctx.restore();
+ }
+
+ // TODO: Test for text
+ if (clip && !parentClipped) {
+ ctx.clip();
+ }
+
+ return this.flagReset();
+
+ }
+
+ },
+
+ 'linear-gradient': {
+
+ render: function(ctx) {
+
+ this._update();
+
+ if (!this._renderer.effect || this._flagEndPoints || this._flagStops) {
+
+ this._renderer.effect = ctx.createLinearGradient(
+ this.left._x, this.left._y,
+ this.right._x, this.right._y
+ );
+
+ for (var i = 0; i < this.stops.length; i++) {
+ var stop = this.stops[i];
+ this._renderer.effect.addColorStop(stop._offset, stop._color);
+ }
+
+ }
+
+ return this.flagReset();
+
+ }
+
+ },
+
+ 'radial-gradient': {
+
+ render: function(ctx) {
+
+ this._update();
+
+ if (!this._renderer.effect || this._flagCenter || this._flagFocal
+ || this._flagRadius || this._flagStops) {
+
+ this._renderer.effect = ctx.createRadialGradient(
+ this.center._x, this.center._y, 0,
+ this.focal._x, this.focal._y, this._radius
+ );
+
+ for (var i = 0; i < this.stops.length; i++) {
+ var stop = this.stops[i];
+ this._renderer.effect.addColorStop(stop._offset, stop._color);
+ }
+
+ }
+
+ return this.flagReset();
+
+ }
+
+ },
+
+ texture: {
+
+ render: function(ctx) {
+
+ this._update();
+
+ var image = this.image;
+ var repeat;
+
+ if (!this._renderer.effect || ((this._flagLoaded || this._flagImage || this._flagVideo || this._flagRepeat) && this.loaded)) {
+ this._renderer.effect = ctx.createPattern(this.image, this._repeat);
+ }
+
+ if (this._flagOffset || this._flagLoaded || this._flagScale) {
+
+ if (!(this._renderer.offset instanceof Two.Vector)) {
+ this._renderer.offset = new Two.Vector();
+ }
+
+ this._renderer.offset.x = - this._offset.x;
+ this._renderer.offset.y = - this._offset.y;
+
+ if (image) {
+
+ this._renderer.offset.x += image.width / 2;
+ this._renderer.offset.y += image.height / 2;
+
+ if (this._scale instanceof Two.Vector) {
+ this._renderer.offset.x *= this._scale.x;
+ this._renderer.offset.y *= this._scale.y;
+ } else {
+ this._renderer.offset.x *= this._scale;
+ this._renderer.offset.y *= this._scale;
+ }
+ }
+
+ }
+
+ if (this._flagScale || this._flagLoaded) {
+
+ if (!(this._renderer.scale instanceof Two.Vector)) {
+ this._renderer.scale = new Two.Vector();
+ }
+
+ if (this._scale instanceof Two.Vector) {
+ this._renderer.scale.copy(this._scale);
+ } else {
+ this._renderer.scale.set(this._scale, this._scale);
+ }
+
+ }
+
+ return this.flagReset();
+
+ }
+
+ }
+
+ };
+
+ var Renderer = Two[Two.Types.canvas] = function(params) {
+ // Smoothing property. Defaults to true
+ // Set it to false when working with pixel art.
+ // false can lead to better performance, since it would use a cheaper interpolation algorithm.
+ // It might not make a big difference on GPU backed canvases.
+ var smoothing = (params.smoothing !== false);
+ this.domElement = params.domElement || document.createElement('canvas');
+ this.ctx = this.domElement.getContext('2d');
+ this.overdraw = params.overdraw || false;
+
+ if (!_.isUndefined(this.ctx.imageSmoothingEnabled)) {
+ this.ctx.imageSmoothingEnabled = smoothing;
+ }
+
+ // Everything drawn on the canvas needs to be added to the scene.
+ this.scene = new Two.Group();
+ this.scene.parent = this;
+ };
+
+
+ _.extend(Renderer, {
+
+ Utils: canvas
+
+ });
+
+ _.extend(Renderer.prototype, Two.Utils.Events, {
+
+ setSize: function(width, height, ratio) {
+
+ this.width = width;
+ this.height = height;
+
+ this.ratio = _.isUndefined(ratio) ? getRatio(this.ctx) : ratio;
+
+ this.domElement.width = width * this.ratio;
+ this.domElement.height = height * this.ratio;
+
+ if (this.domElement.style) {
+ _.extend(this.domElement.style, {
+ width: width + 'px',
+ height: height + 'px'
+ });
+ }
+
+ return this;
+
+ },
+
+ render: function() {
+
+ var isOne = this.ratio === 1;
+
+ if (!isOne) {
+ this.ctx.save();
+ this.ctx.scale(this.ratio, this.ratio);
+ }
+
+ if (!this.overdraw) {
+ this.ctx.clearRect(0, 0, this.width, this.height);
+ }
+
+ canvas.group.render.call(this.scene, this.ctx);
+
+ if (!isOne) {
+ this.ctx.restore();
+ }
+
+ return this;
+
+ }
+
+ });
+
+ function resetTransform(ctx) {
+ ctx.setTransform(1, 0, 0, 1, 0, 0);
+ }
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ /**
+ * Constants
+ */
+
+ var root = Two.root,
+ multiplyMatrix = Two.Matrix.Multiply,
+ mod = Two.Utils.mod,
+ identity = [1, 0, 0, 0, 1, 0, 0, 0, 1],
+ transformation = new Two.Array(9),
+ getRatio = Two.Utils.getRatio,
+ getComputedMatrix = Two.Utils.getComputedMatrix,
+ toFixed = Two.Utils.toFixed,
+ _ = Two.Utils;
+
+ var webgl = {
+
+ isHidden: /(none|transparent)/i,
+
+ canvas: (root.document ? root.document.createElement('canvas') : { getContext: _.identity }),
+
+ alignments: {
+ left: 'start',
+ middle: 'center',
+ right: 'end'
+ },
+
+ matrix: new Two.Matrix(),
+
+ uv: new Two.Array([
+ 0, 0,
+ 1, 0,
+ 0, 1,
+ 0, 1,
+ 1, 0,
+ 1, 1
+ ]),
+
+ group: {
+
+ removeChild: function(child, gl) {
+ if (child.children) {
+ for (var i = 0; i < child.children.length; i++) {
+ webgl.group.removeChild(child.children[i], gl);
+ }
+ return;
+ }
+ // Deallocate texture to free up gl memory.
+ gl.deleteTexture(child._renderer.texture);
+ delete child._renderer.texture;
+ },
+
+ renderChild: function(child) {
+ webgl[child._renderer.type].render.call(child, this.gl, this.program);
+ },
+
+ render: function(gl, program) {
+
+ this._update();
+
+ var parent = this.parent;
+ var flagParentMatrix = (parent._matrix && parent._matrix.manual) || parent._flagMatrix;
+ var flagMatrix = this._matrix.manual || this._flagMatrix;
+
+ if (flagParentMatrix || flagMatrix) {
+
+ if (!this._renderer.matrix) {
+ this._renderer.matrix = new Two.Array(9);
+ }
+
+ // Reduce amount of object / array creation / deletion
+ this._matrix.toArray(true, transformation);
+
+ multiplyMatrix(transformation, parent._renderer.matrix, this._renderer.matrix);
+ this._renderer.scale = this._scale * parent._renderer.scale;
+
+ if (flagParentMatrix) {
+ this._flagMatrix = true;
+ }
+
+ }
+
+ if (this._mask) {
+
+ gl.enable(gl.STENCIL_TEST);
+ gl.stencilFunc(gl.ALWAYS, 1, 1);
+
+ gl.colorMask(false, false, false, true);
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR);
+
+ webgl[this._mask._renderer.type].render.call(this._mask, gl, program, this);
+
+ gl.colorMask(true, true, true, true);
+ gl.stencilFunc(gl.NOTEQUAL, 0, 1);
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
+
+ }
+
+ this._flagOpacity = parent._flagOpacity || this._flagOpacity;
+
+ this._renderer.opacity = this._opacity
+ * (parent && parent._renderer ? parent._renderer.opacity : 1);
+
+ if (this._flagSubtractions) {
+ for (var i = 0; i < this.subtractions.length; i++) {
+ webgl.group.removeChild(this.subtractions[i], gl);
+ }
+ }
+
+ this.children.forEach(webgl.group.renderChild, {
+ gl: gl,
+ program: program
+ });
+
+ if (this._mask) {
+
+ gl.colorMask(false, false, false, false);
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR);
+
+ webgl[this._mask._renderer.type].render.call(this._mask, gl, program, this);
+
+ gl.colorMask(true, true, true, true);
+ gl.stencilFunc(gl.NOTEQUAL, 0, 1);
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
+
+ gl.disable(gl.STENCIL_TEST);
+
+ }
+
+ return this.flagReset();
+
+ }
+
+ },
+
+ path: {
+
+ updateCanvas: function(elem) {
+
+ var next, prev, a, c, ux, uy, vx, vy, ar, bl, br, cl, x, y;
+ var isOffset;
+
+ var commands = elem._vertices;
+ var canvas = this.canvas;
+ var ctx = this.ctx;
+
+ // Styles
+ var scale = elem._renderer.scale;
+ var stroke = elem._stroke;
+ var linewidth = elem._linewidth;
+ var fill = elem._fill;
+ var opacity = elem._renderer.opacity || elem._opacity;
+ var cap = elem._cap;
+ var join = elem._join;
+ var miter = elem._miter;
+ var closed = elem._closed;
+ var length = commands.length;
+ var last = length - 1;
+
+ canvas.width = Math.max(Math.ceil(elem._renderer.rect.width * scale), 1);
+ canvas.height = Math.max(Math.ceil(elem._renderer.rect.height * scale), 1);
+
+ var centroid = elem._renderer.rect.centroid;
+ var cx = centroid.x;
+ var cy = centroid.y;
+
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+
+ if (fill) {
+ if (_.isString(fill)) {
+ ctx.fillStyle = fill;
+ } else {
+ webgl[fill._renderer.type].render.call(fill, ctx, elem);
+ ctx.fillStyle = fill._renderer.effect;
+ }
+ }
+ if (stroke) {
+ if (_.isString(stroke)) {
+ ctx.strokeStyle = stroke;
+ } else {
+ webgl[stroke._renderer.type].render.call(stroke, ctx, elem);
+ ctx.strokeStyle = stroke._renderer.effect;
+ }
+ }
+ if (linewidth) {
+ ctx.lineWidth = linewidth;
+ }
+ if (miter) {
+ ctx.miterLimit = miter;
+ }
+ if (join) {
+ ctx.lineJoin = join;
+ }
+ if (cap) {
+ ctx.lineCap = cap;
+ }
+ if (_.isNumber(opacity)) {
+ ctx.globalAlpha = opacity;
+ }
+
+ var d;
+ ctx.save();
+ ctx.scale(scale, scale);
+ ctx.translate(cx, cy);
+
+ ctx.beginPath();
+ for (var i = 0; i < commands.length; i++) {
+
+ b = commands[i];
+
+ x = toFixed(b._x);
+ y = toFixed(b._y);
+
+ switch (b._command) {
+
+ case Two.Commands.close:
+ ctx.closePath();
+ break;
+
+ case Two.Commands.curve:
+
+ prev = closed ? mod(i - 1, length) : Math.max(i - 1, 0);
+ next = closed ? mod(i + 1, length) : Math.min(i + 1, last);
+
+ a = commands[prev];
+ c = commands[next];
+ ar = (a.controls && a.controls.right) || Two.Vector.zero;
+ bl = (b.controls && b.controls.left) || Two.Vector.zero;
+
+ if (a._relative) {
+ vx = toFixed((ar.x + a._x));
+ vy = toFixed((ar.y + a._y));
+ } else {
+ vx = toFixed(ar.x);
+ vy = toFixed(ar.y);
+ }
+
+ if (b._relative) {
+ ux = toFixed((bl.x + b._x));
+ uy = toFixed((bl.y + b._y));
+ } else {
+ ux = toFixed(bl.x);
+ uy = toFixed(bl.y);
+ }
+
+ ctx.bezierCurveTo(vx, vy, ux, uy, x, y);
+
+ if (i >= last && closed) {
+
+ c = d;
+
+ br = (b.controls && b.controls.right) || Two.Vector.zero;
+ cl = (c.controls && c.controls.left) || Two.Vector.zero;
+
+ if (b._relative) {
+ vx = toFixed((br.x + b._x));
+ vy = toFixed((br.y + b._y));
+ } else {
+ vx = toFixed(br.x);
+ vy = toFixed(br.y);
+ }
+
+ if (c._relative) {
+ ux = toFixed((cl.x + c._x));
+ uy = toFixed((cl.y + c._y));
+ } else {
+ ux = toFixed(cl.x);
+ uy = toFixed(cl.y);
+ }
+
+ x = toFixed(c._x);
+ y = toFixed(c._y);
+
+ ctx.bezierCurveTo(vx, vy, ux, uy, x, y);
+
+ }
+
+ break;
+
+ case Two.Commands.line:
+ ctx.lineTo(x, y);
+ break;
+
+ case Two.Commands.move:
+ d = b;
+ ctx.moveTo(x, y);
+ break;
+
+ }
+
+ }
+
+ // Loose ends
+
+ if (closed) {
+ ctx.closePath();
+ }
+
+ if (!webgl.isHidden.test(fill)) {
+ isOffset = fill._renderer && fill._renderer.offset
+ if (isOffset) {
+ ctx.save();
+ ctx.translate(
+ - fill._renderer.offset.x, - fill._renderer.offset.y);
+ ctx.scale(fill._renderer.scale.x, fill._renderer.scale.y);
+ }
+ ctx.fill();
+ if (isOffset) {
+ ctx.restore();
+ }
+ }
+
+ if (!webgl.isHidden.test(stroke)) {
+ isOffset = stroke._renderer && stroke._renderer.offset;
+ if (isOffset) {
+ ctx.save();
+ ctx.translate(
+ - stroke._renderer.offset.x, - stroke._renderer.offset.y);
+ ctx.scale(stroke._renderer.scale.x, stroke._renderer.scale.y);
+ ctx.lineWidth = linewidth / stroke._renderer.scale.x;
+ }
+ ctx.stroke();
+ if (isOffset) {
+ ctx.restore();
+ }
+ }
+
+ ctx.restore();
+
+ },
+
+ /**
+ * Returns the rect of a set of verts. Typically takes vertices that are
+ * "centered" around 0 and returns them to be anchored upper-left.
+ */
+ getBoundingClientRect: function(vertices, border, rect) {
+
+ var left = Infinity, right = -Infinity,
+ top = Infinity, bottom = -Infinity,
+ width, height;
+
+ vertices.forEach(function(v) {
+
+ var x = v.x, y = v.y, controls = v.controls;
+ var a, b, c, d, cl, cr;
+
+ top = Math.min(y, top);
+ left = Math.min(x, left);
+ right = Math.max(x, right);
+ bottom = Math.max(y, bottom);
+
+ if (!v.controls) {
+ return;
+ }
+
+ cl = controls.left;
+ cr = controls.right;
+
+ if (!cl || !cr) {
+ return;
+ }
+
+ a = v._relative ? cl.x + x : cl.x;
+ b = v._relative ? cl.y + y : cl.y;
+ c = v._relative ? cr.x + x : cr.x;
+ d = v._relative ? cr.y + y : cr.y;
+
+ if (!a || !b || !c || !d) {
+ return;
+ }
+
+ top = Math.min(b, d, top);
+ left = Math.min(a, c, left);
+ right = Math.max(a, c, right);
+ bottom = Math.max(b, d, bottom);
+
+ });
+
+ // Expand borders
+
+ if (_.isNumber(border)) {
+ top -= border;
+ left -= border;
+ right += border;
+ bottom += border;
+ }
+
+ width = right - left;
+ height = bottom - top;
+
+ rect.top = top;
+ rect.left = left;
+ rect.right = right;
+ rect.bottom = bottom;
+ rect.width = width;
+ rect.height = height;
+
+ if (!rect.centroid) {
+ rect.centroid = {};
+ }
+
+ rect.centroid.x = - left;
+ rect.centroid.y = - top;
+
+ },
+
+ render: function(gl, program, forcedParent) {
+
+ if (!this._visible || !this._opacity) {
+ return this;
+ }
+
+ this._update();
+
+ // Calculate what changed
+
+ var parent = this.parent;
+ var flagParentMatrix = parent._matrix.manual || parent._flagMatrix;
+ var flagMatrix = this._matrix.manual || this._flagMatrix;
+ var flagTexture = this._flagVertices || this._flagFill
+ || (this._fill instanceof Two.LinearGradient && (this._fill._flagSpread || this._fill._flagStops || this._fill._flagEndPoints))
+ || (this._fill instanceof Two.RadialGradient && (this._fill._flagSpread || this._fill._flagStops || this._fill._flagRadius || this._fill._flagCenter || this._fill._flagFocal))
+ || (this._fill instanceof Two.Texture && (this._fill._flagLoaded && this._fill.loaded || this._fill._flagOffset || this._fill._flagScale))
+ || (this._stroke instanceof Two.LinearGradient && (this._stroke._flagSpread || this._stroke._flagStops || this._stroke._flagEndPoints))
+ || (this._stroke instanceof Two.RadialGradient && (this._stroke._flagSpread || this._stroke._flagStops || this._stroke._flagRadius || this._stroke._flagCenter || this._stroke._flagFocal))
+ || (this._stroke instanceof Two.Texture && (this._stroke._flagLoaded && this._stroke.loaded || this._stroke._flagOffset || this._fill._flagScale))
+ || this._flagStroke || this._flagLinewidth || this._flagOpacity
+ || parent._flagOpacity || this._flagVisible || this._flagCap
+ || this._flagJoin || this._flagMiter || this._flagScale
+ || !this._renderer.texture;
+
+ if (flagParentMatrix || flagMatrix) {
+
+ if (!this._renderer.matrix) {
+ this._renderer.matrix = new Two.Array(9);
+ }
+
+ // Reduce amount of object / array creation / deletion
+
+ this._matrix.toArray(true, transformation);
+
+ multiplyMatrix(transformation, parent._renderer.matrix, this._renderer.matrix);
+ this._renderer.scale = this._scale * parent._renderer.scale;
+
+ }
+
+ if (flagTexture) {
+
+ if (!this._renderer.rect) {
+ this._renderer.rect = {};
+ }
+
+ if (!this._renderer.triangles) {
+ this._renderer.triangles = new Two.Array(12);
+ }
+
+ this._renderer.opacity = this._opacity * parent._renderer.opacity;
+
+ webgl.path.getBoundingClientRect(this._vertices, this._linewidth, this._renderer.rect);
+ webgl.getTriangles(this._renderer.rect, this._renderer.triangles);
+
+ webgl.updateBuffer.call(webgl, gl, this, program);
+ webgl.updateTexture.call(webgl, gl, this);
+
+ }
+
+ // if (this._mask) {
+ // webgl[this._mask._renderer.type].render.call(mask, gl, program, this);
+ // }
+
+ if (this._clip && !forcedParent) {
+ return;
+ }
+
+ // Draw Texture
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._renderer.textureCoordsBuffer);
+
+ gl.vertexAttribPointer(program.textureCoords, 2, gl.FLOAT, false, 0, 0);
+
+ gl.bindTexture(gl.TEXTURE_2D, this._renderer.texture);
+
+
+ // Draw Rect
+
+ gl.uniformMatrix3fv(program.matrix, false, this._renderer.matrix);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._renderer.buffer);
+
+ gl.vertexAttribPointer(program.position, 2, gl.FLOAT, false, 0, 0);
+
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ return this.flagReset();
+
+ }
+
+ },
+
+ text: {
+
+ updateCanvas: function(elem) {
+
+ var canvas = this.canvas;
+ var ctx = this.ctx;
+
+ // Styles
+ var scale = elem._renderer.scale;
+ var stroke = elem._stroke;
+ var linewidth = elem._linewidth * scale;
+ var fill = elem._fill;
+ var opacity = elem._renderer.opacity || elem._opacity;
+
+ canvas.width = Math.max(Math.ceil(elem._renderer.rect.width * scale), 1);
+ canvas.height = Math.max(Math.ceil(elem._renderer.rect.height * scale), 1);
+
+ var centroid = elem._renderer.rect.centroid;
+ var cx = centroid.x;
+ var cy = centroid.y;
+
+ var a, b, c, d, e, sx, sy;
+ var isOffset = fill._renderer && fill._renderer.offset
+ && stroke._renderer && stroke._renderer.offset;
+
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+
+ if (!isOffset) {
+ ctx.font = [elem._style, elem._weight, elem._size + 'px/' +
+ elem._leading + 'px', elem._family].join(' ');
+ }
+
+ ctx.textAlign = 'center';
+ ctx.textBaseline = 'middle';
+
+ // Styles
+ if (fill) {
+ if (_.isString(fill)) {
+ ctx.fillStyle = fill;
+ } else {
+ webgl[fill._renderer.type].render.call(fill, ctx, elem);
+ ctx.fillStyle = fill._renderer.effect;
+ }
+ }
+ if (stroke) {
+ if (_.isString(stroke)) {
+ ctx.strokeStyle = stroke;
+ } else {
+ webgl[stroke._renderer.type].render.call(stroke, ctx, elem);
+ ctx.strokeStyle = stroke._renderer.effect;
+ }
+ }
+ if (linewidth) {
+ ctx.lineWidth = linewidth;
+ }
+ if (_.isNumber(opacity)) {
+ ctx.globalAlpha = opacity;
+ }
+
+ ctx.save();
+ ctx.scale(scale, scale);
+ ctx.translate(cx, cy);
+
+ if (!webgl.isHidden.test(fill)) {
+
+ if (fill._renderer && fill._renderer.offset) {
+
+ sx = toFixed(fill._renderer.scale.x);
+ sy = toFixed(fill._renderer.scale.y);
+
+ ctx.save();
+ ctx.translate( - toFixed(fill._renderer.offset.x),
+ - toFixed(fill._renderer.offset.y));
+ ctx.scale(sx, sy);
+
+ a = elem._size / fill._renderer.scale.y;
+ b = elem._leading / fill._renderer.scale.y;
+ ctx.font = [elem._style, elem._weight, toFixed(a) + 'px/',
+ toFixed(b) + 'px', elem._family].join(' ');
+
+ c = fill._renderer.offset.x / fill._renderer.scale.x;
+ d = fill._renderer.offset.y / fill._renderer.scale.y;
+
+ ctx.fillText(elem.value, toFixed(c), toFixed(d));
+ ctx.restore();
+
+ } else {
+ ctx.fillText(elem.value, 0, 0);
+ }
+
+ }
+
+ if (!webgl.isHidden.test(stroke)) {
+
+ if (stroke._renderer && stroke._renderer.offset) {
+
+ sx = toFixed(stroke._renderer.scale.x);
+ sy = toFixed(stroke._renderer.scale.y);
+
+ ctx.save();
+ ctx.translate(- toFixed(stroke._renderer.offset.x),
+ - toFixed(stroke._renderer.offset.y));
+ ctx.scale(sx, sy);
+
+ a = elem._size / stroke._renderer.scale.y;
+ b = elem._leading / stroke._renderer.scale.y;
+ ctx.font = [elem._style, elem._weight, toFixed(a) + 'px/',
+ toFixed(b) + 'px', elem._family].join(' ');
+
+ c = stroke._renderer.offset.x / stroke._renderer.scale.x;
+ d = stroke._renderer.offset.y / stroke._renderer.scale.y;
+ e = linewidth / stroke._renderer.scale.x;
+
+ ctx.lineWidth = toFixed(e);
+ ctx.strokeText(elem.value, toFixed(c), toFixed(d));
+ ctx.restore();
+
+ } else {
+ ctx.strokeText(elem.value, 0, 0);
+ }
+
+ }
+
+ ctx.restore();
+
+ },
+
+ getBoundingClientRect: function(elem, rect) {
+
+ var ctx = webgl.ctx;
+
+ ctx.font = [elem._style, elem._weight, elem._size + 'px/' +
+ elem._leading + 'px', elem._family].join(' ');
+
+ ctx.textAlign = 'center';
+ ctx.textBaseline = elem._baseline;
+
+ // TODO: Estimate this better
+ var width = ctx.measureText(elem._value).width;
+ var height = Math.max(elem._size || elem._leading);
+
+ if (this._linewidth && !webgl.isHidden.test(this._stroke)) {
+ // width += this._linewidth; // TODO: Not sure if the `measure` calcs this.
+ height += this._linewidth;
+ }
+
+ var w = width / 2;
+ var h = height / 2;
+
+ switch (webgl.alignments[elem._alignment] || elem._alignment) {
+
+ case webgl.alignments.left:
+ rect.left = 0;
+ rect.right = width;
+ break;
+ case webgl.alignments.right:
+ rect.left = - width;
+ rect.right = 0;
+ break;
+ default:
+ rect.left = - w;
+ rect.right = w;
+ }
+
+ // TODO: Gradients aren't inherited...
+ switch (elem._baseline) {
+ case 'bottom':
+ rect.top = - height;
+ rect.bottom = 0;
+ break;
+ case 'top':
+ rect.top = 0;
+ rect.bottom = height;
+ break;
+ default:
+ rect.top = - h;
+ rect.bottom = h;
+ }
+
+ rect.width = width;
+ rect.height = height;
+
+ if (!rect.centroid) {
+ rect.centroid = {};
+ }
+
+ // TODO:
+ rect.centroid.x = w;
+ rect.centroid.y = h;
+
+ },
+
+ render: function(gl, program, forcedParent) {
+
+ if (!this._visible || !this._opacity) {
+ return this;
+ }
+
+ this._update();
+
+ // Calculate what changed
+
+ var parent = this.parent;
+ var flagParentMatrix = parent._matrix.manual || parent._flagMatrix;
+ var flagMatrix = this._matrix.manual || this._flagMatrix;
+ var flagTexture = this._flagVertices || this._flagFill
+ || (this._fill instanceof Two.LinearGradient && (this._fill._flagSpread || this._fill._flagStops || this._fill._flagEndPoints))
+ || (this._fill instanceof Two.RadialGradient && (this._fill._flagSpread || this._fill._flagStops || this._fill._flagRadius || this._fill._flagCenter || this._fill._flagFocal))
+ || (this._fill instanceof Two.Texture && (this._fill._flagLoaded && this._fill.loaded))
+ || (this._stroke instanceof Two.LinearGradient && (this._stroke._flagSpread || this._stroke._flagStops || this._stroke._flagEndPoints))
+ || (this._stroke instanceof Two.RadialGradient && (this._stroke._flagSpread || this._stroke._flagStops || this._stroke._flagRadius || this._stroke._flagCenter || this._stroke._flagFocal))
+ || (this._texture instanceof Two.Texture && (this._texture._flagLoaded && this._texture.loaded))
+ || this._flagStroke || this._flagLinewidth || this._flagOpacity
+ || parent._flagOpacity || this._flagVisible || this._flagScale
+ || this._flagValue || this._flagFamily || this._flagSize
+ || this._flagLeading || this._flagAlignment || this._flagBaseline
+ || this._flagStyle || this._flagWeight || this._flagDecoration
+ || !this._renderer.texture;
+
+ if (flagParentMatrix || flagMatrix) {
+
+ if (!this._renderer.matrix) {
+ this._renderer.matrix = new Two.Array(9);
+ }
+
+ // Reduce amount of object / array creation / deletion
+
+ this._matrix.toArray(true, transformation);
+
+ multiplyMatrix(transformation, parent._renderer.matrix, this._renderer.matrix);
+ this._renderer.scale = this._scale * parent._renderer.scale;
+
+ }
+
+ if (flagTexture) {
+
+ if (!this._renderer.rect) {
+ this._renderer.rect = {};
+ }
+
+ if (!this._renderer.triangles) {
+ this._renderer.triangles = new Two.Array(12);
+ }
+
+ this._renderer.opacity = this._opacity * parent._renderer.opacity;
+
+ webgl.text.getBoundingClientRect(this, this._renderer.rect);
+ webgl.getTriangles(this._renderer.rect, this._renderer.triangles);
+
+ webgl.updateBuffer.call(webgl, gl, this, program);
+ webgl.updateTexture.call(webgl, gl, this);
+
+ }
+
+ // if (this._mask) {
+ // webgl[this._mask._renderer.type].render.call(mask, gl, program, this);
+ // }
+
+ if (this._clip && !forcedParent) {
+ return;
+ }
+
+ // Draw Texture
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._renderer.textureCoordsBuffer);
+
+ gl.vertexAttribPointer(program.textureCoords, 2, gl.FLOAT, false, 0, 0);
+
+ gl.bindTexture(gl.TEXTURE_2D, this._renderer.texture);
+
+
+ // Draw Rect
+
+ gl.uniformMatrix3fv(program.matrix, false, this._renderer.matrix);
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._renderer.buffer);
+
+ gl.vertexAttribPointer(program.position, 2, gl.FLOAT, false, 0, 0);
+
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
+
+ return this.flagReset();
+
+ }
+
+ },
+
+ 'linear-gradient': {
+
+ render: function(ctx, elem) {
+
+ if (!ctx.canvas.getContext('2d')) {
+ return;
+ }
+
+ this._update();
+
+ if (!this._renderer.effect || this._flagEndPoints || this._flagStops) {
+
+ this._renderer.effect = ctx.createLinearGradient(
+ this.left._x, this.left._y,
+ this.right._x, this.right._y
+ );
+
+ for (var i = 0; i < this.stops.length; i++) {
+ var stop = this.stops[i];
+ this._renderer.effect.addColorStop(stop._offset, stop._color);
+ }
+
+ }
+
+ return this.flagReset();
+
+ }
+
+ },
+
+ 'radial-gradient': {
+
+ render: function(ctx, elem) {
+
+ if (!ctx.canvas.getContext('2d')) {
+ return;
+ }
+
+ this._update();
+
+ if (!this._renderer.effect || this._flagCenter || this._flagFocal
+ || this._flagRadius || this._flagStops) {
+
+ this._renderer.effect = ctx.createRadialGradient(
+ this.center._x, this.center._y, 0,
+ this.focal._x, this.focal._y, this._radius
+ );
+
+ for (var i = 0; i < this.stops.length; i++) {
+ var stop = this.stops[i];
+ this._renderer.effect.addColorStop(stop._offset, stop._color);
+ }
+
+ }
+
+ return this.flagReset();
+
+ }
+
+ },
+
+ texture: {
+
+ render: function(ctx, elem) {
+
+ if (!ctx.canvas.getContext('2d')) {
+ return;
+ }
+
+ this._update();
+
+ var image = this.image;
+ var repeat;
+
+ if (!this._renderer.effect || ((this._flagLoaded || this._flagRepeat) && this.loaded)) {
+ this._renderer.effect = ctx.createPattern(image, this._repeat);
+ }
+
+ if (this._flagOffset || this._flagLoaded || this._flagScale) {
+
+ if (!(this._renderer.offset instanceof Two.Vector)) {
+ this._renderer.offset = new Two.Vector();
+ }
+
+ this._renderer.offset.x = this._offset.x;
+ this._renderer.offset.y = this._offset.y;
+
+ if (image) {
+
+ this._renderer.offset.x -= image.width / 2;
+ this._renderer.offset.y += image.height / 2;
+
+ if (this._scale instanceof Two.Vector) {
+ this._renderer.offset.x *= this._scale.x;
+ this._renderer.offset.y *= this._scale.y;
+ } else {
+ this._renderer.offset.x *= this._scale;
+ this._renderer.offset.y *= this._scale;
+ }
+ }
+
+ }
+
+ if (this._flagScale || this._flagLoaded) {
+
+ if (!(this._renderer.scale instanceof Two.Vector)) {
+ this._renderer.scale = new Two.Vector();
+ }
+
+ if (this._scale instanceof Two.Vector) {
+ this._renderer.scale.copy(this._scale);
+ } else {
+ this._renderer.scale.set(this._scale, this._scale);
+ }
+
+ }
+
+ return this.flagReset();
+
+ }
+
+ },
+
+ getTriangles: function(rect, triangles) {
+
+ var top = rect.top,
+ left = rect.left,
+ right = rect.right,
+ bottom = rect.bottom;
+
+ // First Triangle
+
+ triangles[0] = left;
+ triangles[1] = top;
+
+ triangles[2] = right;
+ triangles[3] = top;
+
+ triangles[4] = left;
+ triangles[5] = bottom;
+
+ // Second Triangle
+
+ triangles[6] = left;
+ triangles[7] = bottom;
+
+ triangles[8] = right;
+ triangles[9] = top;
+
+ triangles[10] = right;
+ triangles[11] = bottom;
+
+ },
+
+ updateTexture: function(gl, elem) {
+
+ this[elem._renderer.type].updateCanvas.call(webgl, elem);
+
+ if (elem._renderer.texture) {
+ gl.deleteTexture(elem._renderer.texture);
+ }
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, elem._renderer.textureCoordsBuffer);
+
+ // TODO: Is this necessary every time or can we do once?
+ // TODO: Create a registry for textures
+ elem._renderer.texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, elem._renderer.texture);
+
+ // Set the parameters so we can render any size image.
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+
+ if (this.canvas.width <= 0 || this.canvas.height <= 0) {
+ return;
+ }
+
+ // Upload the image into the texture.
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.canvas);
+
+ },
+
+ updateBuffer: function(gl, elem, program) {
+
+ if (_.isObject(elem._renderer.buffer)) {
+ gl.deleteBuffer(elem._renderer.buffer);
+ }
+
+ elem._renderer.buffer = gl.createBuffer();
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, elem._renderer.buffer);
+ gl.enableVertexAttribArray(program.position);
+
+ gl.bufferData(gl.ARRAY_BUFFER, elem._renderer.triangles, gl.STATIC_DRAW);
+
+ if (_.isObject(elem._renderer.textureCoordsBuffer)) {
+ gl.deleteBuffer(elem._renderer.textureCoordsBuffer);
+ }
+
+ elem._renderer.textureCoordsBuffer = gl.createBuffer();
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, elem._renderer.textureCoordsBuffer);
+ gl.enableVertexAttribArray(program.textureCoords);
+
+ gl.bufferData(gl.ARRAY_BUFFER, this.uv, gl.STATIC_DRAW);
+
+ },
+
+ program: {
+
+ create: function(gl, shaders) {
+ var program, linked, error;
+ program = gl.createProgram();
+ _.each(shaders, function(s) {
+ gl.attachShader(program, s);
+ });
+
+ gl.linkProgram(program);
+ linked = gl.getProgramParameter(program, gl.LINK_STATUS);
+ if (!linked) {
+ error = gl.getProgramInfoLog(program);
+ gl.deleteProgram(program);
+ throw new Two.Utils.Error('unable to link program: ' + error);
+ }
+
+ return program;
+
+ }
+
+ },
+
+ shaders: {
+
+ create: function(gl, source, type) {
+ var shader, compiled, error;
+ shader = gl.createShader(gl[type]);
+ gl.shaderSource(shader, source);
+ gl.compileShader(shader);
+
+ compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
+ if (!compiled) {
+ error = gl.getShaderInfoLog(shader);
+ gl.deleteShader(shader);
+ throw new Two.Utils.Error('unable to compile shader ' + shader + ': ' + error);
+ }
+
+ return shader;
+
+ },
+
+ types: {
+ vertex: 'VERTEX_SHADER',
+ fragment: 'FRAGMENT_SHADER'
+ },
+
+ vertex: [
+ 'attribute vec2 a_position;',
+ 'attribute vec2 a_textureCoords;',
+ '',
+ 'uniform mat3 u_matrix;',
+ 'uniform vec2 u_resolution;',
+ '',
+ 'varying vec2 v_textureCoords;',
+ '',
+ 'void main() {',
+ ' vec2 projected = (u_matrix * vec3(a_position, 1.0)).xy;',
+ ' vec2 normal = projected / u_resolution;',
+ ' vec2 clipspace = (normal * 2.0) - 1.0;',
+ '',
+ ' gl_Position = vec4(clipspace * vec2(1.0, -1.0), 0.0, 1.0);',
+ ' v_textureCoords = a_textureCoords;',
+ '}'
+ ].join('\n'),
+
+ fragment: [
+ 'precision mediump float;',
+ '',
+ 'uniform sampler2D u_image;',
+ 'varying vec2 v_textureCoords;',
+ '',
+ 'void main() {',
+ ' gl_FragColor = texture2D(u_image, v_textureCoords);',
+ '}'
+ ].join('\n')
+
+ },
+
+ TextureRegistry: new Two.Registry()
+
+ };
+
+ webgl.ctx = webgl.canvas.getContext('2d');
+
+ var Renderer = Two[Two.Types.webgl] = function(options) {
+
+ var params, gl, vs, fs;
+ this.domElement = options.domElement || document.createElement('canvas');
+
+ // Everything drawn on the canvas needs to come from the stage.
+ this.scene = new Two.Group();
+ this.scene.parent = this;
+
+ this._renderer = {
+ matrix: new Two.Array(identity),
+ scale: 1,
+ opacity: 1
+ };
+ this._flagMatrix = true;
+
+ // http://games.greggman.com/game/webgl-and-alpha/
+ // http://www.khronos.org/registry/webgl/specs/latest/#5.2
+ params = _.defaults(options || {}, {
+ antialias: false,
+ alpha: true,
+ premultipliedAlpha: true,
+ stencil: true,
+ preserveDrawingBuffer: true,
+ overdraw: false
+ });
+
+ this.overdraw = params.overdraw;
+
+ gl = this.ctx = this.domElement.getContext('webgl', params) ||
+ this.domElement.getContext('experimental-webgl', params);
+
+ if (!this.ctx) {
+ throw new Two.Utils.Error(
+ 'unable to create a webgl context. Try using another renderer.');
+ }
+
+ // Compile Base Shaders to draw in pixel space.
+ vs = webgl.shaders.create(
+ gl, webgl.shaders.vertex, webgl.shaders.types.vertex);
+ fs = webgl.shaders.create(
+ gl, webgl.shaders.fragment, webgl.shaders.types.fragment);
+
+ this.program = webgl.program.create(gl, [vs, fs]);
+ gl.useProgram(this.program);
+
+ // Create and bind the drawing buffer
+
+ // look up where the vertex data needs to go.
+ this.program.position = gl.getAttribLocation(this.program, 'a_position');
+ this.program.matrix = gl.getUniformLocation(this.program, 'u_matrix');
+ this.program.textureCoords = gl.getAttribLocation(this.program, 'a_textureCoords');
+
+ // Copied from Three.js WebGLRenderer
+ gl.disable(gl.DEPTH_TEST);
+
+ // Setup some initial statements of the gl context
+ gl.enable(gl.BLEND);
+
+ // https://code.google.com/p/chromium/issues/detail?id=316393
+ // gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, gl.TRUE);
+
+ gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
+ gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA,
+ gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
+
+ };
+
+ _.extend(Renderer, {
+
+ Utils: webgl
+
+ });
+
+ _.extend(Renderer.prototype, Two.Utils.Events, {
+
+ setSize: function(width, height, ratio) {
+
+ this.width = width;
+ this.height = height;
+
+ this.ratio = _.isUndefined(ratio) ? getRatio(this.ctx) : ratio;
+
+ this.domElement.width = width * this.ratio;
+ this.domElement.height = height * this.ratio;
+
+ _.extend(this.domElement.style, {
+ width: width + 'px',
+ height: height + 'px'
+ });
+
+ width *= this.ratio;
+ height *= this.ratio;
+
+ // Set for this.stage parent scaling to account for HDPI
+ this._renderer.matrix[0] = this._renderer.matrix[4] = this._renderer.scale = this.ratio;
+
+ this._flagMatrix = true;
+
+ this.ctx.viewport(0, 0, width, height);
+
+ var resolutionLocation = this.ctx.getUniformLocation(
+ this.program, 'u_resolution');
+ this.ctx.uniform2f(resolutionLocation, width, height);
+
+ return this;
+
+ },
+
+ render: function() {
+
+ var gl = this.ctx;
+
+ if (!this.overdraw) {
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+ }
+
+ webgl.group.render.call(this.scene, gl, this.program);
+ this._flagMatrix = false;
+
+ return this;
+
+ }
+
+ });
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ var _ = Two.Utils;
+
+ var Shape = Two.Shape = function() {
+
+ // Private object for renderer specific variables.
+ this._renderer = {};
+ this._renderer.flagMatrix = _.bind(Shape.FlagMatrix, this);
+ this.isShape = true;
+
+ this.id = Two.Identifier + Two.uniqueId();
+ this.classList = [];
+
+ // Define matrix properties which all inherited
+ // objects of Shape have.
+
+ this._matrix = new Two.Matrix();
+
+ this.translation = new Two.Vector();
+ this.rotation = 0;
+ this.scale = 1;
+
+ };
+
+ _.extend(Shape, {
+
+ FlagMatrix: function() {
+ this._flagMatrix = true;
+ },
+
+ MakeObservable: function(object) {
+
+ Object.defineProperty(object, 'translation', {
+ enumerable: true,
+ get: function() {
+ return this._translation;
+ },
+ set: function(v) {
+ if (this._translation) {
+ this._translation.unbind(Two.Events.change, this._renderer.flagMatrix);
+ }
+ this._translation = v;
+ this._translation.bind(Two.Events.change, this._renderer.flagMatrix);
+ Shape.FlagMatrix.call(this);
+ }
+ });
+
+ Object.defineProperty(object, 'rotation', {
+ enumerable: true,
+ get: function() {
+ return this._rotation;
+ },
+ set: function(v) {
+ this._rotation = v;
+ this._flagMatrix = true;
+ }
+ });
+
+ Object.defineProperty(object, 'scale', {
+ enumerable: true,
+ get: function() {
+ return this._scale;
+ },
+ set: function(v) {
+
+ if (this._scale instanceof Two.Vector) {
+ this._scale.unbind(Two.Events.change, this._renderer.flagMatrix);
+ }
+
+ this._scale = v;
+
+ if (this._scale instanceof Two.Vector) {
+ this._scale.bind(Two.Events.change, this._renderer.flagMatrix);
+ }
+
+ this._flagMatrix = true;
+ this._flagScale = true;
+
+ }
+ });
+
+ }
+
+ });
+
+ _.extend(Shape.prototype, Two.Utils.Events, {
+
+ // Flags
+
+ _flagMatrix: true,
+ _flagScale: false,
+
+ // _flagMask: false,
+ // _flagClip: false,
+
+ // Underlying Properties
+
+ _rotation: 0,
+ _scale: 1,
+ _translation: null,
+
+ // _mask: null,
+ // _clip: false,
+
+ addTo: function(group) {
+ group.add(this);
+ return this;
+ },
+
+ clone: function() {
+ var clone = new Shape();
+ clone.translation.copy(this.translation);
+ clone.rotation = this.rotation;
+ clone.scale = this.scale;
+ _.each(Shape.Properties, function(k) {
+ clone[k] = this[k];
+ }, this);
+ return clone._update();
+ },
+
+ /**
+ * To be called before render that calculates and collates all information
+ * to be as up-to-date as possible for the render. Called once a frame.
+ */
+ _update: function(deep) {
+
+ if (!this._matrix.manual && this._flagMatrix) {
+
+ this._matrix
+ .identity()
+ .translate(this.translation.x, this.translation.y);
+
+ if (this._scale instanceof Two.Vector) {
+ this._matrix.scale(this._scale.x, this._scale.y);
+ } else {
+ this._matrix.scale(this._scale);
+ }
+
+ this._matrix.rotate(this.rotation);
+
+ }
+
+ if (deep) {
+ // Bubble up to parents mainly for `getBoundingClientRect` method.
+ if (this.parent && this.parent._update) {
+ this.parent._update();
+ }
+ }
+
+ return this;
+
+ },
+
+ flagReset: function() {
+
+ this._flagMatrix = this._flagScale = false;
+
+ return this;
+
+ }
+
+ });
+
+ Shape.MakeObservable(Shape.prototype);
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ /**
+ * Constants
+ */
+
+ var min = Math.min, max = Math.max, round = Math.round,
+ getComputedMatrix = Two.Utils.getComputedMatrix;
+
+ var commands = {};
+ var _ = Two.Utils;
+
+ _.each(Two.Commands, function(v, k) {
+ commands[k] = new RegExp(v);
+ });
+
+ var Path = Two.Path = function(vertices, closed, curved, manual) {
+
+ Two.Shape.call(this);
+
+ this._renderer.type = 'path';
+ this._renderer.flagVertices = _.bind(Path.FlagVertices, this);
+ this._renderer.bindVertices = _.bind(Path.BindVertices, this);
+ this._renderer.unbindVertices = _.bind(Path.UnbindVertices, this);
+
+ this._renderer.flagFill = _.bind(Path.FlagFill, this);
+ this._renderer.flagStroke = _.bind(Path.FlagStroke, this);
+
+ this._closed = !!closed;
+ this._curved = !!curved;
+
+ this.beginning = 0;
+ this.ending = 1;
+
+ // Style properties
+
+ this.fill = '#fff';
+ this.stroke = '#000';
+ this.linewidth = 1.0;
+ this.opacity = 1.0;
+ this.visible = true;
+
+ this.cap = 'butt'; // Default of Adobe Illustrator
+ this.join = 'miter'; // Default of Adobe Illustrator
+ this.miter = 4; // Default of Adobe Illustrator
+
+ this._vertices = [];
+ this.vertices = vertices;
+
+ // Determines whether or not two.js should calculate curves, lines, and
+ // commands automatically for you or to let the developer manipulate them
+ // for themselves.
+ this.automatic = !manual;
+
+ };
+
+ _.extend(Path, {
+
+ Properties: [
+ 'fill',
+ 'stroke',
+ 'linewidth',
+ 'opacity',
+ 'visible',
+ 'cap',
+ 'join',
+ 'miter',
+
+ 'closed',
+ 'curved',
+ 'automatic',
+ 'beginning',
+ 'ending'
+ ],
+
+ FlagVertices: function() {
+ this._flagVertices = true;
+ this._flagLength = true;
+ },
+
+ BindVertices: function(items) {
+
+ // This function is called a lot
+ // when importing a large SVG
+ var i = items.length;
+ while (i--) {
+ items[i].bind(Two.Events.change, this._renderer.flagVertices);
+ }
+
+ this._renderer.flagVertices();
+
+ },
+
+ UnbindVertices: function(items) {
+
+ var i = items.length;
+ while (i--) {
+ items[i].unbind(Two.Events.change, this._renderer.flagVertices);
+ }
+
+ this._renderer.flagVertices();
+
+ },
+
+ FlagFill: function() {
+ this._flagFill = true;
+ },
+
+ FlagStroke: function() {
+ this._flagStroke = true;
+ },
+
+ MakeObservable: function(object) {
+
+ Two.Shape.MakeObservable(object);
+
+ // Only the 6 defined properties are flagged like this. The subsequent
+ // properties behave differently and need to be hand written.
+ _.each(Path.Properties.slice(2, 8), Two.Utils.defineProperty, object);
+
+ Object.defineProperty(object, 'fill', {
+ enumerable: true,
+ get: function() {
+ return this._fill;
+ },
+ set: function(f) {
+
+ if (this._fill instanceof Two.Gradient
+ || this._fill instanceof Two.LinearGradient
+ || this._fill instanceof Two.RadialGradient
+ || this._fill instanceof Two.Texture) {
+ this._fill.unbind(Two.Events.change, this._renderer.flagFill);
+ }
+
+ this._fill = f;
+ this._flagFill = true;
+
+ if (this._fill instanceof Two.Gradient
+ || this._fill instanceof Two.LinearGradient
+ || this._fill instanceof Two.RadialGradient
+ || this._fill instanceof Two.Texture) {
+ this._fill.bind(Two.Events.change, this._renderer.flagFill);
+ }
+
+ }
+ });
+
+ Object.defineProperty(object, 'stroke', {
+ enumerable: true,
+ get: function() {
+ return this._stroke;
+ },
+ set: function(f) {
+
+ if (this._stroke instanceof Two.Gradient
+ || this._stroke instanceof Two.LinearGradient
+ || this._stroke instanceof Two.RadialGradient
+ || this._stroke instanceof Two.Texture) {
+ this._stroke.unbind(Two.Events.change, this._renderer.flagStroke);
+ }
+
+ this._stroke = f;
+ this._flagStroke = true;
+
+ if (this._stroke instanceof Two.Gradient
+ || this._stroke instanceof Two.LinearGradient
+ || this._stroke instanceof Two.RadialGradient
+ || this._stroke instanceof Two.Texture) {
+ this._stroke.bind(Two.Events.change, this._renderer.flagStroke);
+ }
+
+ }
+ });
+
+ Object.defineProperty(object, 'length', {
+ get: function() {
+ if (this._flagLength) {
+ this._updateLength();
+ }
+ return this._length;
+ }
+ });
+
+ Object.defineProperty(object, 'closed', {
+ enumerable: true,
+ get: function() {
+ return this._closed;
+ },
+ set: function(v) {
+ this._closed = !!v;
+ this._flagVertices = true;
+ }
+ });
+
+ Object.defineProperty(object, 'curved', {
+ enumerable: true,
+ get: function() {
+ return this._curved;
+ },
+ set: function(v) {
+ this._curved = !!v;
+ this._flagVertices = true;
+ }
+ });
+
+ Object.defineProperty(object, 'automatic', {
+ enumerable: true,
+ get: function() {
+ return this._automatic;
+ },
+ set: function(v) {
+ if (v === this._automatic) {
+ return;
+ }
+ this._automatic = !!v;
+ var method = this._automatic ? 'ignore' : 'listen';
+ _.each(this.vertices, function(v) {
+ v[method]();
+ });
+ }
+ });
+
+ Object.defineProperty(object, 'beginning', {
+ enumerable: true,
+ get: function() {
+ return this._beginning;
+ },
+ set: function(v) {
+ this._beginning = v;
+ this._flagVertices = true;
+ }
+ });
+
+ Object.defineProperty(object, 'ending', {
+ enumerable: true,
+ get: function() {
+ return this._ending;
+ },
+ set: function(v) {
+ this._ending = v;
+ this._flagVertices = true;
+ }
+ });
+
+ Object.defineProperty(object, 'vertices', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._collection;
+ },
+
+ set: function(vertices) {
+
+ var updateVertices = this._renderer.flagVertices;
+ var bindVertices = this._renderer.bindVertices;
+ var unbindVertices = this._renderer.unbindVertices;
+
+ // Remove previous listeners
+ if (this._collection) {
+ this._collection
+ .unbind(Two.Events.insert, bindVertices)
+ .unbind(Two.Events.remove, unbindVertices);
+ }
+
+ // Create new Collection with copy of vertices
+ this._collection = new Two.Utils.Collection((vertices || []).slice(0));
+
+ // Listen for Collection changes and bind / unbind
+ this._collection
+ .bind(Two.Events.insert, bindVertices)
+ .bind(Two.Events.remove, unbindVertices);
+
+ // Bind Initial Vertices
+ bindVertices(this._collection);
+
+ }
+
+ });
+
+ Object.defineProperty(object, 'clip', {
+ enumerable: true,
+ get: function() {
+ return this._clip;
+ },
+ set: function(v) {
+ this._clip = v;
+ this._flagClip = true;
+ }
+ });
+
+ }
+
+ });
+
+ _.extend(Path.prototype, Two.Shape.prototype, {
+
+ // Flags
+ // http://en.wikipedia.org/wiki/Flag
+
+ _flagVertices: true,
+ _flagLength: true,
+
+ _flagFill: true,
+ _flagStroke: true,
+ _flagLinewidth: true,
+ _flagOpacity: true,
+ _flagVisible: true,
+
+ _flagCap: true,
+ _flagJoin: true,
+ _flagMiter: true,
+
+ _flagClip: false,
+
+ // Underlying Properties
+
+ _length: 0,
+
+ _fill: '#fff',
+ _stroke: '#000',
+ _linewidth: 1.0,
+ _opacity: 1.0,
+ _visible: true,
+
+ _cap: 'round',
+ _join: 'round',
+ _miter: 4,
+
+ _closed: true,
+ _curved: false,
+ _automatic: true,
+ _beginning: 0,
+ _ending: 1.0,
+
+ _clip: false,
+
+ clone: function(parent) {
+
+ parent = parent || this.parent;
+
+ var points = _.map(this.vertices, function(v) {
+ return v.clone();
+ });
+
+ var clone = new Path(points, this.closed, this.curved, !this.automatic);
+
+ _.each(Two.Path.Properties, function(k) {
+ clone[k] = this[k];
+ }, this);
+
+ clone.translation.copy(this.translation);
+ clone.rotation = this.rotation;
+ clone.scale = this.scale;
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone;
+
+ },
+
+ toObject: function() {
+
+ var result = {
+ vertices: _.map(this.vertices, function(v) {
+ return v.toObject();
+ })
+ };
+
+ _.each(Two.Shape.Properties, function(k) {
+ result[k] = this[k];
+ }, this);
+
+ result.translation = this.translation.toObject;
+ result.rotation = this.rotation;
+ result.scale = this.scale;
+
+ return result;
+
+ },
+
+ noFill: function() {
+ this.fill = 'transparent';
+ return this;
+ },
+
+ noStroke: function() {
+ this.stroke = 'transparent';
+ return this;
+ },
+
+ /**
+ * Orient the vertices of the shape to the upper lefthand
+ * corner of the path.
+ */
+ corner: function() {
+
+ var rect = this.getBoundingClientRect(true);
+
+ rect.centroid = {
+ x: rect.left + rect.width / 2,
+ y: rect.top + rect.height / 2
+ };
+
+ _.each(this.vertices, function(v) {
+ v.addSelf(rect.centroid);
+ });
+
+ return this;
+
+ },
+
+ /**
+ * Orient the vertices of the shape to the center of the
+ * path.
+ */
+ center: function() {
+
+ var rect = this.getBoundingClientRect(true);
+
+ rect.centroid = {
+ x: rect.left + rect.width / 2,
+ y: rect.top + rect.height / 2
+ };
+
+ _.each(this.vertices, function(v) {
+ v.subSelf(rect.centroid);
+ });
+
+ // this.translation.addSelf(rect.centroid);
+
+ return this;
+
+ },
+
+ /**
+ * Remove self from the scene / parent.
+ */
+ remove: function() {
+
+ if (!this.parent) {
+ return this;
+ }
+
+ this.parent.remove(this);
+
+ return this;
+
+ },
+
+ /**
+ * Return an object with top, left, right, bottom, width, and height
+ * parameters of the group.
+ */
+ getBoundingClientRect: function(shallow) {
+ var matrix, border, l, x, y, i, v;
+
+ var left = Infinity, right = -Infinity,
+ top = Infinity, bottom = -Infinity;
+
+ // TODO: Update this to not __always__ update. Just when it needs to.
+ this._update(true);
+
+ matrix = !!shallow ? this._matrix : getComputedMatrix(this);
+
+ border = this.linewidth / 2;
+ l = this._vertices.length;
+
+ if (l <= 0) {
+ v = matrix.multiply(0, 0, 1);
+ return {
+ top: v.y,
+ left: v.x,
+ right: v.x,
+ bottom: v.y,
+ width: 0,
+ height: 0
+ };
+ }
+
+ for (i = 0; i < l; i++) {
+ v = this._vertices[i];
+
+ x = v.x;
+ y = v.y;
+
+ v = matrix.multiply(x, y, 1);
+ top = min(v.y - border, top);
+ left = min(v.x - border, left);
+ right = max(v.x + border, right);
+ bottom = max(v.y + border, bottom);
+ }
+
+ return {
+ top: top,
+ left: left,
+ right: right,
+ bottom: bottom,
+ width: right - left,
+ height: bottom - top
+ };
+
+ },
+
+ /**
+ * Given a float `t` from 0 to 1, return a point or assign a passed `obj`'s
+ * coordinates to that percentage on this Two.Path's curve.
+ */
+ getPointAt: function(t, obj) {
+ var ia, ib;
+ var x, x1, x2, x3, x4, y, y1, y2, y3, y4, left, right;
+ var target = this.length * Math.min(Math.max(t, 0), 1);
+ var length = this.vertices.length;
+ var last = length - 1;
+
+ var a = null;
+ var b = null;
+
+ for (var i = 0, l = this._lengths.length, sum = 0; i < l; i++) {
+
+ if (sum + this._lengths[i] >= target) {
+
+ if (this._closed) {
+ ia = Two.Utils.mod(i, length);
+ ib = Two.Utils.mod(i - 1, length);
+ if (i === 0) {
+ ia = ib;
+ ib = i;
+ }
+ } else {
+ ia = i;
+ ib = Math.min(Math.max(i - 1, 0), last);
+ }
+
+ a = this.vertices[ia];
+ b = this.vertices[ib];
+ target -= sum;
+ if (this._lengths[i] !== 0) {
+ t = target / this._lengths[i];
+ }
+
+ break;
+
+ }
+
+ sum += this._lengths[i];
+
+ }
+
+ // console.log(sum, a.command, b.command);
+
+ if (_.isNull(a) || _.isNull(b)) {
+ return null;
+ }
+
+ right = b.controls && b.controls.right;
+ left = a.controls && a.controls.left;
+
+ x1 = b.x;
+ y1 = b.y;
+ x2 = (right || b).x;
+ y2 = (right || b).y;
+ x3 = (left || a).x;
+ y3 = (left || a).y;
+ x4 = a.x;
+ y4 = a.y;
+
+ if (right && b._relative) {
+ x2 += b.x;
+ y2 += b.y;
+ }
+
+ if (left && a._relative) {
+ x3 += a.x;
+ y3 += a.y;
+ }
+
+ x = Two.Utils.getPointOnCubicBezier(t, x1, x2, x3, x4);
+ y = Two.Utils.getPointOnCubicBezier(t, y1, y2, y3, y4);
+
+ if (_.isObject(obj)) {
+ obj.x = x;
+ obj.y = y;
+ return obj;
+ }
+
+ return new Two.Vector(x, y);
+
+ },
+
+ /**
+ * Based on closed / curved and sorting of vertices plot where all points
+ * should be and where the respective handles should be too.
+ */
+ plot: function() {
+
+ if (this.curved) {
+ Two.Utils.getCurveFromPoints(this._vertices, this.closed);
+ return this;
+ }
+
+ for (var i = 0; i < this._vertices.length; i++) {
+ this._vertices[i]._command = i === 0 ? Two.Commands.move : Two.Commands.line;
+ }
+
+ return this;
+
+ },
+
+ subdivide: function(limit) {
+ //TODO: DRYness (function below)
+ this._update();
+
+ var last = this.vertices.length - 1;
+ var b = this.vertices[last];
+ var closed = this._closed || this.vertices[last]._command === Two.Commands.close;
+ var points = [];
+ _.each(this.vertices, function(a, i) {
+
+ if (i <= 0 && !closed) {
+ b = a;
+ return;
+ }
+
+ if (a.command === Two.Commands.move) {
+ points.push(new Two.Anchor(b.x, b.y));
+ if (i > 0) {
+ points[points.length - 1].command = Two.Commands.line;
+ }
+ b = a;
+ return;
+ }
+
+ var verts = getSubdivisions(a, b, limit);
+ points = points.concat(verts);
+
+ // Assign commands to all the verts
+ _.each(verts, function(v, i) {
+ if (i <= 0 && b.command === Two.Commands.move) {
+ v.command = Two.Commands.move;
+ } else {
+ v.command = Two.Commands.line;
+ }
+ });
+
+ if (i >= last) {
+
+ // TODO: Add check if the two vectors in question are the same values.
+ if (this._closed && this._automatic) {
+
+ b = a;
+
+ verts = getSubdivisions(a, b, limit);
+ points = points.concat(verts);
+
+ // Assign commands to all the verts
+ _.each(verts, function(v, i) {
+ if (i <= 0 && b.command === Two.Commands.move) {
+ v.command = Two.Commands.move;
+ } else {
+ v.command = Two.Commands.line;
+ }
+ });
+
+ } else if (closed) {
+ points.push(new Two.Anchor(a.x, a.y));
+ }
+
+ points[points.length - 1].command = closed ? Two.Commands.close : Two.Commands.line;
+
+ }
+
+ b = a;
+
+ }, this);
+
+ this._automatic = false;
+ this._curved = false;
+ this.vertices = points;
+
+ return this;
+
+ },
+
+ _updateLength: function(limit) {
+ //TODO: DRYness (function above)
+ this._update();
+
+ var length = this.vertices.length;
+ var last = length - 1;
+ var b = this.vertices[last];
+ var closed = this._closed || this.vertices[last]._command === Two.Commands.close;
+ var sum = 0;
+
+ if (_.isUndefined(this._lengths)) {
+ this._lengths = [];
+ }
+
+ _.each(this.vertices, function(a, i) {
+
+ if ((i <= 0 && !closed) || a.command === Two.Commands.move) {
+ b = a;
+ this._lengths[i] = 0;
+ return;
+ }
+
+ this._lengths[i] = getCurveLength(a, b, limit);
+ sum += this._lengths[i];
+
+ if (i >= last && closed) {
+
+ b = this.vertices[(i + 1) % length];
+
+ this._lengths[i + 1] = getCurveLength(a, b, limit);
+ sum += this._lengths[i + 1];
+
+ }
+
+ b = a;
+
+ }, this);
+
+ this._length = sum;
+
+ return this;
+
+ },
+
+ _update: function() {
+
+ if (this._flagVertices) {
+
+ var l = this.vertices.length;
+ var last = l - 1, v;
+
+ // TODO: Should clamp this so that `ia` and `ib`
+ // cannot select non-verts.
+ var ia = round((this._beginning) * last);
+ var ib = round((this._ending) * last);
+
+ this._vertices.length = 0;
+
+ for (var i = ia; i < ib + 1; i++) {
+ v = this.vertices[i];
+ this._vertices.push(v);
+ }
+
+ if (this._automatic) {
+ this.plot();
+ }
+
+ }
+
+ Two.Shape.prototype._update.apply(this, arguments);
+
+ return this;
+
+ },
+
+ flagReset: function() {
+
+ this._flagVertices = this._flagFill = this._flagStroke =
+ this._flagLinewidth = this._flagOpacity = this._flagVisible =
+ this._flagCap = this._flagJoin = this._flagMiter =
+ this._flagClip = false;
+
+ Two.Shape.prototype.flagReset.call(this);
+
+ return this;
+
+ }
+
+ });
+
+ Path.MakeObservable(Path.prototype);
+
+ /**
+ * Utility functions
+ */
+
+ function getCurveLength(a, b, limit) {
+ // TODO: DRYness
+ var x1, x2, x3, x4, y1, y2, y3, y4;
+
+ var right = b.controls && b.controls.right;
+ var left = a.controls && a.controls.left;
+
+ x1 = b.x;
+ y1 = b.y;
+ x2 = (right || b).x;
+ y2 = (right || b).y;
+ x3 = (left || a).x;
+ y3 = (left || a).y;
+ x4 = a.x;
+ y4 = a.y;
+
+ if (right && b._relative) {
+ x2 += b.x;
+ y2 += b.y;
+ }
+
+ if (left && a._relative) {
+ x3 += a.x;
+ y3 += a.y;
+ }
+
+ return Two.Utils.getCurveLength(x1, y1, x2, y2, x3, y3, x4, y4, limit);
+
+ }
+
+ function getSubdivisions(a, b, limit) {
+ // TODO: DRYness
+ var x1, x2, x3, x4, y1, y2, y3, y4;
+
+ var right = b.controls && b.controls.right;
+ var left = a.controls && a.controls.left;
+
+ x1 = b.x;
+ y1 = b.y;
+ x2 = (right || b).x;
+ y2 = (right || b).y;
+ x3 = (left || a).x;
+ y3 = (left || a).y;
+ x4 = a.x;
+ y4 = a.y;
+
+ if (right && b._relative) {
+ x2 += b.x;
+ y2 += b.y;
+ }
+
+ if (left && a._relative) {
+ x3 += a.x;
+ y3 += a.y;
+ }
+
+ return Two.Utils.subdivide(x1, y1, x2, y2, x3, y3, x4, y4, limit);
+
+ }
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ var Path = Two.Path;
+ var _ = Two.Utils;
+
+ var Line = Two.Line = function(x1, y1, x2, y2) {
+
+ var width = x2 - x1;
+ var height = y2 - y1;
+
+ var w2 = width / 2;
+ var h2 = height / 2;
+
+ Path.call(this, [
+ new Two.Anchor(- w2, - h2),
+ new Two.Anchor(w2, h2)
+ ]);
+
+ this.translation.set(x1 + w2, y1 + h2);
+
+ };
+
+ _.extend(Line.prototype, Path.prototype);
+
+ Path.MakeObservable(Line.prototype);
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ var Path = Two.Path;
+ var _ = Two.Utils;
+
+ var Rectangle = Two.Rectangle = function(x, y, width, height) {
+
+ Path.call(this, [
+ new Two.Anchor(),
+ new Two.Anchor(),
+ new Two.Anchor(),
+ new Two.Anchor()
+ ], true);
+
+ this.width = width;
+ this.height = height;
+ this._update();
+
+ this.translation.set(x, y);
+
+ };
+
+ _.extend(Rectangle, {
+
+ Properties: ['width', 'height'],
+
+ MakeObservable: function(obj) {
+ Path.MakeObservable(obj);
+ _.each(Rectangle.Properties, Two.Utils.defineProperty, obj);
+ }
+
+ });
+
+ _.extend(Rectangle.prototype, Path.prototype, {
+
+ _width: 0,
+ _height: 0,
+
+ _flagWidth: 0,
+ _flagHeight: 0,
+
+ _update: function() {
+
+ if (this._flagWidth || this._flagHeight) {
+
+ var xr = this._width / 2;
+ var yr = this._height / 2;
+
+ this.vertices[0].set(-xr, -yr);
+ this.vertices[1].set(xr, -yr);
+ this.vertices[2].set(xr, yr);
+ this.vertices[3].set(-xr, yr);
+
+ }
+
+ Path.prototype._update.call(this);
+
+ return this;
+
+ },
+
+ flagReset: function() {
+
+ this._flagWidth = this._flagHeight = false;
+ Path.prototype.flagReset.call(this);
+
+ return this;
+
+ }
+
+ });
+
+ Rectangle.MakeObservable(Rectangle.prototype);
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ var Path = Two.Path, TWO_PI = Math.PI * 2, cos = Math.cos, sin = Math.sin;
+ var _ = Two.Utils;
+
+ var Ellipse = Two.Ellipse = function(ox, oy, rx, ry) {
+
+ if (!_.isNumber(ry)) {
+ ry = rx;
+ }
+
+ var amount = Two.Resolution;
+
+ var points = _.map(_.range(amount), function(i) {
+ return new Two.Anchor();
+ }, this);
+
+ Path.call(this, points, true, true);
+
+ this.width = rx * 2;
+ this.height = ry * 2;
+
+ this._update();
+ this.translation.set(ox, oy);
+
+ };
+
+ _.extend(Ellipse, {
+
+ Properties: ['width', 'height'],
+
+ MakeObservable: function(obj) {
+
+ Path.MakeObservable(obj);
+ _.each(Ellipse.Properties, Two.Utils.defineProperty, obj);
+
+ }
+
+ });
+
+ _.extend(Ellipse.prototype, Path.prototype, {
+
+ _width: 0,
+ _height: 0,
+
+ _flagWidth: false,
+ _flagHeight: false,
+
+ _update: function() {
+
+ if (this._flagWidth || this._flagHeight) {
+ for (var i = 0, l = this.vertices.length; i < l; i++) {
+ var pct = i / l;
+ var theta = pct * TWO_PI;
+ var x = this._width * cos(theta) / 2;
+ var y = this._height * sin(theta) / 2;
+ this.vertices[i].set(x, y);
+ }
+ }
+
+ Path.prototype._update.call(this);
+ return this;
+
+ },
+
+ flagReset: function() {
+
+ this._flagWidth = this._flagHeight = false;
+
+ Path.prototype.flagReset.call(this);
+ return this;
+
+ }
+
+ });
+
+ Ellipse.MakeObservable(Ellipse.prototype);
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ var Path = Two.Path, TWO_PI = Math.PI * 2, cos = Math.cos, sin = Math.sin;
+ var _ = Two.Utils;
+
+ var Circle = Two.Circle = function(ox, oy, r) {
+
+ var amount = Two.Resolution;
+
+ var points = _.map(_.range(amount), function(i) {
+ return new Two.Anchor();
+ }, this);
+
+ Path.call(this, points, true, true);
+
+ this.radius = r;
+
+ this._update();
+ this.translation.set(ox, oy);
+
+ };
+
+ _.extend(Circle, {
+
+ Properties: ['radius'],
+
+ MakeObservable: function(obj) {
+
+ Path.MakeObservable(obj);
+ _.each(Circle.Properties, Two.Utils.defineProperty, obj);
+
+ }
+
+ });
+
+ _.extend(Circle.prototype, Path.prototype, {
+
+ _radius: 0,
+ _flagRadius: false,
+
+ _update: function() {
+
+ if (this._flagRadius) {
+ for (var i = 0, l = this.vertices.length; i < l; i++) {
+ var pct = i / l;
+ var theta = pct * TWO_PI;
+ var x = this._radius * cos(theta);
+ var y = this._radius * sin(theta);
+ this.vertices[i].set(x, y);
+ }
+ }
+
+ Path.prototype._update.call(this);
+ return this;
+
+ },
+
+ flagReset: function() {
+
+ this._flagRadius = false;
+
+ Path.prototype.flagReset.call(this);
+ return this;
+
+ }
+
+ });
+
+ Circle.MakeObservable(Circle.prototype);
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ var Path = Two.Path, TWO_PI = Math.PI * 2, cos = Math.cos, sin = Math.sin;
+ var _ = Two.Utils;
+
+ var Polygon = Two.Polygon = function(ox, oy, r, sides) {
+
+ sides = Math.max(sides || 0, 3);
+
+ var points = _.map(_.range(sides), function(i) {
+ return new Two.Anchor();
+ });
+
+ Path.call(this, points, true);
+
+ this.width = r * 2;
+ this.height = r * 2;
+ this.sides = sides;
+
+ this._update();
+ this.translation.set(ox, oy);
+
+ };
+
+ _.extend(Polygon, {
+
+ Properties: ['width', 'height', 'sides'],
+
+ MakeObservable: function(obj) {
+
+ Path.MakeObservable(obj);
+ _.each(Polygon.Properties, Two.Utils.defineProperty, obj);
+
+ }
+
+ });
+
+ _.extend(Polygon.prototype, Path.prototype, {
+
+ _width: 0,
+ _height: 0,
+ _sides: 0,
+
+ _flagWidth: false,
+ _flagHeight: false,
+ _flagSides: false,
+
+ _update: function() {
+
+ if (this._flagWidth || this._flagHeight || this._flagSides) {
+
+ var sides = this._sides;
+ var amount = this.vertices.length;
+
+ if (amount > sides) {
+ this.vertices.splice(sides - 1, amount - sides);
+ }
+
+ for (var i = 0; i < sides; i++) {
+
+ var pct = (i + 0.5) / sides;
+ var theta = TWO_PI * pct + Math.PI / 2;
+ var x = this._width * cos(theta);
+ var y = this._height * sin(theta);
+
+ if (i >= amount) {
+ this.vertices.push(new Two.Anchor(x, y));
+ } else {
+ this.vertices[i].set(x, y);
+ }
+
+ }
+
+ }
+
+ Path.prototype._update.call(this);
+ return this;
+
+ },
+
+ flagReset: function() {
+
+ this._flagWidth = this._flagHeight = this._flagSides = false;
+ Path.prototype.flagReset.call(this);
+
+ return this;
+
+ }
+
+ });
+
+ Polygon.MakeObservable(Polygon.prototype);
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ var Path = Two.Path, PI = Math.PI, TWO_PI = Math.PI * 2, HALF_PI = Math.PI / 2,
+ cos = Math.cos, sin = Math.sin, abs = Math.abs, _ = Two.Utils;
+
+ var ArcSegment = Two.ArcSegment = function(ox, oy, ir, or, sa, ea, res) {
+
+ var points = _.map(_.range(res || (Two.Resolution * 3)), function() {
+ return new Two.Anchor();
+ });
+
+ Path.call(this, points, false, false, true);
+
+ this.innerRadius = ir;
+ this.outerRadius = or;
+
+ this.startAngle = sa;
+ this.endAngle = ea;
+
+ this._update();
+ this.translation.set(ox, oy);
+
+ }
+
+ _.extend(ArcSegment, {
+
+ Properties: ['startAngle', 'endAngle', 'innerRadius', 'outerRadius'],
+
+ MakeObservable: function(obj) {
+
+ Path.MakeObservable(obj);
+ _.each(ArcSegment.Properties, Two.Utils.defineProperty, obj);
+
+ }
+
+ });
+
+ _.extend(ArcSegment.prototype, Path.prototype, {
+
+ _flagStartAngle: false,
+ _flagEndAngle: false,
+ _flagInnerRadius: false,
+ _flagOuterRadius: false,
+
+ _startAngle: 0,
+ _endAngle: TWO_PI,
+ _innerRadius: 0,
+ _outerRadius: 0,
+
+ _update: function() {
+
+ if (this._flagStartAngle || this._flagEndAngle || this._flagInnerRadius
+ || this._flagOuterRadius) {
+
+ var sa = this._startAngle;
+ var ea = this._endAngle;
+
+ var ir = this._innerRadius;
+ var or = this._outerRadius;
+
+ var connected = mod(sa, TWO_PI) === mod(ea, TWO_PI);
+ var punctured = ir > 0;
+
+ var vertices = this.vertices;
+ var length = (punctured ? vertices.length / 2 : vertices.length);
+ var command, id = 0;
+
+ if (connected) {
+ length--;
+ } else if (!punctured) {
+ length -= 2;
+ }
+
+ /**
+ * Outer Circle
+ */
+ for (var i = 0, last = length - 1; i < length; i++) {
+
+ var pct = i / last;
+ var v = vertices[id];
+ var theta = pct * (ea - sa) + sa;
+ var step = (ea - sa) / length;
+
+ var x = or * Math.cos(theta);
+ var y = or * Math.sin(theta);
+
+ switch (i) {
+ case 0:
+ command = Two.Commands.move;
+ break;
+ default:
+ command = Two.Commands.curve;
+ }
+
+ v.command = command;
+ v.x = x;
+ v.y = y;
+ v.controls.left.clear();
+ v.controls.right.clear();
+
+ if (v.command === Two.Commands.curve) {
+ var amp = or * step / Math.PI;
+ v.controls.left.x = amp * Math.cos(theta - HALF_PI);
+ v.controls.left.y = amp * Math.sin(theta - HALF_PI);
+ v.controls.right.x = amp * Math.cos(theta + HALF_PI);
+ v.controls.right.y = amp * Math.sin(theta + HALF_PI);
+ if (i === 1) {
+ v.controls.left.multiplyScalar(2);
+ }
+ if (i === last) {
+ v.controls.right.multiplyScalar(2);
+ }
+ }
+
+ id++;
+
+ }
+
+ if (punctured) {
+
+ if (connected) {
+ vertices[id].command = Two.Commands.close;
+ id++;
+ } else {
+ length--;
+ last = length - 1;
+ }
+
+ /**
+ * Inner Circle
+ */
+ for (i = 0; i < length; i++) {
+
+ pct = i / last;
+ v = vertices[id];
+ theta = (1 - pct) * (ea - sa) + sa;
+ step = (ea - sa) / length;
+
+ x = ir * Math.cos(theta);
+ y = ir * Math.sin(theta);
+ command = Two.Commands.curve;
+ if (i <= 0) {
+ command = connected ? Two.Commands.move : Two.Commands.line;
+ }
+
+ v.command = command;
+ v.x = x;
+ v.y = y;
+ v.controls.left.clear();
+ v.controls.right.clear();
+
+ if (v.command === Two.Commands.curve) {
+ amp = ir * step / Math.PI;
+ v.controls.left.x = amp * Math.cos(theta + HALF_PI);
+ v.controls.left.y = amp * Math.sin(theta + HALF_PI);
+ v.controls.right.x = amp * Math.cos(theta - HALF_PI);
+ v.controls.right.y = amp * Math.sin(theta - HALF_PI);
+ if (i === 1) {
+ v.controls.left.multiplyScalar(2);
+ }
+ if (i === last) {
+ v.controls.right.multiplyScalar(2);
+ }
+ }
+
+ id++;
+
+ }
+
+ } else if (!connected) {
+
+ vertices[id].command = Two.Commands.line;
+ vertices[id].x = 0;
+ vertices[id].y = 0;
+ id++;
+
+ }
+
+ /**
+ * Final Point
+ */
+ vertices[id].command = Two.Commands.close;
+
+ }
+
+ Path.prototype._update.call(this);
+
+ return this;
+
+ },
+
+ flagReset: function() {
+
+ Path.prototype.flagReset.call(this);
+
+ this._flagStartAngle = this._flagEndAngle
+ = this._flagInnerRadius = this._flagOuterRadius = false;
+
+ return this;
+
+ }
+
+ });
+
+ ArcSegment.MakeObservable(ArcSegment.prototype);
+
+ function mod(v, l) {
+ while (v < 0) {
+ v += l;
+ }
+ return v % l;
+ }
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ var Path = Two.Path, TWO_PI = Math.PI * 2, cos = Math.cos, sin = Math.sin;
+ var _ = Two.Utils;
+
+ var Star = Two.Star = function(ox, oy, or, ir, sides) {
+
+ if (!_.isNumber(ir)) {
+ ir = or / 2;
+ }
+
+ if (!_.isNumber(sides) || sides <= 0) {
+ sides = 5;
+ }
+
+ var length = sides * 2;
+
+ var points = _.map(_.range(length), function(i) {
+ return new Two.Anchor();
+ });
+
+ Path.call(this, points, true);
+
+ this.innerRadius = ir;
+ this.outerRadius = or;
+ this.sides = sides;
+
+ this._update();
+ this.translation.set(ox, oy);
+
+ };
+
+ _.extend(Star, {
+
+ Properties: ['innerRadius', 'outerRadius', 'sides'],
+
+ MakeObservable: function(obj) {
+
+ Path.MakeObservable(obj);
+ _.each(Star.Properties, Two.Utils.defineProperty, obj);
+
+ }
+
+ });
+
+ _.extend(Star.prototype, Path.prototype, {
+
+ _innerRadius: 0,
+ _outerRadius: 0,
+ _sides: 0,
+
+ _flagInnerRadius: false,
+ _flagOuterRadius: false,
+ _flagSides: false,
+
+ _update: function() {
+
+ if (this._flagInnerRadius || this._flagOuterRadius || this._flagSides) {
+
+ var sides = this._sides * 2;
+ var amount = this.vertices.length;
+
+ if (amount > sides) {
+ this.vertices.splice(sides - 1, amount - sides);
+ }
+
+ for (var i = 0; i < sides; i++) {
+
+ var pct = (i + 0.5) / sides;
+ var theta = TWO_PI * pct;
+ var r = (i % 2 ? this._innerRadius : this._outerRadius);
+ var x = r * cos(theta);
+ var y = r * sin(theta);
+
+ if (i >= amount) {
+ this.vertices.push(new Two.Anchor(x, y));
+ } else {
+ this.vertices[i].set(x, y);
+ }
+
+ }
+
+ }
+
+ Path.prototype._update.call(this);
+
+ return this;
+
+ },
+
+ flagReset: function() {
+
+ this._flagInnerRadius = this._flagOuterRadius = this._flagSides = false;
+ Path.prototype.flagReset.call(this);
+
+ return this;
+
+ }
+
+ });
+
+ Star.MakeObservable(Star.prototype);
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ var Path = Two.Path;
+ var _ = Two.Utils;
+
+ var RoundedRectangle = Two.RoundedRectangle = function(ox, oy, width, height, radius) {
+
+ if (!_.isNumber(radius)) {
+ radius = Math.floor(Math.min(width, height) / 12);
+ }
+
+ var amount = 10;
+
+ var points = _.map(_.range(amount), function(i) {
+ return new Two.Anchor(0, 0, 0, 0, 0, 0,
+ i === 0 ? Two.Commands.move : Two.Commands.curve);
+ });
+
+ points[points.length - 1].command = Two.Commands.close;
+
+ Path.call(this, points, false, false, true);
+
+ this.width = width;
+ this.height = height;
+ this.radius = radius;
+
+ this._update();
+ this.translation.set(ox, oy);
+
+ };
+
+ _.extend(RoundedRectangle, {
+
+ Properties: ['width', 'height', 'radius'],
+
+ MakeObservable: function(obj) {
+
+ Path.MakeObservable(obj);
+ _.each(RoundedRectangle.Properties, Two.Utils.defineProperty, obj);
+
+ }
+
+ });
+
+ _.extend(RoundedRectangle.prototype, Path.prototype, {
+
+ _width: 0,
+ _height: 0,
+ _radius: 0,
+
+ _flagWidth: false,
+ _flagHeight: false,
+ _flagRadius: false,
+
+ _update: function() {
+
+ if (this._flagWidth || this._flagHeight || this._flagRadius) {
+
+ var width = this._width;
+ var height = this._height;
+ var radius = Math.min(Math.max(this._radius, 0),
+ Math.min(width, height));
+
+ var v;
+ var w = width / 2;
+ var h = height / 2;
+
+ v = this.vertices[0];
+ v.x = - (w - radius);
+ v.y = - h;
+
+ // Upper Right Corner
+
+ v = this.vertices[1];
+ v.x = (w - radius);
+ v.y = - h;
+ v.controls.left.clear();
+ v.controls.right.x = radius;
+ v.controls.right.y = 0;
+
+ v = this.vertices[2];
+ v.x = w;
+ v.y = - (h - radius);
+ v.controls.right.clear();
+ v.controls.left.clear();
+
+ // Bottom Right Corner
+
+ v = this.vertices[3];
+ v.x = w;
+ v.y = (h - radius);
+ v.controls.left.clear();
+ v.controls.right.x = 0;
+ v.controls.right.y = radius;
+
+ v = this.vertices[4];
+ v.x = (w - radius);
+ v.y = h;
+ v.controls.right.clear();
+ v.controls.left.clear();
+
+ // Bottom Left Corner
+
+ v = this.vertices[5];
+ v.x = - (w - radius);
+ v.y = h;
+ v.controls.left.clear();
+ v.controls.right.x = - radius;
+ v.controls.right.y = 0;
+
+ v = this.vertices[6];
+ v.x = - w;
+ v.y = (h - radius);
+ v.controls.left.clear();
+ v.controls.right.clear();
+
+ // Upper Left Corner
+
+ v = this.vertices[7];
+ v.x = - w;
+ v.y = - (h - radius);
+ v.controls.left.clear();
+ v.controls.right.x = 0;
+ v.controls.right.y = - radius;
+
+ v = this.vertices[8];
+ v.x = - (w - radius);
+ v.y = - h;
+ v.controls.left.clear();
+ v.controls.right.clear();
+
+ v = this.vertices[9];
+ v.copy(this.vertices[8]);
+
+ }
+
+ Path.prototype._update.call(this);
+
+ return this;
+
+ },
+
+ flagReset: function() {
+
+ this._flagWidth = this._flagHeight = this._flagRadius = false;
+ Path.prototype.flagReset.call(this);
+
+ return this;
+
+ }
+
+ });
+
+ RoundedRectangle.MakeObservable(RoundedRectangle.prototype);
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ var root = Two.root;
+ var getComputedMatrix = Two.Utils.getComputedMatrix;
+ var _ = Two.Utils;
+
+ var canvas = (root.document ? root.document.createElement('canvas') : { getContext: _.identity });
+ var ctx = canvas.getContext('2d');
+
+ var Text = Two.Text = function(message, x, y, styles) {
+
+ Two.Shape.call(this);
+
+ this._renderer.type = 'text';
+ this._renderer.flagFill = _.bind(Text.FlagFill, this);
+ this._renderer.flagStroke = _.bind(Text.FlagStroke, this);
+
+ this.value = message;
+
+ if (_.isNumber(x)) {
+ this.translation.x = x;
+ }
+ if (_.isNumber(y)) {
+ this.translation.y = y;
+ }
+
+ if (!_.isObject(styles)) {
+ return this;
+ }
+
+ _.each(Two.Text.Properties, function(property) {
+
+ if (property in styles) {
+ this[property] = styles[property];
+ }
+
+ }, this);
+
+ };
+
+ _.extend(Two.Text, {
+
+ Properties: [
+ 'value', 'family', 'size', 'leading', 'alignment', 'linewidth', 'style',
+ 'weight', 'decoration', 'baseline', 'opacity', 'visible', 'fill', 'stroke'
+ ],
+
+ FlagFill: function() {
+ this._flagFill = true;
+ },
+
+ FlagStroke: function() {
+ this._flagStroke = true;
+ },
+
+ MakeObservable: function(object) {
+
+ Two.Shape.MakeObservable(object);
+
+ _.each(Two.Text.Properties.slice(0, 12), Two.Utils.defineProperty, object);
+
+ Object.defineProperty(object, 'fill', {
+ enumerable: true,
+ get: function() {
+ return this._fill;
+ },
+ set: function(f) {
+
+ if (this._fill instanceof Two.Gradient
+ || this._fill instanceof Two.LinearGradient
+ || this._fill instanceof Two.RadialGradient
+ || this._fill instanceof Two.Texture) {
+ this._fill.unbind(Two.Events.change, this._renderer.flagFill);
+ }
+
+ this._fill = f;
+ this._flagFill = true;
+
+ if (this._fill instanceof Two.Gradient
+ || this._fill instanceof Two.LinearGradient
+ || this._fill instanceof Two.RadialGradient
+ || this._fill instanceof Two.Texture) {
+ this._fill.bind(Two.Events.change, this._renderer.flagFill);
+ }
+
+ }
+ });
+
+ Object.defineProperty(object, 'stroke', {
+ enumerable: true,
+ get: function() {
+ return this._stroke;
+ },
+ set: function(f) {
+
+ if (this._stroke instanceof Two.Gradient
+ || this._stroke instanceof Two.LinearGradient
+ || this._stroke instanceof Two.RadialGradient
+ || this._stroke instanceof Two.Texture) {
+ this._stroke.unbind(Two.Events.change, this._renderer.flagStroke);
+ }
+
+ this._stroke = f;
+ this._flagStroke = true;
+
+ if (this._stroke instanceof Two.Gradient
+ || this._stroke instanceof Two.LinearGradient
+ || this._stroke instanceof Two.RadialGradient
+ || this._stroke instanceof Two.Texture) {
+ this._stroke.bind(Two.Events.change, this._renderer.flagStroke);
+ }
+
+ }
+ });
+
+ Object.defineProperty(object, 'clip', {
+ enumerable: true,
+ get: function() {
+ return this._clip;
+ },
+ set: function(v) {
+ this._clip = v;
+ this._flagClip = true;
+ }
+ });
+
+ }
+
+ });
+
+ _.extend(Two.Text.prototype, Two.Shape.prototype, {
+
+ // Flags
+ // http://en.wikipedia.org/wiki/Flag
+
+ _flagValue: true,
+ _flagFamily: true,
+ _flagSize: true,
+ _flagLeading: true,
+ _flagAlignment: true,
+ _flagBaseline: true,
+ _flagStyle: true,
+ _flagWeight: true,
+ _flagDecoration: true,
+
+ _flagFill: true,
+ _flagStroke: true,
+ _flagLinewidth: true,
+ _flagOpacity: true,
+ _flagVisible: true,
+
+ _flagClip: false,
+
+ // Underlying Properties
+
+ _value: '',
+ _family: 'sans-serif',
+ _size: 13,
+ _leading: 17,
+ _alignment: 'center',
+ _baseline: 'middle',
+ _style: 'normal',
+ _weight: 500,
+ _decoration: 'none',
+
+ _fill: '#000',
+ _stroke: 'transparent',
+ _linewidth: 1,
+ _opacity: 1,
+ _visible: true,
+
+ _clip: false,
+
+ remove: function() {
+
+ if (!this.parent) {
+ return this;
+ }
+
+ this.parent.remove(this);
+
+ return this;
+
+ },
+
+ clone: function(parent) {
+
+ var parent = parent || this.parent;
+
+ var clone = new Two.Text(this.value);
+ clone.translation.copy(this.translation);
+ clone.rotation = this.rotation;
+ clone.scale = this.scale;
+
+ _.each(Two.Text.Properties, function(property) {
+ clone[property] = this[property];
+ }, this);
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone;
+
+ },
+
+ toObject: function() {
+
+ var result = {
+ translation: this.translation.toObject(),
+ rotation: this.rotation,
+ scale: this.scale
+ };
+
+ _.each(Two.Text.Properties, function(property) {
+ result[property] = this[property];
+ }, this);
+
+ return result;
+
+ },
+
+ noStroke: function() {
+ this.stroke = 'transparent';
+ return this;
+ },
+
+ noFill: function() {
+ this.fill = 'transparent';
+ return this;
+ },
+
+ /**
+ * A shim to not break `getBoundingClientRect` calls. TODO: Implement a
+ * way to calculate proper bounding boxes of `Two.Text`.
+ */
+ getBoundingClientRect: function(shallow) {
+
+ var matrix, border, l, x, y, i, v;
+
+ var left = Infinity, right = -Infinity,
+ top = Infinity, bottom = -Infinity;
+
+ // TODO: Update this to not __always__ update. Just when it needs to.
+ this._update(true);
+
+ matrix = !!shallow ? this._matrix : getComputedMatrix(this);
+
+ v = matrix.multiply(0, 0, 1);
+
+ return {
+ top: v.x,
+ left: v.y,
+ right: v.x,
+ bottom: v.y,
+ width: 0,
+ height: 0
+ };
+
+ },
+
+ flagReset: function() {
+
+ this._flagValue = this._flagFamily = this._flagSize =
+ this._flagLeading = this._flagAlignment = this._flagFill =
+ this._flagStroke = this._flagLinewidth = this._flagOpaicty =
+ this._flagVisible = this._flagClip = this._flagDecoration =
+ this._flagBaseline = false;
+
+ Two.Shape.prototype.flagReset.call(this);
+
+ return this;
+
+ }
+
+ });
+
+ Two.Text.MakeObservable(Two.Text.prototype);
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ var _ = Two.Utils;
+
+ var Stop = Two.Stop = function(offset, color, opacity) {
+
+ this._renderer = {};
+ this._renderer.type = 'stop';
+
+ this.offset = _.isNumber(offset) ? offset
+ : Stop.Index <= 0 ? 0 : 1;
+
+ this.opacity = _.isNumber(opacity) ? opacity : 1;
+
+ this.color = _.isString(color) ? color
+ : Stop.Index <= 0 ? '#fff' : '#000';
+
+ Stop.Index = (Stop.Index + 1) % 2;
+
+ };
+
+ _.extend(Stop, {
+
+ Index: 0,
+
+ Properties: [
+ 'offset',
+ 'opacity',
+ 'color'
+ ],
+
+ MakeObservable: function(object) {
+
+ _.each(Stop.Properties, function(property) {
+
+ var object = this;
+ var secret = '_' + property;
+ var flag = '_flag' + property.charAt(0).toUpperCase() + property.slice(1);
+
+ Object.defineProperty(object, property, {
+ enumerable: true,
+ get: function() {
+ return this[secret];
+ },
+ set: function(v) {
+ this[secret] = v;
+ this[flag] = true;
+ if (this.parent) {
+ this.parent._flagStops = true;
+ }
+ }
+ });
+
+ }, object);
+
+ }
+
+ });
+
+ _.extend(Stop.prototype, Two.Utils.Events, {
+
+ clone: function() {
+
+ var clone = new Stop();
+
+ _.each(Stop.Properties, function(property) {
+ clone[property] = this[property];
+ }, this);
+
+ return clone;
+
+ },
+
+ toObject: function() {
+
+ var result = {};
+
+ _.each(Stop.Properties, function(k) {
+ result[k] = this[k];
+ }, this);
+
+ return result;
+
+ },
+
+ flagReset: function() {
+
+ this._flagOffset = this._flagColor = this._flagOpacity = false;
+
+ return this;
+
+ }
+
+ });
+
+ Stop.MakeObservable(Stop.prototype);
+
+ var Gradient = Two.Gradient = function(stops) {
+
+ this._renderer = {};
+ this._renderer.type = 'gradient';
+
+ this.id = Two.Identifier + Two.uniqueId();
+ this.classList = [];
+
+ this._renderer.flagStops = _.bind(Gradient.FlagStops, this);
+ this._renderer.bindStops = _.bind(Gradient.BindStops, this);
+ this._renderer.unbindStops = _.bind(Gradient.UnbindStops, this);
+
+ this.spread = 'pad';
+
+ this.stops = stops;
+
+ };
+
+ _.extend(Gradient, {
+
+ Stop: Stop,
+
+ Properties: [
+ 'spread'
+ ],
+
+ MakeObservable: function(object) {
+
+ _.each(Gradient.Properties, Two.Utils.defineProperty, object);
+
+ Object.defineProperty(object, 'stops', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._stops;
+ },
+
+ set: function(stops) {
+
+ var updateStops = this._renderer.flagStops;
+ var bindStops = this._renderer.bindStops;
+ var unbindStops = this._renderer.unbindStops;
+
+ // Remove previous listeners
+ if (this._stops) {
+ this._stops
+ .unbind(Two.Events.insert, bindStops)
+ .unbind(Two.Events.remove, unbindStops);
+ }
+
+ // Create new Collection with copy of Stops
+ this._stops = new Two.Utils.Collection((stops || []).slice(0));
+
+ // Listen for Collection changes and bind / unbind
+ this._stops
+ .bind(Two.Events.insert, bindStops)
+ .bind(Two.Events.remove, unbindStops);
+
+ // Bind Initial Stops
+ bindStops(this._stops);
+
+ }
+
+ });
+
+ },
+
+ FlagStops: function() {
+ this._flagStops = true;
+ },
+
+ BindStops: function(items) {
+
+ // This function is called a lot
+ // when importing a large SVG
+ var i = items.length;
+ while(i--) {
+ items[i].bind(Two.Events.change, this._renderer.flagStops);
+ items[i].parent = this;
+ }
+
+ this._renderer.flagStops();
+
+ },
+
+ UnbindStops: function(items) {
+
+ var i = items.length;
+ while(i--) {
+ items[i].unbind(Two.Events.change, this._renderer.flagStops);
+ delete items[i].parent;
+ }
+
+ this._renderer.flagStops();
+
+ }
+
+ });
+
+ _.extend(Gradient.prototype, Two.Utils.Events, {
+
+ _flagStops: false,
+ _flagSpread: false,
+
+ clone: function(parent) {
+
+ parent = parent || this.parent;
+
+ var stops = _.map(this.stops, function(s) {
+ return s.clone();
+ });
+
+ var clone = new Gradient(stops);
+
+ _.each(Two.Gradient.Properties, function(k) {
+ clone[k] = this[k];
+ }, this);
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone;
+
+ },
+
+ toObject: function() {
+
+ var result = {
+ stops: _.map(this.stops, function(s) {
+ return s.toObject();
+ })
+ };
+
+ _.each(Gradient.Properties, function(k) {
+ result[k] = this[k];
+ }, this);
+
+ return result;
+
+ },
+
+ _update: function() {
+
+ if (this._flagSpread || this._flagStops) {
+ this.trigger(Two.Events.change);
+ }
+
+ return this;
+
+ },
+
+ flagReset: function() {
+
+ this._flagSpread = this._flagStops = false;
+
+ return this;
+
+ }
+
+ });
+
+ Gradient.MakeObservable(Gradient.prototype);
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ var _ = Two.Utils;
+
+ var LinearGradient = Two.LinearGradient = function(x1, y1, x2, y2, stops) {
+
+ Two.Gradient.call(this, stops);
+
+ this._renderer.type = 'linear-gradient';
+
+ var flagEndPoints = _.bind(LinearGradient.FlagEndPoints, this);
+ this.left = new Two.Vector().bind(Two.Events.change, flagEndPoints);
+ this.right = new Two.Vector().bind(Two.Events.change, flagEndPoints);
+
+ if (_.isNumber(x1)) {
+ this.left.x = x1;
+ }
+ if (_.isNumber(y1)) {
+ this.left.y = y1;
+ }
+ if (_.isNumber(x2)) {
+ this.right.x = x2;
+ }
+ if (_.isNumber(y2)) {
+ this.right.y = y2;
+ }
+
+ };
+
+ _.extend(LinearGradient, {
+
+ Stop: Two.Gradient.Stop,
+
+ MakeObservable: function(object) {
+ Two.Gradient.MakeObservable(object);
+ },
+
+ FlagEndPoints: function() {
+ this._flagEndPoints = true;
+ }
+
+ });
+
+ _.extend(LinearGradient.prototype, Two.Gradient.prototype, {
+
+ _flagEndPoints: false,
+
+ clone: function(parent) {
+
+ parent = parent || this.parent;
+
+ var stops = _.map(this.stops, function(stop) {
+ return stop.clone();
+ });
+
+ var clone = new LinearGradient(this.left._x, this.left._y,
+ this.right._x, this.right._y, stops);
+
+ _.each(Two.Gradient.Properties, function(k) {
+ clone[k] = this[k];
+ }, this);
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone;
+
+ },
+
+ toObject: function() {
+
+ var result = Two.Gradient.prototype.toObject.call(this);
+
+ result.left = this.left.toObject();
+ result.right = this.right.toObject();
+
+ return result;
+
+ },
+
+ _update: function() {
+
+ if (this._flagEndPoints || this._flagSpread || this._flagStops) {
+ this.trigger(Two.Events.change);
+ }
+
+ return this;
+
+ },
+
+ flagReset: function() {
+
+ this._flagEndPoints = false;
+
+ Two.Gradient.prototype.flagReset.call(this);
+
+ return this;
+
+ }
+
+ });
+
+ LinearGradient.MakeObservable(LinearGradient.prototype);
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ var _ = Two.Utils;
+
+ var RadialGradient = Two.RadialGradient = function(cx, cy, r, stops, fx, fy) {
+
+ Two.Gradient.call(this, stops);
+
+ this._renderer.type = 'radial-gradient';
+
+ this.center = new Two.Vector()
+ .bind(Two.Events.change, _.bind(function() {
+ this._flagCenter = true;
+ }, this));
+
+ this.radius = _.isNumber(r) ? r : 20;
+
+ this.focal = new Two.Vector()
+ .bind(Two.Events.change, _.bind(function() {
+ this._flagFocal = true;
+ }, this));
+
+ if (_.isNumber(cx)) {
+ this.center.x = cx;
+ }
+ if (_.isNumber(cy)) {
+ this.center.y = cy;
+ }
+
+ this.focal.copy(this.center);
+
+ if (_.isNumber(fx)) {
+ this.focal.x = fx;
+ }
+ if (_.isNumber(fy)) {
+ this.focal.y = fy;
+ }
+
+ };
+
+ _.extend(RadialGradient, {
+
+ Stop: Two.Gradient.Stop,
+
+ Properties: [
+ 'radius'
+ ],
+
+ MakeObservable: function(object) {
+
+ Two.Gradient.MakeObservable(object);
+
+ _.each(RadialGradient.Properties, Two.Utils.defineProperty, object);
+
+ }
+
+ });
+
+ _.extend(RadialGradient.prototype, Two.Gradient.prototype, {
+
+ _flagRadius: false,
+ _flagCenter: false,
+ _flagFocal: false,
+
+ clone: function(parent) {
+
+ parent = parent || this.parent;
+
+ var stops = _.map(this.stops, function(stop) {
+ return stop.clone();
+ });
+
+ var clone = new RadialGradient(this.center._x, this.center._y,
+ this._radius, stops, this.focal._x, this.focal._y);
+
+ _.each(Two.Gradient.Properties.concat(RadialGradient.Properties), function(k) {
+ clone[k] = this[k];
+ }, this);
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone;
+
+ },
+
+ toObject: function() {
+
+ var result = Two.Gradient.prototype.toObject.call(this);
+
+ _.each(RadialGradient.Properties, function(k) {
+ result[k] = this[k];
+ }, this);
+
+ result.center = this.center.toObject();
+ result.focal = this.focal.toObject();
+
+ return result;
+
+ },
+
+ _update: function() {
+
+ if (this._flagRadius || this._flatCenter || this._flagFocal
+ || this._flagSpread || this._flagStops) {
+ this.trigger(Two.Events.change);
+ }
+
+ return this;
+
+ },
+
+ flagReset: function() {
+
+ this._flagRadius = this._flagCenter = this._flagFocal = false;
+
+ Two.Gradient.prototype.flagReset.call(this);
+
+ return this;
+
+ }
+
+ });
+
+ RadialGradient.MakeObservable(RadialGradient.prototype);
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ var _ = Two.Utils;
+ var anchor;
+ var regex = {
+ video: /\.(mp4|webm)$/i,
+ image: /\.(jpe?g|png|gif|tiff)$/i
+ };
+
+ if (this.document) {
+ anchor = document.createElement('a');
+ }
+
+ var Texture = Two.Texture = function(src, callback) {
+
+ this._renderer = {};
+ this._renderer.type = 'texture';
+ this._renderer.flagOffset = _.bind(Texture.FlagOffset, this);
+ this._renderer.flagScale = _.bind(Texture.FlagScale, this);
+
+ this.id = Two.Identifier + Two.uniqueId();
+ this.classList = [];
+
+ this.offset = new Two.Vector();
+
+ if (_.isFunction(callback)) {
+ var loaded = _.bind(function() {
+ this.unbind(Two.Events.load, loaded);
+ if (_.isFunction(callback)) {
+ callback();
+ }
+ }, this);
+ this.bind(Two.Events.load, loaded);
+ }
+
+ if (_.isString(src)) {
+ this.src = src;
+ } else if (_.isElement(src)) {
+ this.image = src;
+ }
+
+ this._update();
+
+ };
+
+ _.extend(Texture, {
+
+ Properties: [
+ 'src',
+ 'loaded',
+ 'repeat'
+ ],
+
+ ImageRegistry: new Two.Registry(),
+
+ getAbsoluteURL: function(path) {
+ if (!anchor) {
+ // TODO: Fix for headless environment
+ return path;
+ }
+ anchor.href = path;
+ return anchor.href;
+ },
+
+ getImage: function(src) {
+
+ var absoluteSrc = Texture.getAbsoluteURL(src);
+
+ if (Texture.ImageRegistry.contains(absoluteSrc)) {
+ return Texture.ImageRegistry.get(absoluteSrc);
+ }
+
+ var image;
+
+ if (regex.video.test(absoluteSrc)) {
+ image = document.createElement('video');
+ } else {
+ image = document.createElement('img');
+ }
+
+ image.crossOrigin = 'anonymous';
+
+ return image;
+
+ },
+
+ Register: {
+ canvas: function(texture, callback) {
+ texture._src = '#' + texture.id;
+ Texture.ImageRegistry.add(texture.src, texture.image);
+ if (_.isFunction(callback)) {
+ callback();
+ }
+ },
+ img: function(texture, callback) {
+
+ var loaded = function(e) {
+ texture.image.removeEventListener('load', loaded, false);
+ texture.image.removeEventListener('error', error, false);
+ if (_.isFunction(callback)) {
+ callback();
+ }
+ };
+ var error = function(e) {
+ texture.image.removeEventListener('load', loaded, false);
+ texture.image.removeEventListener('error', error, false);
+ throw new Two.Utils.Error('unable to load ' + texture.src);
+ };
+
+ if (_.isNumber(texture.image.width) && texture.image.width > 0
+ && _.isNumber(texture.image.height) && texture.image.height > 0) {
+ loaded();
+ } else {
+ texture.image.addEventListener('load', loaded, false);
+ texture.image.addEventListener('error', error, false);
+ }
+
+ texture._src = Texture.getAbsoluteURL(texture._src);
+
+ if (texture.image && texture.image.getAttribute('two-src')) {
+ return;
+ }
+
+ texture.image.setAttribute('two-src', texture.src);
+ Texture.ImageRegistry.add(texture.src, texture.image);
+ texture.image.src = texture.src;
+
+ },
+ video: function(texture, callback) {
+
+ var loaded = function(e) {
+ texture.image.removeEventListener('load', loaded, false);
+ texture.image.removeEventListener('error', error, false);
+ texture.image.width = texture.image.videoWidth;
+ texture.image.height = texture.image.videoHeight;
+ texture.image.play();
+ if (_.isFunction(callback)) {
+ callback();
+ }
+ };
+ var error = function(e) {
+ texture.image.removeEventListener('load', loaded, false);
+ texture.image.removeEventListener('error', error, false);
+ throw new Two.Utils.Error('unable to load ' + texture.src);
+ };
+
+ texture._src = Texture.getAbsoluteURL(texture._src);
+ texture.image.addEventListener('canplaythrough', loaded, false);
+ texture.image.addEventListener('error', error, false);
+
+ if (texture.image && texture.image.getAttribute('two-src')) {
+ return;
+ }
+
+ texture.image.setAttribute('two-src', texture.src);
+ Texture.ImageRegistry.add(texture.src, texture.image);
+ texture.image.src = texture.src;
+ texture.image.loop = true;
+ texture.image.load();
+
+ }
+ },
+
+ load: function(texture, callback) {
+
+ var src = texture.src;
+ var image = texture.image;
+ var tag = image && image.nodeName.toLowerCase();
+
+ if (texture._flagImage) {
+ if (/canvas/i.test(tag)) {
+ Texture.Register.canvas(texture, callback);
+ } else {
+ texture._src = image.getAttribute('two-src') || image.src;
+ Texture.Register[tag](texture, callback);
+ }
+ }
+
+ if (texture._flagSrc) {
+ if (!image) {
+ texture.image = Texture.getImage(texture.src);
+ }
+ tag = texture.image.nodeName.toLowerCase();
+ Texture.Register[tag](texture, callback);
+ }
+
+ },
+
+ FlagOffset: function() {
+ this._flagOffset = true;
+ },
+
+ FlagScale: function() {
+ this._flagScale = true;
+ },
+
+ MakeObservable: function(object) {
+
+ _.each(Texture.Properties, Two.Utils.defineProperty, object);
+
+ Object.defineProperty(object, 'image', {
+ enumerable: true,
+ get: function() {
+ return this._image;
+ },
+ set: function(image) {
+
+ var tag = image && image.nodeName.toLowerCase();
+ var index;
+
+ switch (tag) {
+ case 'canvas':
+ index = '#' + image.id;
+ break;
+ default:
+ index = image.src;
+ }
+
+ if (Texture.ImageRegistry.contains(index)) {
+ this._image = Texture.ImageRegistry.get(image.src);
+ } else {
+ this._image = image;
+ }
+
+ this._flagImage = true;
+
+ }
+
+ });
+
+ Object.defineProperty(object, 'offset', {
+ enumerable: true,
+ get: function() {
+ return this._offset;
+ },
+ set: function(v) {
+ if (this._offset) {
+ this._offset.unbind(Two.Events.change, this._renderer.flagOffset);
+ }
+ this._offset = v;
+ this._offset.bind(Two.Events.change, this._renderer.flagOffset);
+ this._flagOffset = true;
+ }
+ });
+
+ Object.defineProperty(object, 'scale', {
+ enumerable: true,
+ get: function() {
+ return this._scale;
+ },
+ set: function(v) {
+
+ if (this._scale instanceof Two.Vector) {
+ this._scale.unbind(Two.Events.change, this._renderer.flagScale);
+ }
+
+ this._scale = v;
+
+ if (this._scale instanceof Two.Vector) {
+ this._scale.bind(Two.Events.change, this._renderer.flagScale);
+ }
+
+ this._flagScale = true;
+
+ }
+ });
+
+ }
+
+ });
+
+ _.extend(Texture.prototype, Two.Utils.Events, Two.Shape.prototype, {
+
+ _flagSrc: false,
+ _flagImage: false,
+ _flagVideo: false,
+ _flagLoaded: false,
+ _flagRepeat: false,
+
+ _flagOffset: false,
+ _flagScale: false,
+
+ _src: '',
+ _image: null,
+ _loaded: false,
+ _repeat: 'no-repeat',
+
+ _scale: 1,
+ _offset: null,
+
+ clone: function() {
+ return new Texture(this.src);
+ },
+
+ toObject: function() {
+ return {
+ src: this.src,
+ image: this.image
+ }
+ },
+
+ _update: function() {
+
+ if (this._flagSrc || this._flagImage || this._flagVideo) {
+
+ this.trigger(Two.Events.change);
+
+ if (this._flagSrc || this._flagImage) {
+ this.loaded = false;
+ Texture.load(this, _.bind(function() {
+ this.loaded = true;
+ this
+ .trigger(Two.Events.change)
+ .trigger(Two.Events.load);
+ }, this));
+ }
+
+ }
+
+ if (this._image && this._image.readyState >= 4) {
+ this._flagVideo = true;
+ }
+
+ return this;
+
+ },
+
+ flagReset: function() {
+
+ this._flagSrc = this._flagImage = this._flagLoaded
+ = this._flagVideo = this._flagScale = this._flagOffset = false;
+
+ return this;
+
+ }
+
+ });
+
+ Texture.MakeObservable(Texture.prototype);
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ var _ = Two.Utils;
+ var Path = Two.Path;
+ var Rectangle = Two.Rectangle;
+
+ var Sprite = Two.Sprite = function(path, ox, oy, cols, rows, frameRate) {
+
+ Path.call(this, [
+ new Two.Anchor(),
+ new Two.Anchor(),
+ new Two.Anchor(),
+ new Two.Anchor()
+ ], true);
+
+ this.noStroke();
+ this.noFill();
+
+ if (path instanceof Two.Texture) {
+ this.texture = path;
+ } else if (_.isString(path)) {
+ this.texture = new Two.Texture(path);
+ }
+
+ this._update();
+ this.translation.set(ox || 0, oy || 0);
+
+ if (_.isNumber(cols)) {
+ this.columns = cols;
+ }
+ if (_.isNumber(rows)) {
+ this.rows = rows;
+ }
+ if (_.isNumber(frameRate)) {
+ this.frameRate = frameRate;
+ }
+
+ };
+
+ _.extend(Sprite, {
+
+ Properties: [
+ 'texture', 'columns', 'rows', 'frameRate', 'index'
+ ],
+
+ MakeObservable: function(obj) {
+
+ Rectangle.MakeObservable(obj);
+ _.each(Sprite.Properties, Two.Utils.defineProperty, obj);
+
+ }
+
+ })
+
+ _.extend(Sprite.prototype, Rectangle.prototype, {
+
+ _flagTexture: false,
+ _flagColumns: false,
+ _flagRows: false,
+ _flagFrameRate: false,
+ flagIndex: false,
+
+ // Private variables
+ _amount: 1,
+ _duration: 0,
+ _startTime: 0,
+ _playing: false,
+ _firstFrame: 0,
+ _lastFrame: 0,
+ _loop: true,
+
+ // Exposed through getter-setter
+ _texture: null,
+ _columns: 1,
+ _rows: 1,
+ _frameRate: 0,
+ _index: 0,
+
+ play: function(firstFrame, lastFrame, onLastFrame) {
+
+ this._playing = true;
+ this._firstFrame = 0;
+ this._lastFrame = this.amount - 1;
+ this._startTime = _.performance.now();
+
+ if (_.isNumber(firstFrame)) {
+ this._firstFrame = firstFrame;
+ }
+ if (_.isNumber(lastFrame)) {
+ this._lastFrame = lastFrame;
+ }
+ if (_.isFunction(onLastFrame)) {
+ this._onLastFrame = onLastFrame;
+ } else {
+ delete this._onLastFrame;
+ }
+
+ if (this._index !== this._firstFrame) {
+ this._startTime -= 1000 * Math.abs(this._index - this._firstFrame)
+ / this._frameRate;
+ }
+
+ return this;
+
+ },
+
+ pause: function() {
+
+ this._playing = false;
+ return this;
+
+ },
+
+ stop: function() {
+
+ this._playing = false;
+ this._index = 0;
+
+ return this;
+
+ },
+
+ clone: function(parent) {
+
+ parent = parent || this.parent;
+
+ var clone = new Sprite(
+ this.texture, this.translation.x, this.translation.y,
+ this.columns, this.rows, this.frameRate
+ );
+
+ if (this.playing) {
+ clone.play(this._firstFrame, this._lastFrame);
+ clone._loop = this._loop;
+ }
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone;
+
+ },
+
+ _update: function() {
+
+ var effect = this._texture;
+ var cols = this._columns;
+ var rows = this._rows;
+
+ var width, height, elapsed, amount, duration;
+ var index, iw, ih, isRange, frames;
+
+ if (this._flagColumns || this._flagRows) {
+ this._amount = this._columns * this._rows;
+ }
+
+ if (this._flagFrameRate) {
+ this._duration = 1000 * this._amount / this._frameRate;
+ }
+
+ if (this._flagTexture) {
+ this.fill = this._texture;
+ }
+
+ if (this._texture.loaded) {
+
+ iw = effect.image.width;
+ ih = effect.image.height;
+
+ width = iw / cols;
+ height = ih / rows;
+ amount = this._amount;
+
+ if (this.width !== width) {
+ this.width = width;
+ }
+ if (this.height !== height) {
+ this.height = height;
+ }
+
+ if (this._playing && this._frameRate > 0) {
+
+ if (_.isNaN(this._lastFrame)) {
+ this._lastFrame = amount - 1;
+ }
+
+ // TODO: Offload perf logic to instance of `Two`.
+ elapsed = _.performance.now() - this._startTime;
+ frames = this._lastFrame + 1;
+ duration = 1000 * (frames - this._firstFrame) / this._frameRate;
+
+ if (this._loop) {
+ elapsed = elapsed % duration;
+ } else {
+ elapsed = Math.min(elapsed, duration);
+ }
+
+ index = _.lerp(this._firstFrame, frames, elapsed / duration);
+ index = Math.floor(index);
+
+ if (index !== this._index) {
+ this._index = index;
+ if (index >= this._lastFrame - 1 && this._onLastFrame) {
+ this._onLastFrame(); // Shortcut for chainable sprite animations
+ }
+ }
+
+ }
+
+ var col = this._index % cols;
+ var row = Math.floor(this._index / cols);
+
+ var ox = - width * col + (iw - width) / 2;
+ var oy = - height * row + (ih - height) / 2;
+
+ // TODO: Improve performance
+ if (ox !== effect.offset.x) {
+ effect.offset.x = ox;
+ }
+ if (oy !== effect.offset.y) {
+ effect.offset.y = oy;
+ }
+
+ }
+
+ Rectangle.prototype._update.call(this);
+
+ return this;
+
+ },
+
+ flagReset: function() {
+
+ this._flagTexture = this._flagColumns = this._flagRows
+ = this._flagFrameRate = false;
+
+ Rectangle.prototype.flagReset.call(this);
+
+ return this;
+ }
+
+
+ });
+
+ Sprite.MakeObservable(Sprite.prototype);
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ var _ = Two.Utils;
+ var Path = Two.Path;
+ var Rectangle = Two.Rectangle;
+
+ var ImageSequence = Two.ImageSequence = function(paths, ox, oy, frameRate) {
+
+ Path.call(this, [
+ new Two.Anchor(),
+ new Two.Anchor(),
+ new Two.Anchor(),
+ new Two.Anchor()
+ ], true);
+
+ this._renderer.flagTextures = _.bind(ImageSequence.FlagTextures, this);
+ this._renderer.bindTextures = _.bind(ImageSequence.BindTextures, this);
+ this._renderer.unbindTextures = _.bind(ImageSequence.UnbindTextures, this);
+
+ this.noStroke();
+ this.noFill();
+
+ this.textures = _.map(paths, ImageSequence.GenerateTexture, this);
+
+ this._update();
+ this.translation.set(ox || 0, oy || 0);
+
+ if (_.isNumber(frameRate)) {
+ this.frameRate = frameRate;
+ } else {
+ this.frameRate = ImageSequence.DefaultFrameRate;
+ }
+
+ };
+
+ _.extend(ImageSequence, {
+
+ Properties: [
+ 'frameRate',
+ 'index'
+ ],
+
+ DefaultFrameRate: 30,
+
+ FlagTextures: function() {
+ this._flagTextures = true;
+ },
+
+ BindTextures: function(items) {
+
+ var i = items.length;
+ while (i--) {
+ items[i].bind(Two.Events.change, this._renderer.flagTextures);
+ }
+
+ this._renderer.flagTextures();
+
+ },
+
+ UnbindTextures: function(items) {
+
+ var i = items.length;
+ while (i--) {
+ items[i].unbind(Two.Events.change, this._renderer.flagTextures);
+ }
+
+ this._renderer.flagTextures();
+
+ },
+
+ MakeObservable: function(obj) {
+
+ Rectangle.MakeObservable(obj);
+ _.each(ImageSequence.Properties, Two.Utils.defineProperty, obj);
+
+ Object.defineProperty(obj, 'textures', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._textures;
+ },
+
+ set: function(textures) {
+
+ var updateTextures = this._renderer.flagTextures;
+ var bindTextures = this._renderer.bindTextures;
+ var unbindTextures = this._renderer.unbindTextures;
+
+ // Remove previous listeners
+ if (this._textures) {
+ this._textures
+ .unbind(Two.Events.insert, bindTextures)
+ .unbind(Two.Events.remove, unbindTextures);
+ }
+
+ // Create new Collection with copy of vertices
+ this._textures = new Two.Utils.Collection((textures || []).slice(0));
+
+ // Listen for Collection changes and bind / unbind
+ this._textures
+ .bind(Two.Events.insert, bindTextures)
+ .bind(Two.Events.remove, unbindTextures);
+
+ // Bind Initial Textures
+ bindTextures(this._textures);
+
+ }
+
+ });
+
+ },
+
+ GenerateTexture: function(obj) {
+ if (obj instanceof Two.Texture) {
+ return obj;
+ } else if (_.isString(obj)) {
+ return new Two.Texture(obj);
+ }
+ }
+
+ });
+
+ _.extend(ImageSequence.prototype, Rectangle.prototype, {
+
+ _flagTextures: false,
+ _flagFrameRate: false,
+ _flagIndex: false,
+
+ // Private variables
+ _amount: 1,
+ _duration: 0,
+ _index: 0,
+ _startTime: 0,
+ _playing: false,
+ _firstFrame: 0,
+ _lastFrame: 0,
+ _loop: true,
+
+ // Exposed through getter-setter
+ _textures: null,
+ _frameRate: 0,
+
+ play: function(firstFrame, lastFrame, onLastFrame) {
+
+ this._playing = true;
+ this._firstFrame = 0;
+ this._lastFrame = this.amount - 1;
+ this._startTime = _.performance.now();
+
+ if (_.isNumber(firstFrame)) {
+ this._firstFrame = firstFrame;
+ }
+ if (_.isNumber(lastFrame)) {
+ this._lastFrame = lastFrame;
+ }
+ if (_.isFunction(onLastFrame)) {
+ this._onLastFrame = onLastFrame;
+ } else {
+ delete this._onLastFrame;
+ }
+
+ if (this._index !== this._firstFrame) {
+ this._startTime -= 1000 * Math.abs(this._index - this._firstFrame)
+ / this._frameRate;
+ }
+
+ return this;
+
+ },
+
+ pause: function() {
+
+ this._playing = false;
+ return this;
+
+ },
+
+ stop: function() {
+
+ this._playing = false;
+ this._index = 0;
+
+ return this;
+
+ },
+
+ clone: function(parent) {
+
+ parent = parent || this.parent;
+
+ var clone = new ImageSequence(this.textures, this.translation.x,
+ this.translation.y, this.frameRate)
+
+ clone._loop = this._loop;
+
+ if (this._playing) {
+ clone.play();
+ }
+
+ if (parent) {
+ parent.add(clone);
+ }
+
+ return clone;
+
+ },
+
+ _update: function() {
+
+ var effects = this._textures;
+ var width, height, elapsed, amount, duration, texture;
+ var index, frames;
+
+ if (this._flagTextures) {
+ this._amount = effects.length;
+ }
+
+ if (this._flagFrameRate) {
+ this._duration = 1000 * this._amount / this._frameRate;
+ }
+
+ if (this._playing && this._frameRate > 0) {
+
+ amount = this._amount;
+
+ if (_.isNaN(this._lastFrame)) {
+ this._lastFrame = amount - 1;
+ }
+
+ // TODO: Offload perf logic to instance of `Two`.
+ elapsed = _.performance.now() - this._startTime;
+ frames = this._lastFrame + 1;
+ duration = 1000 * (frames - this._firstFrame) / this._frameRate;
+
+ if (this._loop) {
+ elapsed = elapsed % duration;
+ } else {
+ elapsed = Math.min(elapsed, duration);
+ }
+
+ index = _.lerp(this._firstFrame, frames, elapsed / duration);
+ index = Math.floor(index);
+
+ if (index !== this._index) {
+
+ this._index = index;
+ texture = effects[this._index];
+
+ if (texture.loaded) {
+
+ width = texture.image.width;
+ height = texture.image.height;
+
+ if (this.width !== width) {
+ this.width = width;
+ }
+ if (this.height !== height) {
+ this.height = height;
+ }
+
+ this.fill = texture;
+
+ if (index >= this._lastFrame - 1 && this._onLastFrame) {
+ this._onLastFrame(); // Shortcut for chainable sprite animations
+ }
+
+ }
+
+ }
+
+ } else if (this._flagIndex || !(this.fill instanceof Two.Texture)) {
+
+ texture = effects[this._index];
+
+ if (texture.loaded) {
+
+ width = texture.image.width;
+ height = texture.image.height;
+
+ if (this.width !== width) {
+ this.width = width;
+ }
+ if (this.height !== height) {
+ this.height = height;
+ }
+
+ }
+
+ this.fill = texture;
+
+ }
+
+ Rectangle.prototype._update.call(this);
+
+ return this;
+
+ },
+
+ flagReset: function() {
+
+ this._flagTextures = this._flagFrameRate = false;
+ Rectangle.prototype.flagReset.call(this);
+
+ return this;
+
+ }
+
+ });
+
+ ImageSequence.MakeObservable(ImageSequence.prototype);
+
+})((typeof global !== 'undefined' ? global : this).Two);
+
+(function(Two) {
+
+ /**
+ * Constants
+ */
+ var min = Math.min, max = Math.max;
+ var _ = Two.Utils;
+
+ /**
+ * A children collection which is accesible both by index and by object id
+ * @constructor
+ */
+ var Children = function() {
+
+ Two.Utils.Collection.apply(this, arguments);
+
+ Object.defineProperty(this, '_events', {
+ value : {},
+ enumerable: false
+ });
+
+ this.ids = {};
+
+ this.on(Two.Events.insert, this.attach);
+ this.on(Two.Events.remove, this.detach);
+ Children.prototype.attach.apply(this, arguments);
+
+ };
+
+ Children.prototype = new Two.Utils.Collection();
+ Children.prototype.constructor = Children;
+
+ _.extend(Children.prototype, {
+
+ attach: function(children) {
+ for (var i = 0; i < children.length; i++) {
+ this.ids[children[i].id] = children[i];
+ }
+ return this;
+ },
+
+ detach: function(children) {
+ for (var i = 0; i < children.length; i++) {
+ delete this.ids[children[i].id];
+ }
+ return this;
+ }
+
+ });
+
+ var Group = Two.Group = function() {
+
+ Two.Shape.call(this, true);
+
+ this._renderer.type = 'group';
+
+ this.additions = [];
+ this.subtractions = [];
+
+ this.children = arguments;
+
+ };
+
+ _.extend(Group, {
+
+ Children: Children,
+
+ InsertChildren: function(children) {
+ for (var i = 0; i < children.length; i++) {
+ replaceParent.call(this, children[i], this);
+ }
+ },
+
+ RemoveChildren: function(children) {
+ for (var i = 0; i < children.length; i++) {
+ replaceParent.call(this, children[i]);
+ }
+ },
+
+ OrderChildren: function(children) {
+ this._flagOrder = true;
+ },
+
+ MakeObservable: function(object) {
+
+ var properties = Two.Path.Properties.slice(0);
+ var oi = _.indexOf(properties, 'opacity');
+
+ if (oi >= 0) {
+
+ properties.splice(oi, 1);
+
+ Object.defineProperty(object, 'opacity', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._opacity;
+ },
+
+ set: function(v) {
+ // Only set flag if there is an actual difference
+ this._flagOpacity = (this._opacity != v);
+ this._opacity = v;
+ }
+
+ });
+
+ }
+
+ Two.Shape.MakeObservable(object);
+ Group.MakeGetterSetters(object, properties);
+
+ Object.defineProperty(object, 'children', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._children;
+ },
+
+ set: function(children) {
+
+ var insertChildren = _.bind(Group.InsertChildren, this);
+ var removeChildren = _.bind(Group.RemoveChildren, this);
+ var orderChildren = _.bind(Group.OrderChildren, this);
+
+ if (this._children) {
+ this._children.unbind();
+ }
+
+ this._children = new Children(children);
+ this._children.bind(Two.Events.insert, insertChildren);
+ this._children.bind(Two.Events.remove, removeChildren);
+ this._children.bind(Two.Events.order, orderChildren);
+
+ }
+
+ });
+
+ Object.defineProperty(object, 'mask', {
+
+ enumerable: true,
+
+ get: function() {
+ return this._mask;
+ },
+
+ set: function(v) {
+ this._mask = v;
+ this._flagMask = true;
+ if (!v.clip) {
+ v.clip = true;
+ }
+ }
+
+ });
+
+ },
+
+ MakeGetterSetters: function(group, properties) {
+
+ if (!_.isArray(properties)) {
+ properties = [properties];
+ }
+
+ _.each(properties, function(k) {
+ Group.MakeGetterSetter(group, k);
+ });
+
+ },
+
+ MakeGetterSetter: function(group, k) {
+
+ var secret = '_' + k;
+
+ Object.defineProperty(group, k, {
+
+ enumerable: true,
+
+ get: function() {
+ return this[secret];
+ },
+
+ set: function(v) {
+ this[secret] = v;
+ _.each(this.children, function(child) { // Trickle down styles
+ child[k] = v;
+ });
+ }
+
+ });
+
+ }
+
+ });
+
+ _.extend(Group.prototype, Two.Shape.prototype, {
+
+ // Flags
+ // http://en.wikipedia.org/wiki/Flag
+
+ _flagAdditions: false,
+ _flagSubtractions: false,
+ _flagOrder: false,
+ _flagOpacity: true,
+
+ _flagMask: false,
+
+ // Underlying Properties
+
+ _fill: '#fff',
+ _stroke: '#000',
+ _linewidth: 1.0,
+ _opacity: 1.0,
+ _visible: true,
+
+ _cap: 'round',
+ _join: 'round',
+ _miter: 4,
+
+ _closed: true,
+ _curved: false,
+ _automatic: true,
+ _beginning: 0,
+ _ending: 1.0,
+
+ _mask: null,
+
+ /**
+ * TODO: Group has a gotcha in that it's at the moment required to be bound to
+ * an instance of two in order to add elements correctly. This needs to
+ * be rethought and fixed.
+ */
+ clone: function(parent) {
+
+ parent = parent || this.parent;
+
+ var group = new Group();
+ var children = _.map(this.children, function(child) {
+ return child.clone(group);
+ });
+
+ group.add(children);
+
+ group.opacity = this.opacity;
+
+ if (this.mask) {
+ group.mask = this.mask;
+ }
+
+ group.translation.copy(this.translation);
+ group.rotation = this.rotation;
+ group.scale = this.scale;
+
+ if (parent) {
+ parent.add(group);
+ }
+
+ return group;
+
+ },
+
+ /**
+ * Export the data from the instance of Two.Group into a plain JavaScript
+ * object. This also makes all children plain JavaScript objects. Great
+ * for turning into JSON and storing in a database.
+ */
+ toObject: function() {
+
+ var result = {
+ children: [],
+ translation: this.translation.toObject(),
+ rotation: this.rotation,
+ scale: this.scale,
+ opacity: this.opacity,
+ mask: (this.mask ? this.mask.toObject() : null)
+ };
+
+ _.each(this.children, function(child, i) {
+ result.children[i] = child.toObject();
+ }, this);
+
+ return result;
+
+ },
+
+ /**
+ * Anchor all children to the upper left hand corner
+ * of the group.
+ */
+ corner: function() {
+
+ var rect = this.getBoundingClientRect(true),
+ corner = { x: rect.left, y: rect.top };
+
+ this.children.forEach(function(child) {
+ child.translation.subSelf(corner);
+ });
+
+ return this;
+
+ },
+
+ /**
+ * Anchors all children around the center of the group,
+ * effectively placing the shape around the unit circle.
+ */
+ center: function() {
+
+ var rect = this.getBoundingClientRect(true);
+
+ rect.centroid = {
+ x: rect.left + rect.width / 2,
+ y: rect.top + rect.height / 2
+ };
+
+ this.children.forEach(function(child) {
+ if (child.isShape) {
+ child.translation.subSelf(rect.centroid);
+ }
+ });
+
+ // this.translation.copy(rect.centroid);
+
+ return this;
+
+ },
+
+ /**
+ * Recursively search for id. Returns the first element found.
+ * Returns null if none found.
+ */
+ getById: function (id) {
+ var search = function (node, id) {
+ if (node.id === id) {
+ return node;
+ } else if (node.children) {
+ var i = node.children.length;
+ while (i--) {
+ var found = search(node.children[i], id);
+ if (found) return found;
+ }
+ }
+
+ };
+ return search(this, id) || null;
+ },
+
+ /**
+ * Recursively search for classes. Returns an array of matching elements.
+ * Empty array if none found.
+ */
+ getByClassName: function (cl) {
+ var found = [];
+ var search = function (node, cl) {
+ if (node.classList.indexOf(cl) != -1) {
+ found.push(node);
+ } else if (node.children) {
+ node.children.forEach(function (child) {
+ search(child, cl);
+ });
+ }
+ return found;
+ };
+ return search(this, cl);
+ },
+
+ /**
+ * Recursively search for children of a specific type,
+ * e.g. Two.Polygon. Pass a reference to this type as the param.
+ * Returns an empty array if none found.
+ */
+ getByType: function(type) {
+ var found = [];
+ var search = function (node, type) {
+ for (var id in node.children) {
+ if (node.children[id] instanceof type) {
+ found.push(node.children[id]);
+ } else if (node.children[id] instanceof Two.Group) {
+ search(node.children[id], type);
+ }
+ }
+ return found;
+ };
+ return search(this, type);
+ },
+
+ /**
+ * Add objects to the group.
+ */
+ add: function(objects) {
+
+ // Allow to pass multiple objects either as array or as multiple arguments
+ // If it's an array also create copy of it in case we're getting passed
+ // a childrens array directly.
+ if (!(objects instanceof Array)) {
+ objects = _.toArray(arguments);
+ } else {
+ objects = objects.slice();
+ }
+
+ // Add the objects
+ for (var i = 0; i < objects.length; i++) {
+ if (!(objects[i] && objects[i].id)) continue;
+ this.children.push(objects[i]);
+ }
+
+ return this;
+
+ },
+
+ /**
+ * Remove objects from the group.
+ */
+ remove: function(objects) {
+
+ var l = arguments.length,
+ grandparent = this.parent;
+
+ // Allow to call remove without arguments
+ // This will detach the object from the scene.
+ if (l <= 0 && grandparent) {
+ grandparent.remove(this);
+ return this;
+ }
+
+ // Allow to pass multiple objects either as array or as multiple arguments
+ // If it's an array also create copy of it in case we're getting passed
+ // a childrens array directly.
+ if (!(objects instanceof Array)) {
+ objects = _.toArray(arguments);
+ } else {
+ objects = objects.slice();
+ }
+
+ // Remove the objects
+ for (var i = 0; i < objects.length; i++) {
+ if (!objects[i] || !(this.children.ids[objects[i].id])) continue;
+ this.children.splice(_.indexOf(this.children, objects[i]), 1);
+ }
+
+ return this;
+
+ },
+
+ /**
+ * Return an object with top, left, right, bottom, width, and height
+ * parameters of the group.
+ */
+ getBoundingClientRect: function(shallow) {
+ var rect;
+
+ // TODO: Update this to not __always__ update. Just when it needs to.
+ this._update(true);
+
+ // Variables need to be defined here, because of nested nature of groups.
+ var left = Infinity, right = -Infinity,
+ top = Infinity, bottom = -Infinity;
+
+ this.children.forEach(function(child) {
+
+ if (/(linear-gradient|radial-gradient|gradient)/.test(child._renderer.type)) {
+ return;
+ }
+
+ rect = child.getBoundingClientRect(shallow);
+
+ if (!_.isNumber(rect.top) || !_.isNumber(rect.left) ||
+ !_.isNumber(rect.right) || !_.isNumber(rect.bottom)) {
+ return;
+ }
+
+ top = min(rect.top, top);
+ left = min(rect.left, left);
+ right = max(rect.right, right);
+ bottom = max(rect.bottom, bottom);
+
+ }, this);
+
+ return {
+ top: top,
+ left: left,
+ right: right,
+ bottom: bottom,
+ width: right - left,
+ height: bottom - top
+ };
+
+ },
+
+ /**
+ * Trickle down of noFill
+ */
+ noFill: function() {
+ this.children.forEach(function(child) {
+ child.noFill();
+ });
+ return this;
+ },
+
+ /**
+ * Trickle down of noStroke
+ */
+ noStroke: function() {
+ this.children.forEach(function(child) {
+ child.noStroke();
+ });
+ return this;
+ },
+
+ /**
+ * Trickle down subdivide
+ */
+ subdivide: function() {
+ var args = arguments;
+ this.children.forEach(function(child) {
+ child.subdivide.apply(child, args);
+ });
+ return this;
+ },
+
+ flagReset: function() {
+
+ if (this._flagAdditions) {
+ this.additions.length = 0;
+ this._flagAdditions = false;
+ }
+
+ if (this._flagSubtractions) {
+ this.subtractions.length = 0;
+ this._flagSubtractions = false;
+ }
+
+ this._flagOrder = this._flagMask = this._flagOpacity = false;
+
+ Two.Shape.prototype.flagReset.call(this);
+
+ return this;
+
+ }
+
+ });
+
+ Group.MakeObservable(Group.prototype);
+
+ /**
+ * Helper function used to sync parent-child relationship within the
+ * `Two.Group.children` object.
+ *
+ * Set the parent of the passed object to another object
+ * and updates parent-child relationships
+ * Calling with one arguments will simply remove the parenting
+ */
+ function replaceParent(child, newParent) {
+
+ var parent = child.parent;
+ var index;
+
+ if (parent === newParent) {
+ this.additions.push(child);
+ this._flagAdditions = true;
+ return;
+ }
+
+ if (parent && parent.children.ids[child.id]) {
+
+ index = _.indexOf(parent.children, child);
+ parent.children.splice(index, 1);
+
+ // If we're passing from one parent to another...
+ index = _.indexOf(parent.additions, child);
+
+ if (index >= 0) {
+ parent.additions.splice(index, 1);
+ } else {
+ parent.subtractions.push(child);
+ parent._flagSubtractions = true;
+ }
+
+ }
+
+ if (newParent) {
+ child.parent = newParent;
+ this.additions.push(child);
+ this._flagAdditions = true;
+ return;
+ }
+
+ // If we're passing from one parent to another...
+ index = _.indexOf(this.additions, child);
+
+ if (index >= 0) {
+ this.additions.splice(index, 1);
+ } else {
+ this.subtractions.push(child);
+ this._flagSubtractions = true;
+ }
+
+ delete child.parent;
+
+ }
+
+})((typeof global !== 'undefined' ? global : this).Two);
diff --git a/debian/patches/boost-url.patch b/debian/patches/boost-url.patch
new file mode 100644
index 000000000..4513ace0d
--- /dev/null
+++ b/debian/patches/boost-url.patch
@@ -0,0 +1,63 @@
+commit 857eedbe6c9ed80ed0625bd0aa27b1a1e85f8d59
+Author: Adam C. Emerson <aemerson@redhat.com>
+Date: Mon May 20 16:22:28 2024 -0400
+
+ mds: Use Boost::url rather than `src.hpp`
+
+ As `src.hpp` is no longer supported.
+
+ Signed-off-by: Adam Emerson <aemerson@redhat.com>
+
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -667,7 +667,7 @@
+ # Boost::thread depends on Boost::atomic, so list it explicitly.
+ set(BOOST_COMPONENTS
+ atomic chrono thread system regex random program_options date_time
+- iostreams context coroutine)
++ iostreams context coroutine url)
+ set(BOOST_HEADER_COMPONENTS container)
+
+ if(WITH_MGR)
+--- a/src/mds/BoostUrlImpl.cc
++++ /dev/null
+@@ -1,8 +0,0 @@
+-/*
+- * https://www.boost.org/doc/libs/1_82_0/libs/url/doc/html/url/overview.html#url.overview.requirements
+- *
+- * To use the library as header-only; that is, to eliminate the requirement
+- * to link a program to a static or dynamic Boost.URL library,
+- * simply place the following line in exactly one source file in your project.
+- */
+-#include <boost/url/src.hpp>
+--- a/src/mds/CMakeLists.txt
++++ b/src/mds/CMakeLists.txt
+@@ -45,12 +45,12 @@
+ QuiesceDbManager.cc
+ QuiesceAgent.cc
+ MDSRankQuiesce.cc
+- BoostUrlImpl.cc
+ ${CMAKE_SOURCE_DIR}/src/common/TrackedOp.cc
+ ${CMAKE_SOURCE_DIR}/src/common/MemoryModel.cc
+ ${CMAKE_SOURCE_DIR}/src/osdc/Journaler.cc
+ ${CMAKE_SOURCE_DIR}/src/mgr/MDSPerfMetricTypes.cc)
+ add_library(mds STATIC ${mds_srcs})
+ target_link_libraries(mds PRIVATE
++ Boost::url
+ heap_profiler cpu_profiler osdc ${LUA_LIBRARIES})
+ target_include_directories(mds PRIVATE "${LUA_INCLUDE_DIR}")
+--- a/src/test/mds/CMakeLists.txt
++++ b/src/test/mds/CMakeLists.txt
+@@ -18,11 +18,10 @@
+ add_executable(unittest_mds_quiesce_db
+ TestQuiesceDb.cc
+ ../../../src/mds/QuiesceDbManager.cc
+- ../../../src/mds/BoostUrlImpl.cc
+ $<TARGET_OBJECTS:unit-main>
+ )
+ add_ceph_unittest(unittest_mds_quiesce_db)
+-target_link_libraries(unittest_mds_quiesce_db ceph-common global)
++target_link_libraries(unittest_mds_quiesce_db ceph-common global Boost::url)
+
+ # unittest_mds_quiesce_agent
+ add_executable(unittest_mds_quiesce_agent
diff --git a/debian/patches/bug1914584.patch b/debian/patches/bug1914584.patch
new file mode 100644
index 000000000..714e8cb56
--- /dev/null
+++ b/debian/patches/bug1914584.patch
@@ -0,0 +1,44 @@
+From a8c1aec073fc8364818027a26fa1ddb5d34c58af Mon Sep 17 00:00:00 2001
+From: Matthew Vernon <mv3@sanger.ac.uk>
+Date: Thu, 4 Feb 2021 11:41:14 +0000
+Subject: [PATCH] rgw/radosgw-admin clarify error when email address already in
+ use
+
+The error message if you try and create an S3 user with an email
+address that is already associated with another S3 account is very
+confusing; this patch makes it much clearer
+
+To reproduce:
+
+radosgw-admin user create --uid=foo --display-name="Foo test" --email=bar@domain.invalid
+radosgw-admin user create --uid=test --display-name="AN test" --email=bar@domain.invalid
+could not create user: unable to parse parameters, user id mismatch, operation id: foo does not match: test
+
+With this patch:
+
+radosgw-admin user create --uid=test --display-name="AN test" --email=bar@domain.invalid
+could not create user: unable to create user test because user id foo already exists with email bar@domain.invalid
+
+Fixes: https://tracker.ceph.com/issues/49137
+Fixes: https://tracker.ceph.com/issues/19411
+Signed-off-by: Matthew Vernon <mv3@sanger.ac.uk>
+(cherry picked from commit 05318d6f71e45a42a46518a0ef17047dfab83990)
+---
+--- a/src/rgw/driver/rados/rgw_user.cc
++++ b/src/rgw/driver/rados/rgw_user.cc
+@@ -834,7 +834,14 @@
+
+ ret = check_op(op_state, &subprocess_msg);
+ if (ret < 0) {
+- set_err_msg(err_msg, "unable to parse request, " + subprocess_msg);
++ if (op_state.is_populated() && (user_id == op_state.get_user_id())) {
++ set_err_msg(err_msg, "unable to create user " + user_id.to_str ()
++ + " because user id " + op_state.get_user_id().to_str()
++ + " already exists with email "
++ + op_state.get_user_email());
++ } else {
++ set_err_msg(err_msg, "unable to parse request, " + subprocess_msg);
++ }
+ return ret;
+ }
+
diff --git a/debian/patches/ceph-exporter-systemd.patch b/debian/patches/ceph-exporter-systemd.patch
new file mode 100644
index 000000000..6c3cbefcf
--- /dev/null
+++ b/debian/patches/ceph-exporter-systemd.patch
@@ -0,0 +1,60 @@
+commit 32cbe079c60031f67ee91e2f74f39244a027eba6
+Author: Shinya Hayashi <shinya-hayashi@cybozu.co.jp>
+Date: Mon Feb 5 04:16:26 2024 +0000
+
+ systemd: add systemd unit file for ceph-exporter
+
+ Signed-off-by: Shinya Hayashi <shinya-hayashi@cybozu.co.jp>
+
+--- a/ceph.spec.in
++++ b/ceph.spec.in
+@@ -2091,6 +2091,7 @@
+
+ %files -n ceph-exporter
+ %{_bindir}/ceph-exporter
++%{_unitdir}/ceph-exporter.service
+
+ %files -n rbd-fuse
+ %{_bindir}/rbd-fuse
+--- a/systemd/CMakeLists.txt
++++ b/systemd/CMakeLists.txt
+@@ -14,6 +14,7 @@
+ set(SYSTEMD_ENV_FILE "${CEPH_SYSTEMD_ENV_DIR}/ceph")
+ foreach(service
+ ceph-crash
++ ceph-exporter
+ ceph-fuse@
+ ceph-mds@
+ ceph-mgr@
+--- /dev/null
++++ b/systemd/ceph-exporter.service.in
+@@ -0,0 +1,29 @@
++[Unit]
++Description=Ceph cluster exporter daemon
++PartOf=ceph.target
++After=network-online.target local-fs.target
++Before=ceph.target
++Wants=network-online.target local-fs.target ceph.target ceph-mon.target
++
++[Service]
++ExecReload=/bin/kill -HUP $MAINPID
++ExecStart=/usr/bin/ceph-exporter -f --id %i --setuser ceph --setgroup ceph
++LockPersonality=true
++NoNewPrivileges=true
++PrivateDevices=yes
++PrivateTmp=true
++ProtectControlGroups=true
++ProtectHome=true
++ProtectHostname=true
++ProtectKernelLogs=true
++ProtectKernelModules=true
++ProtectKernelTunables=true
++ProtectSystem=full
++Restart=on-failure
++RestartSec=10
++RestrictSUIDSGID=true
++StartLimitBurst=3
++StartLimitInterval=30min
++
++[Install]
++WantedBy=multi-user.target ceph.target
diff --git a/debian/patches/dout-fix.patch b/debian/patches/dout-fix.patch
new file mode 100644
index 000000000..b3eda49ea
--- /dev/null
+++ b/debian/patches/dout-fix.patch
@@ -0,0 +1,23 @@
+Description: Fix FTBFS issue in dout subsystem
+Author: Luciano Lo Giudice <luciano.logiudice@canonical.com>
+Forwarded: no
+
+--- a/src/common/dout.h
++++ b/src/common/dout.h
+@@ -157,15 +157,7 @@
+ #define dout_impl(cct, sub, v) \
+ do { \
+ const bool should_gather = [&](const auto cctX) { \
+- if constexpr (ceph::dout::is_dynamic<decltype(sub)>::value || \
+- ceph::dout::is_dynamic<decltype(v)>::value) { \
+- return cctX->_conf->subsys.should_gather(sub, v); \
+- } else { \
+- /* The parentheses are **essential** because commas in angle \
+- * brackets are NOT ignored on macro expansion! A language's \
+- * limitation, sorry. */ \
+- return (cctX->_conf->subsys.template should_gather<sub, v>()); \
+- } \
++ return cctX->_conf->subsys.should_gather(sub, v); \
+ }(cct); \
+ \
+ if (should_gather) { \
diff --git a/debian/patches/enable-strsignal.patch b/debian/patches/enable-strsignal.patch
new file mode 100644
index 000000000..f5647d96c
--- /dev/null
+++ b/debian/patches/enable-strsignal.patch
@@ -0,0 +1,16 @@
+Description: This defines HAVE_REENTRANT_STRSIGNAL as sys_siglist no longer
+ exists with glibc 2.32 and all programs should use strsignal instead.
+Forwarded: no
+Last-Update: 2020-09-21
+
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -566,7 +566,7 @@
+ set(HAVE_THREAD_SAFE_RES_QUERY 1 CACHE INTERNAL "Thread safe res_query supported.")
+ endif()
+
+-option(WITH_REENTRANT_STRSIGNAL "strsignal is reentrant" OFF)
++option(WITH_REENTRANT_STRSIGNAL "strsignal is reentrant" ON)
+ if(WITH_REENTRANT_STRSIGNAL)
+ set(HAVE_REENTRANT_STRSIGNAL 1 CACHE INTERNAL "Reentrant strsignal is supported.")
+ endif()
diff --git a/debian/patches/fix-CheckCxxAtomic-riscv64.patch b/debian/patches/fix-CheckCxxAtomic-riscv64.patch
new file mode 100644
index 000000000..a1a2bebae
--- /dev/null
+++ b/debian/patches/fix-CheckCxxAtomic-riscv64.patch
@@ -0,0 +1,16 @@
+Description: Fix CheckCxxAtomic to detect more accurately
+ Some platforms like riscv64 does not have full support for atomic primitives,
+ yet passes the test. Adding operator++ fixes this issue.
+Author: Eric Long <i@hack3r.moe>
+Last-Update: 2022-08-30
+--- a/cmake/modules/CheckCxxAtomic.cmake
++++ b/cmake/modules/CheckCxxAtomic.cmake
+@@ -47,7 +47,7 @@
+ std::atomic<uint16_t> w2;
+ std::atomic<uint32_t> w4;
+ std::atomic<uint64_t> w8;
+- return w1 + w2 + w4 + w8;
++ return ++w1 + ++w2 + ++w4 + ++w8;
+ }
+ " ${var})
+ endfunction(check_cxx_atomics)
diff --git a/debian/patches/fix-bash-completion-location b/debian/patches/fix-bash-completion-location
new file mode 100644
index 000000000..eb05b9e15
--- /dev/null
+++ b/debian/patches/fix-bash-completion-location
@@ -0,0 +1,9 @@
+--- a/src/bash_completion/CMakeLists.txt
++++ b/src/bash_completion/CMakeLists.txt
+@@ -11,5 +11,5 @@
+ endif()
+
+ install(FILES ${completions}
+- DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/bash_completion.d)
++ DESTINATION /usr/share/bash-completion/completions)
+
diff --git a/debian/patches/fix-cephadm-build.patch b/debian/patches/fix-cephadm-build.patch
new file mode 100644
index 000000000..bf63b5a32
--- /dev/null
+++ b/debian/patches/fix-cephadm-build.patch
@@ -0,0 +1,45 @@
+Description: Fix building cephadm with no internet
+Author: Luciano Lo Giudice <luciano.logiudice@canonical.com>
+Forwarded: no
+
+--- a/src/cephadm/CMakeLists.txt
++++ b/src/cephadm/CMakeLists.txt
+@@ -21,7 +21,7 @@
+ --set-version-var=CEPH_RELEASE=${CEPH_RELEASE}
+ --set-version-var=CEPH_RELEASE_NAME=${CEPH_RELEASE_NAME}
+ --set-version-var=CEPH_RELEASE_TYPE=${CEPH_RELEASE_TYPE}
+- --bundled-dependencies=${CEPHADM_BUNDLED_DEPENDENCIES}
++ --bundled-dependencies=none
+ ${bin_target_file}
+ )
+
+@@ -31,3 +31,7 @@
+ install(PROGRAMS
+ ${bin_target_file}
+ DESTINATION ${CMAKE_INSTALL_SBINDIR})
++
++install(DIRECTORY
++ cephadmlib
++ DESTINATION ${Python3_SITELIB})
+--- a/src/cephadm/build.py
++++ b/src/cephadm/build.py
+@@ -346,7 +346,7 @@
+ if has_venv:
+ log.info('Attempting to create a virtualenv')
+ venv = tempdir / "_venv_"
+- _run([sys.executable, '-m', 'venv', str(venv)])
++ _run([sys.executable, '-m', 'venv', str(venv), "--system-site-packages"])
+ executable = str(venv / "bin" / pathlib.Path(executable).name)
+ # try to upgrade pip in the virtualenv. if it fails ignore the error
+ _run([executable, '-m', 'pip', 'install', '-U', 'pip'])
+--- a/src/cephadm/cephadmlib/host_facts.py
++++ b/src/cephadm/cephadmlib/host_facts.py
+@@ -719,7 +719,7 @@
+ else:
+ summary = {} # type: Dict[str, int]
+ for line in profiles.split('\n'):
+- item, mode = line.split(' ')
++ *_, mode = line.split(' ')
+ mode = mode.strip('()')
+ if mode in summary:
+ summary[mode] += 1
diff --git a/debian/patches/fix-fmt-check.patch b/debian/patches/fix-fmt-check.patch
new file mode 100644
index 000000000..74a375f14
--- /dev/null
+++ b/debian/patches/fix-fmt-check.patch
@@ -0,0 +1,15 @@
+Description: Fix CMake check
+Author: Luciano Lo Giudice <luciano.logiudice@canonical.com>
+Forwarded: no
+
+--- a/src/seastar/cmake/CheckGcc107852.cmake
++++ b/src/seastar/cmake/CheckGcc107852.cmake
+@@ -7,7 +7,7 @@
+ # Seastar_PRIVATE_CXX_FLAGS, which is not applied to CMAKE_CXX_FLAGS, so
+ # let's apply them explicitly.
+ set (CMAKE_REQUIRED_FLAGS "-Werror=stringop-overflow -Werror=array-bound")
+-set (CMAKE_REQUIRED_LIBRARIES fmt::fmt)
++set (CMAKE_REQUIRED_LIBRARIES fmt)
+
+ # see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107852
+ check_cxx_source_compiles ("
diff --git a/debian/patches/fix-mantic-misc.patch b/debian/patches/fix-mantic-misc.patch
new file mode 100644
index 000000000..443f5ca22
--- /dev/null
+++ b/debian/patches/fix-mantic-misc.patch
@@ -0,0 +1,35 @@
+Description: Fixes for Ubuntu Mantic
+Author: Luciano Lo Giudice <luciano.logiudice@canonical.com>
+Forwarded: no
+
+--- a/src/seastar/include/seastar/net/packet.hh
++++ b/src/seastar/include/seastar/net/packet.hh
+@@ -105,7 +105,7 @@
+ unsigned _len = 0;
+ uint16_t _nr_frags = 0;
+ uint16_t _allocated_frags;
+- offload_info _offload_info;
++ struct offload_info _offload_info;
+ std::optional<uint32_t> _rss_hash;
+ char _data[internal_data_size]; // only _frags[0] may use
+ unsigned _headroom = internal_data_size; // in _data
+--- a/src/spdk/lib/iscsi/iscsi.c
++++ b/src/spdk/lib/iscsi/iscsi.c
+@@ -103,7 +103,7 @@
+ static int g_arc4random_initialized = 0;
+
+ static uint32_t
+-arc4random(void)
++rpl_arc4random(void)
+ {
+ uint32_t r;
+ uint32_t r1, r2;
+@@ -117,6 +117,8 @@
+ r = (r1 << 16) | r2;
+ return r;
+ }
++
++#define arc4random rpl_arc4random
+ #endif /* HAVE_ARC4RANDOM */
+
+ static void
diff --git a/debian/patches/logentry-c++23-compat.patch b/debian/patches/logentry-c++23-compat.patch
new file mode 100644
index 000000000..8c4506b18
--- /dev/null
+++ b/debian/patches/logentry-c++23-compat.patch
@@ -0,0 +1,21 @@
+commit b854bfcc70ff372cd087c068e0302d36ad86391f
+Author: Ronen Friedman <rfriedma@redhat.com>
+Date: Sun Mar 3 16:30:59 2024 +0200
+
+ common: fix string creation from '0' in LogEntry
+
+ C++23 disallows conversion from 'int' to 'string'.
+ That includes returning '0' from a function that returns a string.
+
+ Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
+
+--- a/src/common/LogEntry.cc
++++ b/src/common/LogEntry.cc
+@@ -73,7 +73,6 @@
+ return LOG_CRIT;
+ default:
+ ceph_abort();
+- return 0;
+ }
+ }
+
diff --git a/debian/patches/lp1986747-fix-osd-class-dir.patch b/debian/patches/lp1986747-fix-osd-class-dir.patch
new file mode 100644
index 000000000..0b8a3fa1d
--- /dev/null
+++ b/debian/patches/lp1986747-fix-osd-class-dir.patch
@@ -0,0 +1,21 @@
+Description: Fix rados-classes search path.
+ .
+ The commit 3bee4b0 changed the
+ base of the osd_class_dir path from CMAKE_INSTALL_FULL_LIBDIR to
+ CMAKE_INSTALL_LIBDIR. This change aligns the default value with the
+ correct value.
+Author: Chris MacNaughton <chris.macnaughton@ubuntu.com>
+Forwarded: https://github.com/ceph/ceph/pull/47676
+Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/ceph/+bug/1986747
+
+--- a/src/common/options/osd.yaml.in
++++ b/src/common/options/osd.yaml.in
+@@ -534,7 +534,7 @@
+ - name: osd_class_dir
+ type: str
+ level: advanced
+- default: @CMAKE_INSTALL_LIBDIR@/rados-classes
++ default: @CMAKE_INSTALL_FULL_LIBDIR@/rados-classes
+ fmt_desc: The class path for RADOS class plug-ins.
+ with_legacy: true
+ - name: osd_open_classes_on_start
diff --git a/debian/patches/lp2080208.patch b/debian/patches/lp2080208.patch
new file mode 100644
index 000000000..fc91ff189
--- /dev/null
+++ b/debian/patches/lp2080208.patch
@@ -0,0 +1,46 @@
+From 12cc90a8dac62824c9326f5a4b31744c3f2bf10b Mon Sep 17 00:00:00 2001
+From: Peter Sabaini <peter.sabaini@canonical.com>
+Date: Wed, 11 Sep 2024 16:56:50 +0200
+Subject: [PATCH] ceph-volume: fix importlib.metadata compat
+
+The importlib.metadata library removed older shims in releases >5.0.0
+where EntryPoints objects use .select() instead of dict-like access.
+
+Fixes: https://tracker.ceph.com/issues/68032
+
+Signed-off-by: Peter Sabaini <peter.sabaini@canonical.com>
+---
+ src/ceph-volume/ceph_volume/main.py | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/src/ceph-volume/ceph_volume/main.py b/src/ceph-volume/ceph_volume/main.py
+index f8eca65ec497c..110ccf727c82e 100644
+--- a/src/ceph-volume/ceph_volume/main.py
++++ b/src/ceph-volume/ceph_volume/main.py
+@@ -9,15 +9,25 @@
+ # `entry_points` from `importlib.metadata` does not.
+ try:
+ from importlib.metadata import entry_points
++ from importlib.metadata import EntryPoints
+
+ def get_entry_points(group: str): # type: ignore
+- return entry_points().get(group, []) # type: ignore
++ eps = entry_points()
++ if isinstance(eps, EntryPoints) and hasattr(eps, 'select'):
++ # New importlib.metadata uses .select()
++ return eps.select(group=group)
++ else:
++ # Fallback to older EntryPoints that returns dicts
++ return eps.get(group, []) # type: ignore
++
+ except ImportError:
++ # Fallback to `pkg_resources` for older versions
+ from pkg_resources import iter_entry_points as entry_points # type: ignore
+
+ def get_entry_points(group: str): # type: ignore
+ return entry_points(group=group) # type: ignore
+
++
+ from ceph_volume.decorators import catches
+ from ceph_volume import log, devices, configuration, conf, exceptions, terminal, inventory, drive_group, activate
+
diff --git a/debian/patches/mgr-distutils.patch b/debian/patches/mgr-distutils.patch
new file mode 100644
index 000000000..e995a188a
--- /dev/null
+++ b/debian/patches/mgr-distutils.patch
@@ -0,0 +1,32 @@
+Description: Use vendored distutils from setuptools
+ Due to the way Python executes in the mgr process, it
+ avoids the distutils_hack which injects the vendored
+ distutils in setuptools in system modules.
+ .
+ Longer term this needs removing, but for the time
+ being directly reference the vendored distutils module.
+Author: James Page <james.page@ubuntu.com>
+Forwarded: not-needed
+
+--- a/src/pybind/mgr/dashboard/tools.py
++++ b/src/pybind/mgr/dashboard/tools.py
+@@ -9,7 +9,7 @@
+ import time
+ import urllib
+ from datetime import datetime, timedelta
+-from distutils.util import strtobool
++from setuptools._distutils.util import strtobool
+
+ import cherrypy
+ from mgr_util import build_url
+--- a/src/pybind/mgr/volumes/fs/operations/pin_util.py
++++ b/src/pybind/mgr/volumes/fs/operations/pin_util.py
+@@ -3,7 +3,7 @@
+ import cephfs
+
+ from ..exception import VolumeException
+-from distutils.util import strtobool
++from setuptools._distutils.util import strtobool
+
+ _pin_value = {
+ "export": lambda x: int(x),
diff --git a/debian/patches/pass-build-flags.patch b/debian/patches/pass-build-flags.patch
new file mode 100644
index 000000000..51be7dbce
--- /dev/null
+++ b/debian/patches/pass-build-flags.patch
@@ -0,0 +1,25 @@
+Description: Pass build flags when building Python extensions
+Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/ceph/+bug/2078244
+Bug-Gentoo: https://bugs.gentoo.org/866159
+Bug-Gentoo: https://bugs.gentoo.org/866161
+Origin: gentoo, https://github.com/gentoo/gentoo/commit/c588d0c55a2facb7b98331abf3ccb2439cc34286
+Author: Patrick McLean <chutzpah@gentoo.org>
+Last-Update: 2022-08-24
+
+--- a/cmake/modules/Distutils.cmake
++++ b/cmake/modules/Distutils.cmake
+@@ -93,12 +93,12 @@
+ COMMAND
+ env
+ CC="${PY_CC}"
+- CFLAGS="${PY_CFLAGS}"
++ CFLAGS="${PY_CFLAGS}"\ ${CMAKE_C_FLAGS}
+ CPPFLAGS="${PY_CPPFLAGS}"
+ CXX="${PY_CXX}"
+ LDSHARED="${PY_LDSHARED}"
+ OPT=\"-DNDEBUG -g -fwrapv -O2 -w\"
+- LDFLAGS=-L${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
++ LDFLAGS=-L${CMAKE_LIBRARY_OUTPUT_DIRECTORY}\ ${CMAKE_LINKER_FLAGS}\ ${CMAKE_SHARED_LINKER_FLAGS}
+ CYTHON_BUILD_DIR=${CMAKE_CURRENT_BINARY_DIR}
+ CEPH_LIBDIR=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
+ ${Python3_EXECUTABLE} ${setup_py}
diff --git a/debian/patches/ppc64el-fix-linking.patch b/debian/patches/ppc64el-fix-linking.patch
new file mode 100644
index 000000000..d395ed51e
--- /dev/null
+++ b/debian/patches/ppc64el-fix-linking.patch
@@ -0,0 +1,24 @@
+Description: Switch back to static linking
+ Resolves linking failures on ppc64el
+Author: James Page <james.page@canonical.com>
+Forwarded: not-needed
+
+--- a/src/common/CMakeLists.txt
++++ b/src/common/CMakeLists.txt
+@@ -230,7 +230,7 @@
+ crc32c_aarch64.c)
+ endif(HAVE_INTEL)
+
+-add_library(crc32 OBJECT ${crc32_srcs})
++add_library(crc32 STATIC ${crc32_srcs})
+
+ if(HAVE_ARMV8_CRC)
+ set_target_properties(crc32 PROPERTIES
+--- a/src/arch/CMakeLists.txt
++++ b/src/arch/CMakeLists.txt
+@@ -9,4 +9,4 @@
+ list(APPEND arch_srcs ppc.c)
+ endif()
+
+-add_library(arch OBJECT ${arch_srcs})
++add_library(arch STATIC ${arch_srcs})
diff --git a/debian/patches/riscv64-link-pthread.patch b/debian/patches/riscv64-link-pthread.patch
new file mode 100644
index 000000000..782b6ed7b
--- /dev/null
+++ b/debian/patches/riscv64-link-pthread.patch
@@ -0,0 +1,14 @@
+Description: Link with -pthread instead of -lpthread to fix FTBFS on riscv64
+Forwarded: no
+Last-Update: 2020-03-01
+
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -25,6 +25,7 @@
+
+ if(CMAKE_SYSTEM_NAME MATCHES "Linux")
+ set(LINUX ON)
++ set(THREADS_PREFER_PTHREAD_FLAG ON)
+ FIND_PACKAGE(Threads)
+ elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+ set(FREEBSD ON)
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 000000000..5340a4474
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1,22 @@
+lp1986747-fix-osd-class-dir.patch
+enable-strsignal.patch
+update-java-source-target-flags.patch
+# Debian misc fixes
+fix-bash-completion-location
+riscv64-link-pthread.patch
+# text relocation fix AARCH64
+bug1914584.patch
+spdk_top-string-format.patch
+spdk-fix-make-exe.patch
+fix-CheckCxxAtomic-riscv64.patch
+fix-mantic-misc.patch
+fix-fmt-check.patch
+fix-cephadm-build.patch
+ppc64el-fix-linking.patch
+mgr-distutils.patch
+boost-url.patch
+logentry-c++23-compat.patch
+ceph-exporter-systemd.patch
+dout-fix.patch
+lp2080208.patch
+pass-build-flags.patch
diff --git a/debian/patches/spdk-fix-make-exe.patch b/debian/patches/spdk-fix-make-exe.patch
new file mode 100644
index 000000000..441bd00ff
--- /dev/null
+++ b/debian/patches/spdk-fix-make-exe.patch
@@ -0,0 +1,22 @@
+--- a/cmake/modules/BuildSPDK.cmake
++++ b/cmake/modules/BuildSPDK.cmake
+@@ -55,7 +55,7 @@
+ # unset $CFLAGS, otherwise it will interfere with how SPDK sets
+ # its include directory.
+ # unset $LDFLAGS, otherwise SPDK will fail to mock some functions.
+- BUILD_COMMAND env -i PATH=$ENV{PATH} CC=${CMAKE_C_COMPILER} ${make_cmd} EXTRA_CFLAGS=${spdk_CFLAGS}
++ BUILD_COMMAND env -i V=1 PATH=$ENV{PATH} CC=${CMAKE_C_COMPILER} ${MAKE_EXECUTABLE} EXTRA_CFLAGS=${spdk_CFLAGS}
+ BUILD_IN_SOURCE 1
+ BUILD_BYPRODUCTS ${spdk_libs}
+ INSTALL_COMMAND ""
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -288,7 +288,7 @@
+ endif()
+
+ CMAKE_DEPENDENT_OPTION(WITH_SPDK "Enable SPDK" OFF
+- "CMAKE_SYSTEM_PROCESSOR MATCHES i386|i686|amd64|x86_64|AMD64|aarch64" OFF)
++ "CMAKE_SYSTEM_PROCESSOR MATCHES xxx" OFF)
+ if(WITH_SPDK)
+ if(NOT WITH_BLUESTORE)
+ message(SEND_ERROR "Please enable WITH_BLUESTORE for using SPDK")
diff --git a/debian/patches/spdk_top-string-format.patch b/debian/patches/spdk_top-string-format.patch
new file mode 100644
index 000000000..b2667afb2
--- /dev/null
+++ b/debian/patches/spdk_top-string-format.patch
@@ -0,0 +1,39 @@
+Description: spdk_top: always use "%s"-style format for printf()-style functions
+ `ncuses-6.3` added printf-style function attributes and now makes
+ it easier to catch cases when user input is used in palce of format
+ string when built with CFLAGS=-Werror=format-security:
+
+ spdk_top.c:1135:34: error: format not a string literal and no format arguments [-Werror=format-security]
+ 1135 | mvwprintw(win, row, col, tmp_str);
+ | ^~~~~~~
+
+ Let's wrap all the missing places with "%s" format.
+
+Origin: https://review.spdk.io/gerrit/c/spdk/spdk/+/10300
+--- a/src/spdk/app/spdk_top/spdk_top.c
++++ b/src/spdk/app/spdk_top/spdk_top.c
+@@ -655,7 +655,7 @@
+ snprintf(&tmp_str[max_str - DOTS_STR_LEN - 2], DOTS_STR_LEN, "%s", dots);
+ }
+
+- mvwprintw(win, row, col, tmp_str);
++ mvwprintw(win, row, col, "%s", tmp_str);
+
+ refresh();
+ wrefresh(win);
+@@ -1861,13 +1861,13 @@
+ time_last = time_now.tv_sec;
+ rc = get_data();
+ if (rc) {
+- mvprintw(g_max_row - 1, g_max_col - strlen(refresh_error) - 2, refresh_error);
++ mvprintw(g_max_row - 1, g_max_col - strlen(refresh_error) - 2, "%s", refresh_error);
+ }
+
+ max_pages = refresh_tab(active_tab, current_page);
+
+ snprintf(current_page_str, CURRENT_PAGE_STR_LEN - 1, "Page: %d/%d", current_page + 1, max_pages);
+- mvprintw(g_max_row - 1, 1, current_page_str);
++ mvprintw(g_max_row - 1, 1, "%s", current_page_str);
+
+ free_data();
+
diff --git a/debian/patches/update-java-source-target-flags.patch b/debian/patches/update-java-source-target-flags.patch
new file mode 100644
index 000000000..f3f1766c7
--- /dev/null
+++ b/debian/patches/update-java-source-target-flags.patch
@@ -0,0 +1,40 @@
+Description: use --release 8 instead of -source/-target
+ Instead of -source/-target ceph should be build with --release for OpenJDK 9
+ or later so that the bootclasspath is also set, as per JEP-247, otherwise it
+ risks incurring into binary incompatibility when run with an earlier OpenJDK.
+ OpenJDK minimum compatibility release has been updated to 8.
+Author: Tiago Stürmer Daitx <tiago.daitx@ubuntu.com>
+Bug-Ubuntu: https://launchpad.net/bugs/1756854
+Bug-Ubuntu: https://launchpad.net/bugs/1766998
+Forwarded: no
+Last-Update: 2018-04-24
+---
+
+--- a/src/java/CMakeLists.txt
++++ b/src/java/CMakeLists.txt
+@@ -15,13 +15,7 @@
+ java/com/ceph/fs/CephStat.java
+ java/com/ceph/fs/CephStatVFS.java)
+
+-# note: for the -source 1.7 builds, we add
+-# -Xlint:-options
+-# to get rid of the warning
+-# warning: [options] bootstrap class path not set in conjunction with -source 1.7
+-# as per
+-# https://blogs.oracle.com/darcy/entry/bootclasspath_older_source
+-set(CMAKE_JAVA_COMPILE_FLAGS "-source" "1.8" "-target" "1.8" "-Xlint:-options")
++set(CMAKE_JAVA_COMPILE_FLAGS "--release" $ENV{JAVA_TARGET_RELEASE} "-Xlint:-options")
+ set(jni_header_dir "${CMAKE_CURRENT_BINARY_DIR}/native")
+ if(CMAKE_VERSION VERSION_LESS 3.11)
+ set(CMAKE_JAVA_COMPILE_FLAGS ${CMAKE_JAVA_COMPILE_FLAGS} "-h" ${jni_header_dir})
+--- a/src/rocksdb/java/CMakeLists.txt
++++ b/src/rocksdb/java/CMakeLists.txt
+@@ -4,7 +4,7 @@
+ message("Please consider switching to CMake 3.11.4 or newer")
+ endif()
+
+-set(CMAKE_JAVA_COMPILE_FLAGS -source 7)
++set(CMAKE_JAVA_COMPILE_FLAGS -source $ENV{JAVA_TARGET_RELEASE})
+
+ set(JNI_NATIVE_SOURCES
+ rocksjni/backup_engine_options.cc
diff --git a/debian/py3dist-overrides b/debian/py3dist-overrides
deleted file mode 100644
index b6358cf12..000000000
--- a/debian/py3dist-overrides
+++ /dev/null
@@ -1,4 +0,0 @@
-cephfs python3-cephfs; PEP386
-ceph_argparse python3-ceph-argparse
-ceph_common python3-ceph-common
-distutils python3-distutils
diff --git a/debian/python3-ceph-argparse.install b/debian/python3-ceph-argparse.install
index 52479f935..274b8b4f7 100755..100644
--- a/debian/python3-ceph-argparse.install
+++ b/debian/python3-ceph-argparse.install
@@ -1,4 +1,2 @@
-#! /usr/bin/dh-exec
-
-usr/lib/python3*/*-packages/ceph_argparse.py /usr/lib/python3/dist-packages/
-usr/lib/python3*/*-packages/ceph_daemon.py /usr/lib/python3/dist-packages/
+usr/lib/python3*/dist-packages/ceph_argparse.py
+usr/lib/python3*/dist-packages/ceph_daemon.py
diff --git a/debian/python3-ceph-common.install b/debian/python3-ceph-common.install
index a9b47e3b5..6cdb6ce06 100644
--- a/debian/python3-ceph-common.install
+++ b/debian/python3-ceph-common.install
@@ -1,2 +1,2 @@
-usr/lib/python3*/dist-packages/ceph-*.egg-info
usr/lib/python3*/dist-packages/ceph
+usr/lib/python3*/dist-packages/ceph-*.egg-info
diff --git a/debian/python3-ceph.lintian-overrides b/debian/python3-ceph.lintian-overrides
new file mode 100644
index 000000000..fd0d214b0
--- /dev/null
+++ b/debian/python3-ceph.lintian-overrides
@@ -0,0 +1 @@
+python3-ceph: empty-binary-package
diff --git a/debian/radosgw.install b/debian/radosgw.install
index be74a52c1..01651e01f 100644
--- a/debian/radosgw.install
+++ b/debian/radosgw.install
@@ -1,10 +1,8 @@
lib/systemd/system/ceph-radosgw*
-usr/bin/ceph-diff-sorted
usr/bin/radosgw
usr/bin/radosgw-es
usr/bin/radosgw-object-expirer
usr/bin/radosgw-token
-usr/share/man/man8/ceph-diff-sorted.8
+usr/bin/rgw-gap-list
+usr/bin/rgw-gap-list-comparator
usr/share/man/man8/radosgw.8
-usr/share/man/man8/rgw-orphan-list.8
-usr/share/man/man8/rgw-restore-bucket-index.8
diff --git a/debian/radosgw.lintian-overrides b/debian/radosgw.lintian-overrides
new file mode 100644
index 000000000..5c5e06b8e
--- /dev/null
+++ b/debian/radosgw.lintian-overrides
@@ -0,0 +1,8 @@
+# Ceph upstart configuration's don't have init.d equivalents
+radosgw: init.d-script-not-marked-as-conffile etc/init.d/radosgw-all-starter
+radosgw: init.d-script-not-included-in-package etc/init.d/radosgw-all-starter
+radosgw: init.d-script-not-marked-as-conffile etc/init.d/radosgw-instance
+radosgw: init.d-script-not-included-in-package etc/init.d/radosgw-instance
+radosgw: init.d-script-not-marked-as-conffile etc/init.d/radosgw-all
+radosgw: init.d-script-not-included-in-package etc/init.d/radosgw-all
+radosgw: omitted-systemd-service-for-init.d-script radosgw
diff --git a/debian/radosgw.postinst b/debian/radosgw.postinst
index 07e3ec30b..fb352e4f5 100644
--- a/debian/radosgw.postinst
+++ b/debian/radosgw.postinst
@@ -30,11 +30,8 @@ set -e
case "$1" in
configure)
- [ -x /sbin/start ] && start radosgw-all || :
-
- if ! dpkg-statoverride --list /var/lib/ceph/radosgw >/dev/null
- then
- chown $SERVER_USER:$SERVER_GROUP /var/lib/ceph/radosgw
+ if ! dpkg-statoverride --list /var/lib/ceph/radosgw >/dev/null; then
+ chown $SERVER_USER:$SERVER_GROUP /var/lib/ceph/radosgw
fi
;;
abort-upgrade|abort-remove|abort-deconfigure)
diff --git a/debian/radosgw.postrm b/debian/radosgw.postrm
new file mode 100644
index 000000000..3083c1471
--- /dev/null
+++ b/debian/radosgw.postrm
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+set -e
+
+if dpkg-maintscript-helper supports mv_conffile 2>/dev/null; then
+ dpkg-maintscript-helper mv_conffile \
+ /etc/init/radosgw.conf /etc/init/radosgw-instance.conf \
+ 0.72.1-3~ radosgw -- "$@"
+fi
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/radosgw.preinst b/debian/radosgw.preinst
new file mode 100644
index 000000000..3083c1471
--- /dev/null
+++ b/debian/radosgw.preinst
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+set -e
+
+if dpkg-maintscript-helper supports mv_conffile 2>/dev/null; then
+ dpkg-maintscript-helper mv_conffile \
+ /etc/init/radosgw.conf /etc/init/radosgw-instance.conf \
+ 0.72.1-3~ radosgw -- "$@"
+fi
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/radosgw.prerm b/debian/radosgw.prerm
index 4120fb627..0288ab77b 100644
--- a/debian/radosgw.prerm
+++ b/debian/radosgw.prerm
@@ -5,7 +5,6 @@ set -e
case "$1" in
remove)
- [ -x /sbin/stop ] && stop radosgw-all || true
invoke-rc.d radosgw stop || {
RESULT=$?
if [ $RESULT != 100 ]; then
diff --git a/debian/rbd-nbd.install b/debian/rbd-nbd.install
index 27c529ad5..385c4501f 100644
--- a/debian/rbd-nbd.install
+++ b/debian/rbd-nbd.install
@@ -1,3 +1,2 @@
usr/bin/rbd-nbd
usr/share/man/man8/rbd-nbd.8
-usr/libexec/rbd-nbd/rbd-nbd_quiesce
diff --git a/debian/rest-bench.install b/debian/rest-bench.install
new file mode 100644
index 000000000..8535f20d5
--- /dev/null
+++ b/debian/rest-bench.install
@@ -0,0 +1 @@
+usr/bin/rest-bench
diff --git a/debian/rules b/debian/rules
index 442ea28d4..625e7e0a6 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,83 +1,147 @@
#!/usr/bin/make -f
# -*- makefile -*-
-export DH_VERBOSE=1
-export DESTDIR=$(CURDIR)/debian/tmp
+#export DH_VERBOSE=1
-include /usr/share/dpkg/default.mk
+DEB_HOST_ARCH_BITS ?= $(shell dpkg-architecture -qDEB_HOST_ARCH_BITS)
+export DEB_BUILD_ARCH ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH)
+export DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH)
-ifneq (,$(findstring WITH_STATIC_LIBSTDCXX,$(CEPH_EXTRA_CMAKE_ARGS)))
- # dh_auto_build sets LDFLAGS with `dpkg-buildflags --get LDFLAGS` on ubuntu,
- # which makes the application aborts when the shared library throws
- # exception, so strip this linker option,
- # see http://tracker.ceph.com/issues/25209
- export DEB_LDFLAGS_MAINT_STRIP = -Wl,-Bsymbolic-functions
+# support ccache for faster build
+# cmake uses /usr/bin/c*
+ifeq (yes,$(findstring yes,$(shell test -L /usr/lib/ccache/c++ && test -L /usr/lib/ccache/cc && echo -n yes)))
+ extraopts += -DWITH_CCACHE=ON
endif
-ifeq (,$(findstring WITH_SEASTAR,$(CEPH_EXTRA_CMAKE_ARGS)))
- export CEPH_OSD_BASENAME = ceph-osd
+
+# Don't switch to clang for Ubuntu - armhf builder is
+# just fine using g++
+ifeq ($(shell dpkg-vendor --is Debian && echo yes), yes)
+# try to save even more memory on some architectures
+# see #849657 for hints.
+ifneq (,$(findstring $(DEB_HOST_ARCH),armhf mipsel armel sh4 m68k))
+ export CC=clang
+ export CXX=clang++
+ extraopts += -DCMAKE_CXX_COMPILER=/usr/bin/clang++
+ extraopts += -DCMAKE_C_COMPILER=/usr/bin/clang
else
- export CEPH_OSD_BASENAME = crimson-osd
+ # Reduce size of debug symbols to fix FTBFS due to the
+ # 2GB/3GB address space limits on 32bit
+ ifeq (32,$(DEB_HOST_ARCH_BITS))
+ export DEB_CFLAGS_MAINT_APPEND = -g1
+ export DEB_CXXFLAGS_MAINT_APPEND = -g1
+ endif
endif
-ifneq ($(filter pkg.ceph.arrow,$(DEB_BUILD_PROFILES)),)
- extraopts += -DWITH_SYSTEM_ARROW=ON
+else
+ # Reduce size of debug symbols to fix FTBFS due to the
+ # 2GB/3GB address space limits on 32bit
+ ifeq (32,$(DEB_HOST_ARCH_BITS))
+ export DEB_CFLAGS_MAINT_APPEND = -g1
+ export DEB_CXXFLAGS_MAINT_APPEND = -g1
+ endif
+endif # dpkg-vendor --is Debian
+
+ifeq ($(shell dpkg-vendor --is Ubuntu && echo yes) $(DEB_HOST_ARCH), yes i386)
+ skip_packages = -Nceph -Nceph-base -Nceph-mds -Nceph-mgr -Nceph-mon -Nceph-osd -Nceph-common -Nradosgw -Nrbd-mirror
endif
-extraopts += -DWITH_JAEGER=ON
-extraopts += -DWITH_SYSTEM_UTF8PROC=ON
-extraopts += -DWITH_OCF=ON -DWITH_LTTNG=ON
-extraopts += -DWITH_MGR_DASHBOARD_FRONTEND=OFF
+# minimise needless linking and link to libatomic
+# The last is needed because long long atomic operations are not directly
+# supported by all processor architectures
+export DEB_LDFLAGS_MAINT_APPEND= -Wl,--as-needed -latomic
+
+# Enable hardening
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all optimize=-lto
+
+export DESTDIR=$(CURDIR)/debian/tmp
+
+export JAVA_HOME=/usr/lib/jvm/default-java
+## Set JAVAC to prevent FTBFS due to incorrect use of 'gcj' if found (see "m4/ac_prog_javac.m4").
+export JAVAC=javac
+
+include /usr/share/java/java_defaults.mk
+export JAVA_TARGET_RELEASE=$(java_compat_level)
+
+extraopts += -DWITH_OCF=ON -DWITH_NSS=ON -DWITH_PYTHON3=ON -DWITH_DEBUG=ON
+extraopts += -DWITH_PYTHON2=OFF -DMGR_PYTHON_VERSION=3
extraopts += -DWITH_PYTHON3=3
extraopts += -DWITH_CEPHFS_JAVA=ON
extraopts += -DWITH_CEPHFS_SHELL=ON
+extraopts += -DWITH_TESTS=OFF
+extraopts += -DWITH_SYSTEM_BOOST=ON
+extraopts += -DWITH_LTTNG=OFF -DWITH_EMBEDDED=OFF
+extraopts += -DCMAKE_INSTALL_LIBEXECDIR=/usr/lib
+extraopts += -DWITH_MGR_DASHBOARD_FRONTEND=OFF
extraopts += -DWITH_SYSTEMD=ON -DCEPH_SYSTEMD_ENV_DIR=/etc/default
+extraopts += -DCMAKE_INSTALL_SYSCONFDIR=/etc
+extraopts += -DSYSTEMD_SYSTEM_UNIT_DIR=/lib/systemd/system
+extraopts += -DWITH_RADOSGW_KAFKA_ENDPOINT=OFF
+extraopts += -DCMAKE_BUILD_TYPE=RelWithDebInfo
extraopts += -DWITH_GRAFANA=ON
-ifeq ($(DEB_HOST_ARCH), amd64)
- extraopts += -DWITH_RBD_RWL=ON
+extraopts += -DWITH_RADOSGW_SELECT_PARQUET=OFF
+extraopts += -DWITH_JAEGER=OFF
+
+ifneq (,$(findstring $(DEB_HOST_ARCH),amd64 arm64 ppc64el))
+extraopts += -DWITH_RBD_RWL=ON
+extraopts += -DWITH_RBD_SSD_CACHE=ON
+extraopts += -DWITH_SYSTEM_PMDK=ON
+extraopts += -DWITH_BLUESTORE_PMEM=ON
+extraopts += -DWITH_SPDK=ON
else
- extraopts += -DWITH_RBD_RWL=OFF
+extraopts += -DWITH_SPDK=OFF
endif
-extraopts += -DWITH_RBD_SSD_CACHE=ON
-# assumes that ceph is exmpt from multiarch support, so we override the libdir.
-extraopts += -DCMAKE_INSTALL_LIBDIR=/usr/lib
-extraopts += -DCMAKE_INSTALL_LIBEXECDIR=/usr/libexec
-extraopts += -DCMAKE_INSTALL_SYSCONFDIR=/etc
+
+# Enable crimson build on supported architectures
+ifneq (,$(findstring $(DEB_HOST_ARCH),amd64 arm64 ppc64el s390x))
+extraopts += -DWITH_SEASTAR=ON -DSeastar_CXX_FLAGS=-DSEASTAR_DEFAULT_ALLOCATOR
+endif
+
ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
extraopts += -DBOOST_J=$(NUMJOBS)
endif
-ifneq (,$(filter with_system_libs,$(DEB_BUILD_OPTIONS)))
- extraopts += -DWITH_SYSTEM_BOOST=ON
- extraopts += -DWITH_SYSTEM_PMDK=ON
+
+ifneq (,$(findstring $(DEB_HOST_ARCH),mips64el ia64 m68k ppc64 sh4 sparc64 x32))
+ # beast depends on libboost_{context,coroutine} which is not supported on various archs
+ extraopts += -DWITH_BOOST_CONTEXT=OFF
+else
+ extraopts += -DWITH_BOOST_CONTEXT=ON
endif
-# for python3-${pkg} packages
-py3_bindings := rados cephfs rbd rgw ceph-argparse ceph-common
-# for packages with its own py3dist-overrides files, those file should be named
-# like ${pkg}.requires
-py3_overrides_packages := $(basename $(notdir $(wildcard debian/*.requires)))
-# for python3 applications, the package name is used as it is
-py3_packages := cephfs-shell cephfs-top cephadm
+# Use build time calculation unless pkg.ceph.unleashed profile enabled
+ifeq ($(filter pkg.ceph.unleashed,$(DEB_BUILD_PROFILES)),)
+MAX_PARALLEL ?= $(shell ./debian/calc-max-parallel.sh)
+endif
%:
- dh $@ --buildsystem=cmake --with javahelper,python3 --parallel
+ dh $@ --buildsystem=cmake --with javahelper,python3,systemd $(MAX_PARALLEL)
override_dh_auto_configure:
env | sort
- dh_auto_configure --buildsystem=cmake -- $(extraopts) $(CEPH_EXTRA_CMAKE_ARGS)
-
-override_dh_auto_clean:
- dh_auto_clean --buildsystem=cmake
- rm -f debian/radosgw.init debian/ceph.logrotate debian/ceph-base.docs
+ dh_auto_configure --buildsystem=cmake -- $(extraopts)
+# after trying to patch the various places where HAVE_ARM_NEON is used
+# the easiest way to get rid of it on armel seems to be to patch the cmake
+# cache file.
+ifeq ($(DEB_HOST_ARCH),armel)
+ sed 's,^HAVE_ARM_NEON.*,HAVE_ARM_NEON:INTERNAL=0,' -i obj-arm-linux-gnueabi/CMakeCache.txt
+endif
override_dh_auto_install:
dh_auto_install --buildsystem=cmake --destdir=$(DESTDIR)
install -D -m 644 udev/50-rbd.rules $(DESTDIR)/lib/udev/rules.d/50-rbd.rules
install -D -m 644 src/etc-rbdmap $(DESTDIR)/etc/ceph/rbdmap
install -D -m 644 etc/sysctl/90-ceph-osd.conf $(DESTDIR)/etc/sysctl.d/30-ceph-osd.conf
- install -D -m 440 sudoers.d/ceph-smartctl $(DESTDIR)/etc/sudoers.d/ceph-smartctl
- install -D -m 755 src/tools/rbd_nbd/rbd-nbd_quiesce $(DESTDIR)/usr/libexec/rbd-nbd/rbd-nbd_quiesce
+ install -D -m 600 sudoers.d/ceph-smartctl $(DESTDIR)/etc/sudoers.d/ceph-smartctl
+
+ install -m 755 src/cephadm/cephadm.py $(DESTDIR)/usr/sbin/cephadm
install -m 644 -D monitoring/ceph-mixin/prometheus_alerts.yml $(DESTDIR)/etc/prometheus/ceph/ceph_default_alerts.yml
- install -m 644 -D monitoring/ceph-mixin/dashboards_out/* ${DESTDIR}/etc/grafana/dashboards/ceph-dashboard
+
+ # NOTE: ensure that any versioned erasure coding test code is dropped
+ # from the package install - package ships unversioned modules.
+ rm -f $(CURDIR)/debian/tmp/usr/lib/*/ceph/erasure-code/libec_*.so.*
+ find $(CURDIR)/debian/tmp/usr/lib/*/ceph/erasure-code -type l -delete || :
+ # avoid running out of disk space
+ rm -rf $(CURDIR)/obj-*-linux-gnu
+
# doc/changelog is a directory, which confuses dh_installchangelogs
override_dh_installchangelogs:
@@ -87,66 +151,75 @@ override_dh_installlogrotate:
cp src/logrotate.conf debian/ceph-common.logrotate
dh_installlogrotate -pceph-common
+
override_dh_installinit:
cp src/init-radosgw debian/radosgw.init
+ dh_installinit --no-start
+ dh_installinit -pceph-common --name=rbdmap --no-start
+ dh_installinit -pceph-base --name ceph --no-start
# install the systemd stuff manually since we have funny service names
- install -d -m0755 debian/ceph-common/etc/default
- install -m0644 etc/default/ceph debian/ceph-common/etc/default/
+ # and need to update the paths in all of the files post install
+ # systemd:ceph-common
install -d -m0755 debian/ceph-common/usr/lib/tmpfiles.d
install -m 0644 -D systemd/ceph.tmpfiles.d debian/ceph-common/usr/lib/tmpfiles.d/ceph.conf
+ # NOTE(jamespage): Install previous ceph-mon service from packaging for upgrades
+ install -d -m0755 debian/ceph-mon/lib/systemd/system
+ install -m0644 debian/lib-systemd/system/ceph-mon.service debian/ceph-mon/lib/systemd/system
+ # Ensure Debian/Ubuntu specific systemd units are NOT automatically enabled and started
+ # Enable systemd targets only
+ dh_systemd_enable -Xceph-mon.service -Xceph-osd.service -X ceph-mds.service
+ # Start systemd targets only
+ dh_systemd_start --no-stop-on-upgrade --no-restart-after-upgrade
+
+override_dh_systemd_enable:
+ # systemd enable done as part of dh_installinit
+
+override_dh_systemd_start:
+ # systemd start done as part of dh_installinit
+
+override_dh_makeshlibs:
+ # exclude jni libraries in libcephfs-jni to avoid pointless ldconfig
+ # calls in maintainer scripts; exclude private erasure-code plugins.
+ dh_makeshlibs -V -X/usr/lib/jni -X/usr/lib/$(DEB_HOST_MULTIARCH)/ceph/erasure-code
- dh_installinit -p ceph-base --name ceph --no-start
- dh_installinit -p radosgw --no-start
-
-override_dh_installsystemd:
- # Only enable and start systemd targets
- dh_installsystemd --no-stop-on-upgrade --no-restart-after-upgrade -Xceph-mon.service -Xceph-osd.service -X ceph-mds.service
-
-override_dh_strip:
- dh_strip -pceph-mds --dbg-package=ceph-mds-dbg
- dh_strip -pceph-fuse --dbg-package=ceph-fuse-dbg
- dh_strip -pceph-mgr --dbg-package=ceph-mgr-dbg
- dh_strip -pceph-mon --dbg-package=ceph-mon-dbg
- dh_strip -pceph-osd --dbg-package=ceph-osd-dbg
- dh_strip -pceph-base --dbg-package=ceph-base-dbg
- dh_strip -pcephfs-mirror --dbg-package=cephfs-mirror-dbg
- dh_strip -prbd-fuse --dbg-package=rbd-fuse-dbg
- dh_strip -prbd-mirror --dbg-package=rbd-mirror-dbg
- dh_strip -pceph-immutable-object-cache --dbg-package=ceph-immutable-object-cache-dbg
- dh_strip -prbd-nbd --dbg-package=rbd-nbd-dbg
- dh_strip -pceph-common --dbg-package=ceph-common-dbg
- dh_strip -plibrados2 --dbg-package=librados2-dbg
- dh_strip -plibsqlite3-mod-ceph --dbg-package=libsqlite3-mod-ceph-dbg
- dh_strip -plibradosstriper1 --dbg-package=libradosstriper1-dbg
- dh_strip -plibrbd1 --dbg-package=librbd1-dbg
- dh_strip -plibcephfs2 --dbg-package=libcephfs2-dbg
- dh_strip -plibrgw2 --dbg-package=librgw2-dbg
- dh_strip -pradosgw --dbg-package=radosgw-dbg
- dh_strip -pceph-test --dbg-package=ceph-test-dbg
- dh_strip -ppython3-rados --dbg-package=python3-rados-dbg
- dh_strip -ppython3-rbd --dbg-package=python3-rbd-dbg
- dh_strip -ppython3-rgw --dbg-package=python3-rgw-dbg
- dh_strip -ppython3-cephfs --dbg-package=python3-cephfs-dbg
+override_dh_auto_test:
+ # do not run tests
override_dh_shlibdeps:
dh_shlibdeps -a --exclude=erasure-code --exclude=rados-classes --exclude=compressor --exclude=ceph_crypto
override_dh_python3:
- @for binding in $(py3_bindings); do \
- dh_python3 -p python3-$$binding; \
- done
- @for pkg in $(py3_overrides_packages); do \
- dh_python3 -p $$pkg --requires=debian/$$pkg.requires; \
- done
- @for pkg in $(py3_packages); do \
- dh_python3 -p $$pkg; \
- done
- dh_python3 -p ceph-base --shebang=/usr/bin/python3
+ for binding in rados cephfs rbd rgw; do \
+ dh_python3 -p python3-$$binding --shebang=/usr/bin/python3; \
+ done
+ dh_python3 -p python3-ceph-argparse --shebang=/usr/bin/python3
+ dh_python3 -p python3-ceph-common --shebang=/usr/bin/python3
dh_python3 -p ceph-common --shebang=/usr/bin/python3
- dh_python3 -p ceph-fuse --shebang=/usr/bin/python3
- dh_python3 -p ceph-volume --shebang=/usr/bin/python3
-
-# do not run tests
-override_dh_auto_test:
-
-.PHONY: override_dh_autoreconf override_dh_auto_configure override_dh_auto_clean override_dh_auto_install override_dh_installlogrotate override_dh_installinit override_dh_strip override_dh_auto_test
+ dh_python3 -p ceph-base --shebang=/usr/bin/python3
+ dh_python3 -p ceph-osd --shebang=/usr/bin/python3
+ dh_python3 -p ceph-mgr --shebang=/usr/bin/python3
+ dh_python3 -p cephfs-shell --shebang=/usr/bin/python3
+ dh_python3 -p cephadm --shebang=/usr/bin/python3
+
+override_dh_builddeb:
+ dh_builddeb ${skip_packages}
+
+override_dh_gencontrol:
+ dh_gencontrol ${skip_packages}
+
+
+# Helper target for creating snapshots from upstream git
+DATE=$(shell date +%Y%m%d)
+# Upstream branch to track
+BRANCH=squid
+VERSION=19.2.0
+
+get-orig-snapshot:
+ rm -Rf ceph-upstream
+ git clone --branch $(BRANCH) --depth 1 https://github.com/ceph/ceph ceph-upstream
+ cd ceph-upstream && \
+ export COMMIT=`git rev-parse --short HEAD` && \
+ ./make-dist $(VERSION)~git$(DATE).$$COMMIT && \
+ cd .. && \
+ mk-origtargz --version $(VERSION)~git$(DATE).$$COMMIT ceph-upstream/ceph-$(VERSION)~git$(DATE).$$COMMIT.tar.bz2
+ rm -Rf ceph-upstream
diff --git a/debian/source/format b/debian/source/format
index d3827e75a..163aaf8d8 100644
--- a/debian/source/format
+++ b/debian/source/format
@@ -1 +1 @@
-1.0
+3.0 (quilt)
diff --git a/debian/source/lintian-overrides b/debian/source/lintian-overrides
new file mode 100644
index 000000000..7f77f57f6
--- /dev/null
+++ b/debian/source/lintian-overrides
@@ -0,0 +1,10 @@
+# we don't ship thse thirdparty libs here, afaics.
+# license.txt is outdated but fixing it causes the same error
+# come up for the patch, so...
+ceph source: license-problem-json-evil src/s3select/rapidjson/license.txt
+
+# pybind js source is in src/pybind/mgr/dashboard/frontend/src
+ceph source: source-is-missing src/pybind/mgr/dashboard/frontend/dist/*.js
+
+# regression test file is actually shipped with source and build files
+ceph source: source-contains-prebuilt-ms-help-file src/boost/libs/beast/test/extern/zlib-1.2.11/contrib/dotzlib/DotZLib.chm
diff --git a/debian/tests/build-rados b/debian/tests/build-rados
new file mode 100755
index 000000000..c62999251
--- /dev/null
+++ b/debian/tests/build-rados
@@ -0,0 +1,31 @@
+#!/bin/sh
+# autopkgtest check: Build and run a program against librados2 to
+# validate that headers are installed and libraries exists
+
+set -e
+
+WORKDIR=$(mktemp -d)
+trap "rm -rf $WORKDIR" 0 INT QUIT ABRT PIPE TERM
+cd $WORKDIR
+cat <<EOF > radostest.c
+#include <rados/librados.h>
+
+int
+main(void)
+{
+ int err;
+ rados_t cluster;
+
+ err = rados_create(&cluster, NULL);
+ if (err < 0) {
+ return (1);
+ }
+ return(0);
+}
+EOF
+
+gcc -o radostest radostest.c -lrados
+echo "build: OK"
+[ -x radostest ]
+./radostest
+echo "run: OK"
diff --git a/debian/tests/build-rbd b/debian/tests/build-rbd
new file mode 100755
index 000000000..5ad6f8823
--- /dev/null
+++ b/debian/tests/build-rbd
@@ -0,0 +1,24 @@
+#!/bin/sh
+# autopkgtest check: Build and run a program against librbd1 to
+# validate that headers are installed and libraries exists
+
+set -e
+
+WORKDIR=$(mktemp -d)
+trap "rm -rf $WORKDIR" 0 INT QUIT ABRT PIPE TERM
+cd $WORKDIR
+cat <<EOF > rbdtest.c
+#include <rbd/librbd.h>
+
+int
+main(void)
+{
+ return(0);
+}
+EOF
+
+gcc -o rbdtest rbdtest.c -lrbd
+echo "build: OK"
+[ -x rbdtest ]
+./rbdtest
+echo "run: OK"
diff --git a/debian/tests/ceph-client b/debian/tests/ceph-client
new file mode 100755
index 000000000..c693a5698
--- /dev/null
+++ b/debian/tests/ceph-client
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+set -e
+
+CLIENTS=('ceph')
+
+for client in "${CLIENTS[@]}"; do
+ echo -n "Testing client $client: "
+ $client -v 2>&1 > /dev/null
+ echo "OK"
+done
diff --git a/debian/tests/control b/debian/tests/control
new file mode 100644
index 000000000..372a057d0
--- /dev/null
+++ b/debian/tests/control
@@ -0,0 +1,9 @@
+Tests: ceph-client build-rados build-rbd python-ceph
+Depends:
+ build-essential,
+ ceph-common,
+ librados-dev,
+ librbd-dev,
+ python3-rados,
+ python3-rbd,
+Restrictions: needs-root
diff --git a/debian/tests/python-ceph b/debian/tests/python-ceph
new file mode 100755
index 000000000..006dbe63d
--- /dev/null
+++ b/debian/tests/python-ceph
@@ -0,0 +1,7 @@
+#!/usr/bin/python3
+
+# Test that rbd and rados can be imported OK
+import rbd
+import rados
+
+print("python-ceph: OK")
diff --git a/debian/udev/95-ceph-osd-lvm.rules b/debian/udev/95-ceph-osd-lvm.rules
new file mode 100644
index 000000000..00feae51f
--- /dev/null
+++ b/debian/udev/95-ceph-osd-lvm.rules
@@ -0,0 +1,13 @@
+# OSD LVM layout example
+# VG prefix: ceph-
+# LV prefix: osd-
+ACTION=="add", SUBSYSTEM=="block", \
+ ENV{DEVTYPE}=="disk", \
+ ENV{DM_LV_NAME}=="osd-*", \
+ ENV{DM_VG_NAME}=="ceph-*", \
+ OWNER:="ceph", GROUP:="ceph", MODE:="660"
+ACTION=="change", SUBSYSTEM=="block", \
+ ENV{DEVTYPE}=="disk", \
+ ENV{DM_LV_NAME}=="osd-*", \
+ ENV{DM_VG_NAME}=="ceph-*", \
+ OWNER="ceph", GROUP="ceph", MODE="660"
diff --git a/debian/watch b/debian/watch
index ec9ecbf5d..279f3d5f1 100644
--- a/debian/watch
+++ b/debian/watch
@@ -1,2 +1,3 @@
version=3
-https://download.ceph.com/tarballs/ceph-(\d.*)\.tar\.gz
+opts="uversionmangle=s/-/~/,dversionmangle=s/\+dfsg\d*$//" \
+ http://download.ceph.com/tarballs/ceph-(\d.*)\.tar\.gz