Package: libsnappy-java
Version: 1.0.4.1~dfsg-1
Severity: grave
Tags: patch
Justification: renders package unusable

Dear Maintainer,

Apologies if this the wrong package to open a bug against, I was unsure whether
I should open it against libsnappy-java or libsnappy1, feel free to
reassign it if needed

While trying to use the simple example from the snappy-java documentation
attached below I encountered an error of FAILED_LOAD_NATIVE_LIBRARY. After a
lot of reading it seems like the upstream ships compiled versions of shared
object (.so) files for various OSes and architectures that get included in the
shipped jar file. Those are stripped out in the Debian package and a dependency
to the libsnappy1 package is declared. That is a nice approach IMHO
However, the .so file shipped by the libsnappy1 package
(/usr/lib/libsnappy.so.1.1.3) does not contain the necessary JNI bindings and
as a result the JNI calls from the Java code fail.

I have managed to bypass the problem by recompiling the libsnappy1 package
with the JNI bindings provided in the libsnappy-java package. I attach the
patch. I am not sure however if this is the best possible solution. It is
however a relatively clean one. Of course this solution is against the
libsnappy1 package and not the libsnappy-java package

Reproduce with:

SnappyTests.java:

import org.xerial.snappy.Snappy;
import java.lang.String;
import java.lang.System;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

class SnappyTests {
public static void main(String[] args) throws
UnsupportedEncodingException, IOException {
String input = "Hello snappy-java! Snappy-java is a JNI-based wrapper of "
    + "Snappy, a fast compresser/decompresser.";
byte[] compressed = Snappy.compress(input.getBytes("UTF-8"));
byte[] uncompressed = Snappy.uncompress(compressed);

String result = new String(uncompressed, "UTF-8");
System.out.println(result);
}
}

Compile with:

javac -cp /usr/share/java/snappy-java.jar SnappyTests.java

Run with:

java -cp '/usr/share/java/snappy-java.jar:.' SnappyTests

Stacktrace returned is:

java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.xerial.snappy.SnappyLoader.loadNativeLibrary(SnappyLoader.java:317)
at org.xerial.snappy.SnappyLoader.load(SnappyLoader.java:219)
at org.xerial.snappy.Snappy.<clinit>(Snappy.java:44)
at SnappyTests.main(SnappyTests.java:11)
Caused by: java.lang.UnsatisfiedLinkError: no snappyjava in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1856)
at java.lang.Runtime.loadLibrary0(Runtime.java:845)
at java.lang.System.loadLibrary(System.java:1084)
at org.xerial.snappy.SnappyNativeLoader.loadLibrary(SnappyNativeLoader.java:52)
... 8 more
Exception in thread "main" org.xerial.snappy.SnappyError:
[FAILED_TO_LOAD_NATIVE_LIBRARY] null
at org.xerial.snappy.SnappyLoader.load(SnappyLoader.java:229)
at org.xerial.snappy.Snappy.<clinit>(Snappy.java:44)
at SnappyTests.main(SnappyTests.java:11)

-- System Information:
Debian Release: 7.3
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable')
Architecture: amd64 (x86_64)

Kernel: Linux 3.11-0.bpo.2-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.utf8, LC_CTYPE=en_US.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
diff -urN b/snappy-1.0.4/debian/libsnappy1.links a/snappy-1.0.4/debian/libsnappy1.links
--- b/snappy-1.0.4/debian/libsnappy1.links	1970-01-01 00:00:00.000000000 +0000
+++ a/snappy-1.0.4/debian/libsnappy1.links	2013-11-06 14:47:02.701611660 +0000
@@ -0,0 +1 @@
+usr/lib/libsnappy.so.1 usr/lib/libsnappyjava.so
diff -urN b/snappy-1.0.4/debian/patches/jni.patch a/snappy-1.0.4/debian/patches/jni.patch
--- b/snappy-1.0.4/debian/patches/jni.patch	1970-01-01 00:00:00.000000000 +0000
+++ a/snappy-1.0.4/debian/patches/jni.patch	2013-11-06 14:39:55.093530261 +0000
@@ -0,0 +1,411 @@
+--- /dev/null	2013-05-23 22:06:22.347926853 +0000
++++ b/SnappyNative.cc	2013-11-06 12:27:53.491596706 +0000
+@@ -0,0 +1,237 @@
++/*--------------------------------------------------------------------------
++ *  Copyright 2011 Taro L. Saito
++ *
++ *  Licensed under the Apache License, Version 2.0 (the "License");
++ *  you may not use this file except in compliance with the License.
++ *  You may obtain a copy of the License at
++ *
++ *     http://www.apache.org/licenses/LICENSE-2.0
++ *
++ *  Unless required by applicable law or agreed to in writing, software
++ *  distributed under the License is distributed on an "AS IS" BASIS,
++ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ *  See the License for the specific language governing permissions and
++ *  limitations under the License.
++ *--------------------------------------------------------------------------*/
++#include <string>
++#include <cstring>
++#include <snappy.h>
++#include "SnappyNative.h"
++
++void throw_exception(JNIEnv *env, jobject self, int errorCode)
++{
++	jclass c = env->FindClass("Lorg/xerial/snappy/SnappyNative;");
++	if(c==0)
++		return;
++    jmethodID mth_throwex = env->GetMethodID(c, "throw_error", "(I)V");
++    if(mth_throwex == 0)
++    	return;
++    env->CallVoidMethod(self, mth_throwex, (jint) errorCode);
++}
++
++
++JNIEXPORT jstring JNICALL Java_org_xerial_snappy_SnappyNative_nativeLibraryVersion
++  (JNIEnv * env, jobject self)
++{
++	return env->NewStringUTF("1.0.4");
++}
++
++/*
++ * Class:     org_xerial_snappy_Snappy
++ * Method:    compress
++ * Signature: (Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;)J
++ */
++JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_rawCompress__Ljava_nio_ByteBuffer_2IILjava_nio_ByteBuffer_2I
++  (JNIEnv* env, jobject self, jobject uncompressed, jint upos, jint ulen, jobject compressed, jint cpos)
++{
++	char* uncompressedBuffer = (char*) env->GetDirectBufferAddress(uncompressed);
++	char* compressedBuffer = (char*) env->GetDirectBufferAddress(compressed);
++	if(uncompressedBuffer == 0 || compressedBuffer == 0) {
++		throw_exception(env, self, 3);
++		return (jint) 0;
++	}
++
++	size_t compressedLength;
++	snappy::RawCompress(uncompressedBuffer + upos, (size_t) ulen, compressedBuffer + cpos, &compressedLength);
++	return (jint) compressedLength;
++}
++
++
++JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_rawCompress__Ljava_lang_Object_2IILjava_lang_Object_2I
++  (JNIEnv * env, jobject self, jobject input, jint inputOffset, jint inputLen, jobject output, jint outputOffset)
++{
++	char* in = (char*) env->GetPrimitiveArrayCritical((jarray) input, 0);
++	char* out = (char*) env->GetPrimitiveArrayCritical((jarray) output, 0);
++	if(in == 0 || out == 0) {
++		// out of memory
++		throw_exception(env, self, 4);
++		return 0;
++	}
++
++	size_t compressedLength;
++	snappy::RawCompress(in + inputOffset, (size_t) inputLen, out + outputOffset, &compressedLength);
++
++	env->ReleasePrimitiveArrayCritical((jarray) input, in, 0);
++	env->ReleasePrimitiveArrayCritical((jarray) output, out, 0);
++
++	return (jint) compressedLength;
++}
++
++JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_rawUncompress__Ljava_lang_Object_2IILjava_lang_Object_2I
++(JNIEnv * env, jobject self, jobject input, jint inputOffset, jint inputLength, jobject output, jint outputOffset)
++{
++	char* in = (char*) env->GetPrimitiveArrayCritical((jarray) input, 0);
++	char* out = (char*) env->GetPrimitiveArrayCritical((jarray) output, 0);
++	if(in == 0 || out == 0) {
++		// out of memory
++		throw_exception(env, self, 4);
++		return 0;
++	}
++
++	size_t uncompressedLength;
++	snappy::GetUncompressedLength(in + inputOffset, (size_t) inputLength, &uncompressedLength);
++	bool ret = snappy::RawUncompress(in + inputOffset, (size_t) inputLength, out + outputOffset);
++
++	env->ReleasePrimitiveArrayCritical((jarray) input, in, 0);
++	env->ReleasePrimitiveArrayCritical((jarray) output, out, 0);
++
++	if(!ret) {
++		throw_exception(env, self, 5);
++		return 0;
++	}
++
++	return (jint) uncompressedLength;
++}
++
++
++/*
++ * Class:     org_xerial_snappy_Snappy
++ * Method:    uncompress
++ * Signature: (Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;)Z
++ */
++JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_rawUncompress__Ljava_nio_ByteBuffer_2IILjava_nio_ByteBuffer_2I
++  (JNIEnv * env, jobject self, jobject compressed, jint cpos, jint clen, jobject decompressed, jint dpos)
++{
++	char* compressedBuffer = (char*) env->GetDirectBufferAddress(compressed);
++	char* decompressedBuffer = (char*) env->GetDirectBufferAddress(decompressed);
++	if(compressedBuffer == 0 || decompressedBuffer == 0) {
++		throw_exception(env, self, 3);
++		return (jint) 0;
++	}
++
++	size_t decompressedLength;
++	snappy::GetUncompressedLength(compressedBuffer + cpos, (size_t) clen, &decompressedLength);
++	bool ret = snappy::RawUncompress(compressedBuffer + cpos, (size_t) clen, decompressedBuffer + dpos);
++	if(!ret) {
++		throw_exception(env, self, 5);
++		return 0;
++	}
++
++	return (jint) decompressedLength;
++}
++
++
++
++/*
++ * Class:     org_xerial_snappy_Snappy
++ * Method:    maxCompressedLength
++ * Signature: (J)J
++ */
++
++JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_maxCompressedLength
++  (JNIEnv *, jobject, jint size)
++{
++	size_t l = snappy::MaxCompressedLength((size_t) size);
++	return (jint) l;
++}
++
++/*
++ * Class:     org_xerial_snappy_Snappy
++ * Method:    getUncompressedLength
++ * Signature: (Ljava/nio/ByteBuffer;)J
++ */
++JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_uncompressedLength__Ljava_nio_ByteBuffer_2II
++  (JNIEnv * env, jobject self, jobject compressed, jint cpos, jint clen)
++{
++	char* compressedBuffer = (char*) env->GetDirectBufferAddress(compressed);
++	if(compressedBuffer == 0) {
++		throw_exception(env, self, 3);
++		return (jint) 0;
++	}
++
++	size_t result;
++	bool ret = snappy::GetUncompressedLength(compressedBuffer + cpos, (size_t) clen, &result);
++	if(!ret) {
++		throw_exception(env, self, 2);
++		return 0;
++	}
++	return (jint) result;
++}
++
++JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_uncompressedLength__Ljava_lang_Object_2II
++  (JNIEnv * env, jobject self, jobject input, jint offset, jint length)
++{
++	char* in = (char*) env->GetPrimitiveArrayCritical((jarray) input, 0);
++	if(in == 0) {
++		// out of memory
++		throw_exception(env, self, 4);
++		return 0;
++	}
++
++	size_t result;
++	bool ret = snappy::GetUncompressedLength(in + offset, (size_t) length, &result);
++	env->ReleasePrimitiveArrayCritical((jarray) input, in, 0);
++
++	if(!ret) {
++		throw_exception(env, self, 2);
++		return 0;
++	}
++
++	return (jint) result;
++}
++
++JNIEXPORT jboolean JNICALL Java_org_xerial_snappy_SnappyNative_isValidCompressedBuffer__Ljava_nio_ByteBuffer_2II
++  (JNIEnv * env, jobject self, jobject compressed, jint cpos, jint clen)
++{
++	char* compressedBuffer = (char*) env->GetDirectBufferAddress(compressed);
++	if(compressedBuffer == 0) {
++		throw_exception(env, self, 3);
++		return (jint) 0;
++	}
++	bool ret = snappy::IsValidCompressedBuffer(compressedBuffer + cpos, (size_t) clen);
++	return ret;
++}
++
++
++JNIEXPORT jboolean JNICALL Java_org_xerial_snappy_SnappyNative_isValidCompressedBuffer__Ljava_lang_Object_2II
++  (JNIEnv * env, jobject self, jobject input, jint offset, jint length)
++{
++	char* in = (char*) env->GetPrimitiveArrayCritical((jarray) input, 0);
++	if(in == 0) {
++		// out of memory
++		throw_exception(env, self, 4);
++		return 0;
++	}
++	bool ret = snappy::IsValidCompressedBuffer(in + offset, (size_t) length);
++	env->ReleasePrimitiveArrayCritical((jarray) input, in, 0);
++	return ret;
++}
++
++JNIEXPORT void JNICALL Java_org_xerial_snappy_SnappyNative_arrayCopy
++  (JNIEnv * env, jobject self, jobject input, jint offset, jint length, jobject output, jint output_offset)
++{
++	char* src = (char*) env->GetPrimitiveArrayCritical((jarray) input, 0);
++	char* dest = (char*) env->GetPrimitiveArrayCritical((jarray) output, 0);
++	if(src == 0 || dest == 0) {
++		// out of memory
++		throw_exception(env, self, 4);
++		return;
++	}
++
++	memcpy(dest+output_offset, src+offset, (size_t) length);
++
++	env->ReleasePrimitiveArrayCritical((jarray) input, src, 0);
++	env->ReleasePrimitiveArrayCritical((jarray) output, dest, 0);
++}
++
++
+--- /dev/null	2013-05-23 22:06:22.347926853 +0000
++++ b/jni_md.h	2013-11-06 12:28:49.066580304 +0000
+@@ -0,0 +1,24 @@
++/*
++ * %W% %E%
++ *
++ * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
++ * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
++ */
++
++#ifndef _JAVASOFT_JNI_MD_H_
++#define _JAVASOFT_JNI_MD_H_
++
++#define JNIEXPORT __attribute__((__visibility__("default")))
++#define JNIIMPORT
++#define JNICALL
++
++typedef int jint;
++#ifdef _LP64 /* 64-bit Solaris */
++typedef long jlong;
++#else
++typedef long long jlong;
++#endif
++
++typedef signed char jbyte;
++
++#endif /* !_JAVASOFT_JNI_MD_H_ */
+--- /dev/null	2013-05-23 22:06:22.347926853 +0000
++++ b/SnappyNative.h	2013-11-06 12:27:55.443561022 +0000
+@@ -0,0 +1,101 @@
++/* DO NOT EDIT THIS FILE - it is machine generated */
++#include <jni.h>
++/* Header for class org_xerial_snappy_SnappyNative */
++
++#ifndef _Included_org_xerial_snappy_SnappyNative
++#define _Included_org_xerial_snappy_SnappyNative
++#ifdef __cplusplus
++extern "C" {
++#endif
++/*
++ * Class:     org_xerial_snappy_SnappyNative
++ * Method:    nativeLibraryVersion
++ * Signature: ()Ljava/lang/String;
++ */
++JNIEXPORT jstring JNICALL Java_org_xerial_snappy_SnappyNative_nativeLibraryVersion
++  (JNIEnv *, jobject);
++
++/*
++ * Class:     org_xerial_snappy_SnappyNative
++ * Method:    rawCompress
++ * Signature: (Ljava/nio/ByteBuffer;IILjava/nio/ByteBuffer;I)I
++ */
++JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_rawCompress__Ljava_nio_ByteBuffer_2IILjava_nio_ByteBuffer_2I
++  (JNIEnv *, jobject, jobject, jint, jint, jobject, jint);
++
++/*
++ * Class:     org_xerial_snappy_SnappyNative
++ * Method:    rawCompress
++ * Signature: (Ljava/lang/Object;IILjava/lang/Object;I)I
++ */
++JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_rawCompress__Ljava_lang_Object_2IILjava_lang_Object_2I
++  (JNIEnv *, jobject, jobject, jint, jint, jobject, jint);
++
++/*
++ * Class:     org_xerial_snappy_SnappyNative
++ * Method:    rawUncompress
++ * Signature: (Ljava/nio/ByteBuffer;IILjava/nio/ByteBuffer;I)I
++ */
++JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_rawUncompress__Ljava_nio_ByteBuffer_2IILjava_nio_ByteBuffer_2I
++  (JNIEnv *, jobject, jobject, jint, jint, jobject, jint);
++
++/*
++ * Class:     org_xerial_snappy_SnappyNative
++ * Method:    rawUncompress
++ * Signature: (Ljava/lang/Object;IILjava/lang/Object;I)I
++ */
++JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_rawUncompress__Ljava_lang_Object_2IILjava_lang_Object_2I
++  (JNIEnv *, jobject, jobject, jint, jint, jobject, jint);
++
++/*
++ * Class:     org_xerial_snappy_SnappyNative
++ * Method:    maxCompressedLength
++ * Signature: (I)I
++ */
++JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_maxCompressedLength
++  (JNIEnv *, jobject, jint);
++
++/*
++ * Class:     org_xerial_snappy_SnappyNative
++ * Method:    uncompressedLength
++ * Signature: (Ljava/nio/ByteBuffer;II)I
++ */
++JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_uncompressedLength__Ljava_nio_ByteBuffer_2II
++  (JNIEnv *, jobject, jobject, jint, jint);
++
++/*
++ * Class:     org_xerial_snappy_SnappyNative
++ * Method:    uncompressedLength
++ * Signature: (Ljava/lang/Object;II)I
++ */
++JNIEXPORT jint JNICALL Java_org_xerial_snappy_SnappyNative_uncompressedLength__Ljava_lang_Object_2II
++  (JNIEnv *, jobject, jobject, jint, jint);
++
++/*
++ * Class:     org_xerial_snappy_SnappyNative
++ * Method:    isValidCompressedBuffer
++ * Signature: (Ljava/nio/ByteBuffer;II)Z
++ */
++JNIEXPORT jboolean JNICALL Java_org_xerial_snappy_SnappyNative_isValidCompressedBuffer__Ljava_nio_ByteBuffer_2II
++  (JNIEnv *, jobject, jobject, jint, jint);
++
++/*
++ * Class:     org_xerial_snappy_SnappyNative
++ * Method:    isValidCompressedBuffer
++ * Signature: (Ljava/lang/Object;II)Z
++ */
++JNIEXPORT jboolean JNICALL Java_org_xerial_snappy_SnappyNative_isValidCompressedBuffer__Ljava_lang_Object_2II
++  (JNIEnv *, jobject, jobject, jint, jint);
++
++/*
++ * Class:     org_xerial_snappy_SnappyNative
++ * Method:    arrayCopy
++ * Signature: (Ljava/lang/Object;IILjava/lang/Object;I)V
++ */
++JNIEXPORT void JNICALL Java_org_xerial_snappy_SnappyNative_arrayCopy
++  (JNIEnv *, jobject, jobject, jint, jint, jobject, jint);
++
++#ifdef __cplusplus
++}
++#endif
++#endif
+--- a/Makefile.in	2011-09-15 19:29:19.000000000 +0000
++++ b/Makefile.in	2013-11-06 13:06:29.671764323 +0000
+@@ -83,7 +83,7 @@
+ LTLIBRARIES = $(lib_LTLIBRARIES)
+ libsnappy_la_LIBADD =
+ am_libsnappy_la_OBJECTS = snappy.lo snappy-sinksource.lo \
+-	snappy-stubs-internal.lo snappy-c.lo
++	snappy-stubs-internal.lo snappy-c.lo SnappyNative.lo
+ libsnappy_la_OBJECTS = $(am_libsnappy_la_OBJECTS)
+ libsnappy_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ 	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+@@ -100,7 +100,7 @@
+ snappy_unittest_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ 	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ 	$(CXXFLAGS) $(snappy_unittest_LDFLAGS) $(LDFLAGS) -o $@
+-DEFAULT_INCLUDES = -I.@am__isrc@
++DEFAULT_INCLUDES = -I.@am__isrc@ -I/usr/lib/jvm/java-6-openjdk-amd64/include
+ depcomp = $(SHELL) $(top_srcdir)/depcomp
+ am__depfiles_maybe = depfiles
+ am__mv = mv -f
+@@ -270,9 +270,9 @@
+ 
+ # Library.
+ lib_LTLIBRARIES = libsnappy.la
+-libsnappy_la_SOURCES = snappy.cc snappy-sinksource.cc snappy-stubs-internal.cc snappy-c.cc
++libsnappy_la_SOURCES = snappy.cc snappy-sinksource.cc snappy-stubs-internal.cc snappy-c.cc SnappyNative.cc
+ libsnappy_la_LDFLAGS = -version-info $(SNAPPY_LTVERSION)
+-include_HEADERS = snappy.h snappy-sinksource.h snappy-stubs-public.h snappy-c.h
++include_HEADERS = snappy.h snappy-sinksource.h snappy-stubs-public.h snappy-c.h SnappyNative.h jni_md.h
+ noinst_HEADERS = snappy-internal.h snappy-stubs-internal.h snappy-test.h
+ 
+ # Unit tests and benchmarks.
+@@ -392,6 +392,7 @@
+ distclean-compile:
+ 	-rm -f *.tab.c
+ 
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SnappyNative.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snappy-c.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snappy-sinksource.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snappy-stubs-internal.Plo@am__quote@
diff -urN b/snappy-1.0.4/debian/patches/series a/snappy-1.0.4/debian/patches/series
--- b/snappy-1.0.4/debian/patches/series	1970-01-01 00:00:00.000000000 +0000
+++ a/snappy-1.0.4/debian/patches/series	2013-11-06 14:40:02.957532121 +0000
@@ -0,0 +1 @@
+jni.patch
diff -urN b/snappy-1.0.4/debian/source/format a/snappy-1.0.4/debian/source/format
--- b/snappy-1.0.4/debian/source/format	1970-01-01 00:00:00.000000000 +0000
+++ a/snappy-1.0.4/debian/source/format	2013-11-06 14:39:41.045526935 +0000
@@ -0,0 +1 @@
+3.0 (quilt)

Reply via email to