Hello community,

here is the log from the commit of package hiredis for openSUSE:Factory checked 
in at 2015-11-26 17:01:58
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/hiredis (Old)
 and      /work/SRC/openSUSE:Factory/.hiredis.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "hiredis"

Changes:
--------
--- /work/SRC/openSUSE:Factory/hiredis/hiredis.changes  2015-03-05 
18:16:31.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.hiredis.new/hiredis.changes     2015-11-26 
17:02:19.000000000 +0100
@@ -1,0 +2,25 @@
+Sun Nov 22 08:50:22 UTC 2015 - [email protected]
+
+- Update to 0.13.3
+       * Revert "Clear `REDIS_CONNECTED` flag when connection is 
+               closed".
+       * Make tests pass on FreeBSD
+- Changes for 0.13.2
+       * Prevent crash on pending replies in async code
+       * Clear `REDIS_CONNECTED` flag when connection is closed
+       * Add MacOS X addapter
+       * Add Qt adapter
+       * Add Ivykis adapter
+- Changes for 0.13.1
+       * Fix memory leak in async reply handling
+       * Rename struct member to avoid name clash with pre-c99 code
+- Changes for 0.13.0
+       * Windows compatibility layer for parser code
+       * Properly escape data printed to PKGCONF file
+       * Fix tests when assert() undefined 
+       * Implement a reconnect method for the client context, this 
+               changes the structure of `redisContext`
+- Drop hiredis-pkgconfig.patch
+  * fixed in upstream
+
+-------------------------------------------------------------------

Old:
----
  hiredis-pkgconfig.patch
  v0.12.1.tar.gz

New:
----
  v0.13.3.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ hiredis.spec ++++++
--- /var/tmp/diff_new_pack.8qC16B/_old  2015-11-26 17:02:19.000000000 +0100
+++ /var/tmp/diff_new_pack.8qC16B/_new  2015-11-26 17:02:19.000000000 +0100
@@ -16,16 +16,15 @@
 #
 
 
-%global libname lib%{name}0_12
+%global libname lib%{name}0_13
 Name:           hiredis
-Version:        0.12.1
+Version:        0.13.3
 Release:        0
 Summary:        Minimalistic C client for Redis
 License:        BSD-3-Clause
 Group:          Productivity/Databases/Clients
 Url:            https://github.com/redis/hiredis
 Source0:        https://github.com/redis/hiredis/archive/v%{version}.tar.gz
-Patch0:         hiredis-pkgconfig.patch
 BuildRequires:  pkg-config
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 
@@ -52,7 +51,6 @@
 
 %prep
 %setup -q
-%patch0 -p1
 
 %build
 make %{?_smp_mflags} OPTIMIZATION="%{optflags}" PREFIX=%{_prefix} 
LIBRARY_PATH=%{_lib}

++++++ v0.12.1.tar.gz -> v0.13.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/.travis.yml 
new/hiredis-0.13.3/.travis.yml
--- old/hiredis-0.12.1/.travis.yml      2015-01-26 16:08:40.000000000 +0100
+++ new/hiredis-0.13.3/.travis.yml      2015-09-16 12:25:02.000000000 +0200
@@ -1,15 +1,24 @@
 language: c
+sudo: false
 compiler:
   - gcc
   - clang
 
+addons:
+  apt:
+    packages:
+    - libc6-dbg
+    - libc6-dev
+    - libc6:i386
+    - libc6-dev-i386
+    - libc6-dbg:i386
+    - gcc-multilib
+    - valgrind
+
 env:
     - CFLAGS="-Werror"
     - PRE="valgrind --track-origins=yes --leak-check=full"
-    - TARGET="32bit" CFLAGS="-Werror"
-    - TARGET="32bit" PRE="valgrind --track-origins=yes --leak-check=full"
-
-install:
-    - sudo apt-get install libc6-dbg libc6-dev libc6-i686:i386 libc6-dev-i386 
libc6-dbg:i386 valgrind -y
+    - TARGET="32bit" TARGET_VARS="32bit-vars" CFLAGS="-Werror"
+    - TARGET="32bit" TARGET_VARS="32bit-vars" PRE="valgrind 
--track-origins=yes --leak-check=full"
 
-script: make $TARGET CFLAGS="$CFLAGS" && make check PRE="$PRE"
+script: make $TARGET CFLAGS="$CFLAGS" && make check PRE="$PRE" && make 
$TARGET_VARS hiredis-example
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/CHANGELOG.md 
new/hiredis-0.13.3/CHANGELOG.md
--- old/hiredis-0.12.1/CHANGELOG.md     2015-01-26 16:08:40.000000000 +0100
+++ new/hiredis-0.13.3/CHANGELOG.md     2015-09-16 12:25:02.000000000 +0200
@@ -1,9 +1,51 @@
-### 0.12.1 - January 26, 2015
+### 0.13.3 (2015-09-16)
+
+* Revert "Clear `REDIS_CONNECTED` flag when connection is closed".
+* Make tests pass on FreeBSD (Thanks, Giacomo Olgeni)
+
+
+If the `REDIS_CONNECTED` flag is cleared,
+the async onDisconnect callback function will never be called.
+This causes problems as the disconnect is never reported back to the user.
+
+### 0.13.2 (2015-08-25)
+
+* Prevent crash on pending replies in async code (Thanks, @switch-st)
+* Clear `REDIS_CONNECTED` flag when connection is closed (Thanks, Jerry Jacobs)
+* Add MacOS X addapter (Thanks, @dizzus)
+* Add Qt adapter (Thanks, Pietro Cerutti)
+* Add Ivykis adapter (Thanks, Gergely Nagy)
+
+All adapters are provided as is and are only tested where possible.
+
+### 0.13.1 (2015-05-03)
+
+This is a bug fix release.
+The new `reconnect` method introduced new struct members, which clashed with 
pre-defined names in pre-C99 code.
+Another commit forced C99 compilation just to make it work, but of course this 
is not desirable for outside projects.
+Other non-C99 code can now use hiredis as usual again.
+Sorry for the inconvenience.
+
+* Fix memory leak in async reply handling (Salvatore Sanfilippo)
+* Rename struct member to avoid name clash with pre-c99 code (Alex Balashov, 
ncopa)
+
+### 0.13.0 (2015-04-16)
+
+This release adds a minimal Windows compatibility layer.
+The parser, standalone since v0.12.0, can now be compiled on Windows
+(and thus used in other client libraries as well)
+
+* Windows compatibility layer for parser code (tzickel)
+* Properly escape data printed to PKGCONF file (Dan Skorupski)
+* Fix tests when assert() undefined (Keith Bennett, Matt Stancliff)
+* Implement a reconnect method for the client context, this changes the 
structure of `redisContext` (Aaron Bedra)
+
+### 0.12.1 (2015-01-26)
 
 * Fix `make install`: DESTDIR support, install all required files, install 
PKGCONF in proper location
 * Fix `make test` as 32 bit build on 64 bit platform
 
-### 0.12.0 - January 22, 2015
+### 0.12.0 (2015-01-22)
 
 * Add optional KeepAlive support
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/Makefile new/hiredis-0.13.3/Makefile
--- old/hiredis-0.12.1/Makefile 2015-01-26 16:08:40.000000000 +0100
+++ new/hiredis-0.13.3/Makefile 2015-09-16 12:25:02.000000000 +0200
@@ -12,6 +12,7 @@
 HIREDIS_MAJOR=$(shell grep HIREDIS_MAJOR hiredis.h | awk '{print $$3}')
 HIREDIS_MINOR=$(shell grep HIREDIS_MINOR hiredis.h | awk '{print $$3}')
 HIREDIS_PATCH=$(shell grep HIREDIS_PATCH hiredis.h | awk '{print $$3}')
+HIREDIS_SONAME=$(shell grep HIREDIS_SONAME hiredis.h | awk '{print $$3}')
 
 # Installation related variables and target
 PREFIX?=/usr/local
@@ -36,6 +37,7 @@
 
 # Fallback to gcc when $CC is not in $PATH.
 CC:=$(shell sh -c 'type $(CC) >/dev/null 2>/dev/null && echo $(CC) || echo 
gcc')
+CXX:=$(shell sh -c 'type $(CXX) >/dev/null 2>/dev/null && echo $(CXX) || echo 
g++')
 OPTIMIZATION?=-O3
 WARNINGS=-Wall -W -Wstrict-prototypes -Wwrite-strings
 DEBUG?= -g -ggdb
@@ -44,7 +46,7 @@
 
 DYLIBSUFFIX=so
 STLIBSUFFIX=a
-DYLIB_MINOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR).$(HIREDIS_MINOR)
+DYLIB_MINOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_SONAME)
 DYLIB_MAJOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR)
 DYLIBNAME=$(LIBNAME).$(DYLIBSUFFIX)
 DYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) 
$(LDFLAGS)
@@ -60,8 +62,7 @@
 endif
 ifeq ($(uname_S),Darwin)
   DYLIBSUFFIX=dylib
-  DYLIB_MINOR_NAME=$(LIBNAME).$(HIREDIS_MAJOR).$(HIREDIS_MINOR).$(DYLIBSUFFIX)
-  DYLIB_MAJOR_NAME=$(LIBNAME).$(HIREDIS_MAJOR).$(DYLIBSUFFIX)
+  DYLIB_MINOR_NAME=$(LIBNAME).$(HIREDIS_SONAME).$(DYLIBSUFFIX)
   DYLIB_MAKE_CMD=$(CC) -shared -Wl,-install_name,$(DYLIB_MINOR_NAME) -o 
$(DYLIBNAME) $(LDFLAGS)
 endif
 
@@ -95,6 +96,12 @@
 hiredis-example-glib: examples/example-glib.c adapters/glib.h $(STLIBNAME)
        $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) $(shell pkg-config 
--cflags --libs glib-2.0) -I. $< $(STLIBNAME)
 
+hiredis-example-ivykis: examples/example-ivykis.c adapters/ivykis.h 
$(STLIBNAME)
+       $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -livykis 
$(STLIBNAME)
+
+hiredis-example-macosx: examples/example-macosx.c adapters/macosx.h 
$(STLIBNAME)
+       $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -framework 
CoreFoundation $(STLIBNAME)
+
 ifndef AE_DIR
 hiredis-example-ae:
        @echo "Please specify AE_DIR (e.g. <redis repository>/src)"
@@ -110,7 +117,20 @@
        @false
 else
 hiredis-example-libuv: examples/example-libuv.c adapters/libuv.h $(STLIBNAME)
-       $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. 
-I$(LIBUV_DIR)/include $< $(LIBUV_DIR)/.libs/libuv.a -lpthread $(STLIBNAME)
+       $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. 
-I$(LIBUV_DIR)/include $< $(LIBUV_DIR)/.libs/libuv.a -lpthread -lrt $(STLIBNAME)
+endif
+
+ifeq ($(and $(QT_MOC),$(QT_INCLUDE_DIR),$(QT_LIBRARY_DIR)),)
+hiredis-example-qt:
+       @echo "Please specify QT_MOC, QT_INCLUDE_DIR AND QT_LIBRARY_DIR"
+       @false
+else
+hiredis-example-qt: examples/example-qt.cpp adapters/qt.h $(STLIBNAME)
+       $(QT_MOC) adapters/qt.h -I. -I$(QT_INCLUDE_DIR) 
-I$(QT_INCLUDE_DIR)/QtCore | \
+           $(CXX) -x c++ -o qt-adapter-moc.o -c - $(REAL_CFLAGS) -I. 
-I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore
+       $(QT_MOC) examples/example-qt.h -I. -I$(QT_INCLUDE_DIR) 
-I$(QT_INCLUDE_DIR)/QtCore | \
+           $(CXX) -x c++ -o qt-example-moc.o -c - $(REAL_CFLAGS) -I. 
-I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore
+       $(CXX) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. 
-I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore -L$(QT_LIBRARY_DIR) 
qt-adapter-moc.o qt-example-moc.o $< -pthread $(STLIBNAME) -lQtCore
 endif
 
 hiredis-example: examples/example.c $(STLIBNAME)
@@ -150,22 +170,21 @@
 $(PKGCONFNAME): hiredis.h
        @echo "Generating $@ for pkgconfig..."
        @echo prefix=$(PREFIX) > $@
-       @echo exec_prefix=$${prefix} >> $@
-       @echo libdir=$(INSTALL_LIBRARY_PATH) >> $@
-       @echo includedir=$(INSTALL_INCLUDE_PATH) >> $@
+       @echo exec_prefix=\$${prefix} >> $@
+       @echo libdir=$(PREFIX)/$(LIBRARY_PATH) >> $@
+       @echo includedir=$(PREFIX)/$(INCLUDE_PATH) >> $@
        @echo >> $@
        @echo Name: hiredis >> $@
        @echo Description: Minimalistic C client library for Redis. >> $@
        @echo Version: $(HIREDIS_MAJOR).$(HIREDIS_MINOR).$(HIREDIS_PATCH) >> $@
-       @echo Libs: -L$${libdir} -lhiredis >> $@
-       @echo Cflags: -I$${includedir} -D_FILE_OFFSET_BITS=64 >> $@
+       @echo Libs: -L\$${libdir} -lhiredis >> $@
+       @echo Cflags: -I\$${includedir} -D_FILE_OFFSET_BITS=64 >> $@
 
-install: $(DYLIBNAME) $(STLIBNAME)
+install: $(DYLIBNAME) $(STLIBNAME) $(PKGCONFNAME)
        mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_LIBRARY_PATH)
        $(INSTALL) hiredis.h async.h read.h sds.h adapters 
$(INSTALL_INCLUDE_PATH)
        $(INSTALL) $(DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME)
-       cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) 
$(DYLIB_MAJOR_NAME)
-       cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MAJOR_NAME) $(DYLIBNAME)
+       cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIBNAME)
        $(INSTALL) $(STLIBNAME) $(INSTALL_LIBRARY_PATH)
        mkdir -p $(INSTALL_PKGCONF_PATH)
        $(INSTALL) $(PKGCONFNAME) $(INSTALL_PKGCONF_PATH)
@@ -176,6 +195,10 @@
        @echo ""
        $(MAKE) CFLAGS="-m32" LDFLAGS="-m32"
 
+32bit-vars:
+       $(eval CFLAGS=-m32)
+       $(eval LDFLAGS=-m32)
+
 gprof:
        $(MAKE) CFLAGS="-pg" LDFLAGS="-pg"
 
@@ -191,4 +214,4 @@
 noopt:
        $(MAKE) OPTIMIZATION=""
 
-.PHONY: all test check clean dep install 32bit gprof gcov noopt
+.PHONY: all test check clean dep install 32bit 32bit-vars gprof gcov noopt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/README.md new/hiredis-0.13.3/README.md
--- old/hiredis-0.12.1/README.md        2015-01-26 16:08:40.000000000 +0100
+++ new/hiredis-0.13.3/README.md        2015-09-16 12:25:02.000000000 +0200
@@ -387,4 +387,6 @@
 ## AUTHORS
 
 Hiredis was written by Salvatore Sanfilippo (antirez at gmail) and
-Pieter Noordhuis (pcnoordhuis at gmail) and is released under the BSD license.
+Pieter Noordhuis (pcnoordhuis at gmail) and is released under the BSD license. 
 
+Hiredis is currently maintained by Matt Stancliff (matt at genges dot com) and
+Jan-Erik Rediger (janerik at fnordig dot com)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/adapters/glib.h 
new/hiredis-0.13.3/adapters/glib.h
--- old/hiredis-0.12.1/adapters/glib.h  2015-01-26 16:08:40.000000000 +0100
+++ new/hiredis-0.13.3/adapters/glib.h  2015-09-16 12:25:02.000000000 +0200
@@ -16,43 +16,43 @@
 static void
 redis_source_add_read (gpointer data)
 {
-    RedisSource *source = data;
+    RedisSource *source = (RedisSource *)data;
     g_return_if_fail(source);
     source->poll_fd.events |= G_IO_IN;
-    g_main_context_wakeup(g_source_get_context(data));
+    g_main_context_wakeup(g_source_get_context((GSource *)data));
 }
 
 static void
 redis_source_del_read (gpointer data)
 {
-    RedisSource *source = data;
+    RedisSource *source = (RedisSource *)data;
     g_return_if_fail(source);
     source->poll_fd.events &= ~G_IO_IN;
-    g_main_context_wakeup(g_source_get_context(data));
+    g_main_context_wakeup(g_source_get_context((GSource *)data));
 }
 
 static void
 redis_source_add_write (gpointer data)
 {
-    RedisSource *source = data;
+    RedisSource *source = (RedisSource *)data;
     g_return_if_fail(source);
     source->poll_fd.events |= G_IO_OUT;
-    g_main_context_wakeup(g_source_get_context(data));
+    g_main_context_wakeup(g_source_get_context((GSource *)data));
 }
 
 static void
 redis_source_del_write (gpointer data)
 {
-    RedisSource *source = data;
+    RedisSource *source = (RedisSource *)data;
     g_return_if_fail(source);
     source->poll_fd.events &= ~G_IO_OUT;
-    g_main_context_wakeup(g_source_get_context(data));
+    g_main_context_wakeup(g_source_get_context((GSource *)data));
 }
 
 static void
 redis_source_cleanup (gpointer data)
 {
-    RedisSource *source = data;
+    RedisSource *source = (RedisSource *)data;
 
     g_return_if_fail(source);
 
@@ -63,7 +63,7 @@
      * current main loop. However, we will remove the GPollFD.
      */
     if (source->poll_fd.fd >= 0) {
-        g_source_remove_poll(data, &source->poll_fd);
+        g_source_remove_poll((GSource *)data, &source->poll_fd);
         source->poll_fd.fd = -1;
     }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/adapters/ivykis.h 
new/hiredis-0.13.3/adapters/ivykis.h
--- old/hiredis-0.12.1/adapters/ivykis.h        1970-01-01 01:00:00.000000000 
+0100
+++ new/hiredis-0.13.3/adapters/ivykis.h        2015-09-16 12:25:02.000000000 
+0200
@@ -0,0 +1,81 @@
+#ifndef __HIREDIS_IVYKIS_H__
+#define __HIREDIS_IVYKIS_H__
+#include <iv.h>
+#include "../hiredis.h"
+#include "../async.h"
+
+typedef struct redisIvykisEvents {
+    redisAsyncContext *context;
+    struct iv_fd fd;
+} redisIvykisEvents;
+
+static void redisIvykisReadEvent(void *arg) {
+    redisAsyncContext *context = (redisAsyncContext *)arg;
+    redisAsyncHandleRead(context);
+}
+
+static void redisIvykisWriteEvent(void *arg) {
+    redisAsyncContext *context = (redisAsyncContext *)arg;
+    redisAsyncHandleWrite(context);
+}
+
+static void redisIvykisAddRead(void *privdata) {
+    redisIvykisEvents *e = (redisIvykisEvents*)privdata;
+    iv_fd_set_handler_in(&e->fd, redisIvykisReadEvent);
+}
+
+static void redisIvykisDelRead(void *privdata) {
+    redisIvykisEvents *e = (redisIvykisEvents*)privdata;
+    iv_fd_set_handler_in(&e->fd, NULL);
+}
+
+static void redisIvykisAddWrite(void *privdata) {
+    redisIvykisEvents *e = (redisIvykisEvents*)privdata;
+    iv_fd_set_handler_out(&e->fd, redisIvykisWriteEvent);
+}
+
+static void redisIvykisDelWrite(void *privdata) {
+    redisIvykisEvents *e = (redisIvykisEvents*)privdata;
+    iv_fd_set_handler_out(&e->fd, NULL);
+}
+
+static void redisIvykisCleanup(void *privdata) {
+    redisIvykisEvents *e = (redisIvykisEvents*)privdata;
+
+    iv_fd_unregister(&e->fd);
+    free(e);
+}
+
+static int redisIvykisAttach(redisAsyncContext *ac) {
+    redisContext *c = &(ac->c);
+    redisIvykisEvents *e;
+
+    /* Nothing should be attached when something is already attached */
+    if (ac->ev.data != NULL)
+        return REDIS_ERR;
+
+    /* Create container for context and r/w events */
+    e = (redisIvykisEvents*)malloc(sizeof(*e));
+    e->context = ac;
+
+    /* Register functions to start/stop listening for events */
+    ac->ev.addRead = redisIvykisAddRead;
+    ac->ev.delRead = redisIvykisDelRead;
+    ac->ev.addWrite = redisIvykisAddWrite;
+    ac->ev.delWrite = redisIvykisDelWrite;
+    ac->ev.cleanup = redisIvykisCleanup;
+    ac->ev.data = e;
+
+    /* Initialize and install read/write events */
+    IV_FD_INIT(&e->fd);
+    e->fd.fd = c->fd;
+    e->fd.handler_in = redisIvykisReadEvent;
+    e->fd.handler_out = redisIvykisWriteEvent;
+    e->fd.handler_err = NULL;
+    e->fd.cookie = e->context;
+
+    iv_fd_register(&e->fd);
+
+    return REDIS_OK;
+}
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/adapters/macosx.h 
new/hiredis-0.13.3/adapters/macosx.h
--- old/hiredis-0.12.1/adapters/macosx.h        1970-01-01 01:00:00.000000000 
+0100
+++ new/hiredis-0.13.3/adapters/macosx.h        2015-09-16 12:25:02.000000000 
+0200
@@ -0,0 +1,114 @@
+//
+//  Created by Дмитрий Бахвалов on 13.07.15.
+//  Copyright (c) 2015 Dmitry Bakhvalov. All rights reserved.
+//
+
+#ifndef __HIREDIS_MACOSX_H__
+#define __HIREDIS_MACOSX_H__
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "../hiredis.h"
+#include "../async.h"
+
+typedef struct {
+    redisAsyncContext *context;
+    CFSocketRef socketRef;
+    CFRunLoopSourceRef sourceRef;
+} RedisRunLoop;
+
+static int freeRedisRunLoop(RedisRunLoop* redisRunLoop) {
+    if( redisRunLoop != NULL ) {
+        if( redisRunLoop->sourceRef != NULL ) {
+            CFRunLoopSourceInvalidate(redisRunLoop->sourceRef);
+            CFRelease(redisRunLoop->sourceRef);
+        }
+        if( redisRunLoop->socketRef != NULL ) {
+            CFSocketInvalidate(redisRunLoop->socketRef);
+            CFRelease(redisRunLoop->socketRef);
+        }
+        free(redisRunLoop);
+    }
+    return REDIS_ERR;
+}
+
+static void redisMacOSAddRead(void *privdata) {
+    RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
+    CFSocketEnableCallBacks(redisRunLoop->socketRef, kCFSocketReadCallBack);
+}
+
+static void redisMacOSDelRead(void *privdata) {
+    RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
+    CFSocketDisableCallBacks(redisRunLoop->socketRef, kCFSocketReadCallBack);
+}
+
+static void redisMacOSAddWrite(void *privdata) {
+    RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
+    CFSocketEnableCallBacks(redisRunLoop->socketRef, kCFSocketWriteCallBack);
+}
+
+static void redisMacOSDelWrite(void *privdata) {
+    RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
+    CFSocketDisableCallBacks(redisRunLoop->socketRef, kCFSocketWriteCallBack);
+}
+
+static void redisMacOSCleanup(void *privdata) {
+    RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
+    freeRedisRunLoop(redisRunLoop);
+}
+
+static void redisMacOSAsyncCallback(CFSocketRef __unused s, 
CFSocketCallBackType callbackType, CFDataRef __unused address, const void 
__unused *data, void *info) {
+    redisAsyncContext* context = (redisAsyncContext*) info;
+
+    switch (callbackType) {
+        case kCFSocketReadCallBack:
+            redisAsyncHandleRead(context);
+            break;
+
+        case kCFSocketWriteCallBack:
+            redisAsyncHandleWrite(context);
+            break;
+
+        default:
+            break;
+    }
+}
+
+static int redisMacOSAttach(redisAsyncContext *redisAsyncCtx, CFRunLoopRef 
runLoop) {
+    redisContext *redisCtx = &(redisAsyncCtx->c);
+
+    /* Nothing should be attached when something is already attached */
+    if( redisAsyncCtx->ev.data != NULL ) return REDIS_ERR;
+
+    RedisRunLoop* redisRunLoop = (RedisRunLoop*) calloc(1, 
sizeof(RedisRunLoop));
+    if( !redisRunLoop ) return REDIS_ERR;
+
+    /* Setup redis stuff */
+    redisRunLoop->context = redisAsyncCtx;
+
+    redisAsyncCtx->ev.addRead  = redisMacOSAddRead;
+    redisAsyncCtx->ev.delRead  = redisMacOSDelRead;
+    redisAsyncCtx->ev.addWrite = redisMacOSAddWrite;
+    redisAsyncCtx->ev.delWrite = redisMacOSDelWrite;
+    redisAsyncCtx->ev.cleanup  = redisMacOSCleanup;
+    redisAsyncCtx->ev.data     = redisRunLoop;
+
+    /* Initialize and install read/write events */
+    CFSocketContext socketCtx = { 0, redisAsyncCtx, NULL, NULL, NULL };
+
+    redisRunLoop->socketRef = CFSocketCreateWithNative(NULL, redisCtx->fd,
+                                                       kCFSocketReadCallBack | 
kCFSocketWriteCallBack,
+                                                       redisMacOSAsyncCallback,
+                                                       &socketCtx);
+    if( !redisRunLoop->socketRef ) return freeRedisRunLoop(redisRunLoop);
+
+    redisRunLoop->sourceRef = CFSocketCreateRunLoopSource(NULL, 
redisRunLoop->socketRef, 0);
+    if( !redisRunLoop->sourceRef ) return freeRedisRunLoop(redisRunLoop);
+
+    CFRunLoopAddSource(runLoop, redisRunLoop->sourceRef, 
kCFRunLoopDefaultMode);
+
+    return REDIS_OK;
+}
+
+#endif
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/adapters/qt.h 
new/hiredis-0.13.3/adapters/qt.h
--- old/hiredis-0.12.1/adapters/qt.h    1970-01-01 01:00:00.000000000 +0100
+++ new/hiredis-0.13.3/adapters/qt.h    2015-09-16 12:25:02.000000000 +0200
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (C) 2014 Pietro Cerutti <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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 AUTHOR 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 AUTHOR 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.
+ */
+
+#ifndef __HIREDIS_QT_H__
+#define __HIREDIS_QT_H__
+#include <QSocketNotifier>
+#include "../async.h"
+
+static void RedisQtAddRead(void *);
+static void RedisQtDelRead(void *);
+static void RedisQtAddWrite(void *);
+static void RedisQtDelWrite(void *);
+static void RedisQtCleanup(void *);
+
+class RedisQtAdapter : public QObject {
+
+    Q_OBJECT
+
+    friend
+    void RedisQtAddRead(void * adapter) {
+        RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
+        a->addRead();
+    }
+
+    friend
+    void RedisQtDelRead(void * adapter) {
+        RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
+        a->delRead();
+    }
+
+    friend
+    void RedisQtAddWrite(void * adapter) {
+        RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
+        a->addWrite();
+    }
+
+    friend
+    void RedisQtDelWrite(void * adapter) {
+        RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
+        a->delWrite();
+    }
+
+    friend
+    void RedisQtCleanup(void * adapter) {
+        RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
+        a->cleanup();
+    }
+
+    public:
+        RedisQtAdapter(QObject * parent = 0)
+            : QObject(parent), m_ctx(0), m_read(0), m_write(0) { }
+
+        ~RedisQtAdapter() {
+            if (m_ctx != 0) {
+                m_ctx->ev.data = NULL;
+            }
+        }
+
+        int setContext(redisAsyncContext * ac) {
+            if (ac->ev.data != NULL) {
+                return REDIS_ERR;
+            }
+            m_ctx = ac;
+            m_ctx->ev.data = this;
+            m_ctx->ev.addRead = RedisQtAddRead;
+            m_ctx->ev.delRead = RedisQtDelRead;
+            m_ctx->ev.addWrite = RedisQtAddWrite;
+            m_ctx->ev.delWrite = RedisQtDelWrite;
+            m_ctx->ev.cleanup = RedisQtCleanup;
+            return REDIS_OK;
+        }
+
+    private:
+        void addRead() {
+            if (m_read) return;
+            m_read = new QSocketNotifier(m_ctx->c.fd, QSocketNotifier::Read, 
0);
+            connect(m_read, SIGNAL(activated(int)), this, SLOT(read()));
+        }
+
+        void delRead() {
+            if (!m_read) return;
+            delete m_read;
+            m_read = 0;
+        }
+
+        void addWrite() {
+            if (m_write) return;
+            m_write = new QSocketNotifier(m_ctx->c.fd, QSocketNotifier::Write, 
0);
+            connect(m_write, SIGNAL(activated(int)), this, SLOT(write()));
+        }
+
+        void delWrite() {
+            if (!m_write) return;
+            delete m_write;
+            m_write = 0;
+        }
+
+        void cleanup() {
+            delRead();
+            delWrite();
+        }
+
+    private slots:
+        void read() { redisAsyncHandleRead(m_ctx); }
+        void write() { redisAsyncHandleWrite(m_ctx); }
+
+    private:
+        redisAsyncContext * m_ctx;
+        QSocketNotifier * m_read;
+        QSocketNotifier * m_write;
+};
+
+#endif /* !__HIREDIS_QT_H__ */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/async.c new/hiredis-0.13.3/async.c
--- old/hiredis-0.12.1/async.c  2015-01-26 16:08:40.000000000 +0100
+++ new/hiredis-0.13.3/async.c  2015-09-16 12:25:02.000000000 +0200
@@ -418,7 +418,8 @@
         if (reply == NULL) {
             /* When the connection is being disconnected and there are
              * no more replies, this is the cue to really disconnect. */
-            if (c->flags & REDIS_DISCONNECTING && sdslen(c->obuf) == 0) {
+            if (c->flags & REDIS_DISCONNECTING && sdslen(c->obuf) == 0
+                && ac->replies.head == NULL) {
                 __redisAsyncDisconnect(ac);
                 return;
             }
@@ -454,6 +455,7 @@
             if (((redisReply*)reply)->type == REDIS_REPLY_ERROR) {
                 c->err = REDIS_ERR_OTHER;
                 
snprintf(c->errstr,sizeof(c->errstr),"%s",((redisReply*)reply)->str);
+                c->reader->fn->freeObject(reply);
                 __redisAsyncDisconnect(ac);
                 return;
             }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/examples/example-ivykis.c 
new/hiredis-0.13.3/examples/example-ivykis.c
--- old/hiredis-0.12.1/examples/example-ivykis.c        1970-01-01 
01:00:00.000000000 +0100
+++ new/hiredis-0.13.3/examples/example-ivykis.c        2015-09-16 
12:25:02.000000000 +0200
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+
+#include <hiredis.h>
+#include <async.h>
+#include <adapters/ivykis.h>
+
+void getCallback(redisAsyncContext *c, void *r, void *privdata) {
+    redisReply *reply = r;
+    if (reply == NULL) return;
+    printf("argv[%s]: %s\n", (char*)privdata, reply->str);
+
+    /* Disconnect after receiving the reply to GET */
+    redisAsyncDisconnect(c);
+}
+
+void connectCallback(const redisAsyncContext *c, int status) {
+    if (status != REDIS_OK) {
+        printf("Error: %s\n", c->errstr);
+        return;
+    }
+    printf("Connected...\n");
+}
+
+void disconnectCallback(const redisAsyncContext *c, int status) {
+    if (status != REDIS_OK) {
+        printf("Error: %s\n", c->errstr);
+        return;
+    }
+    printf("Disconnected...\n");
+}
+
+int main (int argc, char **argv) {
+    signal(SIGPIPE, SIG_IGN);
+
+    iv_init();
+
+    redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
+    if (c->err) {
+        /* Let *c leak for now... */
+        printf("Error: %s\n", c->errstr);
+        return 1;
+    }
+
+    redisIvykisAttach(c);
+    redisAsyncSetConnectCallback(c,connectCallback);
+    redisAsyncSetDisconnectCallback(c,disconnectCallback);
+    redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], 
strlen(argv[argc-1]));
+    redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key");
+
+    iv_main();
+
+    iv_deinit();
+
+    return 0;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/examples/example-macosx.c 
new/hiredis-0.13.3/examples/example-macosx.c
--- old/hiredis-0.12.1/examples/example-macosx.c        1970-01-01 
01:00:00.000000000 +0100
+++ new/hiredis-0.13.3/examples/example-macosx.c        2015-09-16 
12:25:02.000000000 +0200
@@ -0,0 +1,66 @@
+//
+//  Created by Дмитрий Бахвалов on 13.07.15.
+//  Copyright (c) 2015 Dmitry Bakhvalov. All rights reserved.
+//
+
+#include <stdio.h>
+
+#include <hiredis.h>
+#include <async.h>
+#include <adapters/macosx.h>
+
+void getCallback(redisAsyncContext *c, void *r, void *privdata) {
+    redisReply *reply = r;
+    if (reply == NULL) return;
+    printf("argv[%s]: %s\n", (char*)privdata, reply->str);
+
+    /* Disconnect after receiving the reply to GET */
+    redisAsyncDisconnect(c);
+}
+
+void connectCallback(const redisAsyncContext *c, int status) {
+    if (status != REDIS_OK) {
+        printf("Error: %s\n", c->errstr);
+        return;
+    }
+    printf("Connected...\n");
+}
+
+void disconnectCallback(const redisAsyncContext *c, int status) {
+    if (status != REDIS_OK) {
+        printf("Error: %s\n", c->errstr);
+        return;
+    }
+    CFRunLoopStop(CFRunLoopGetCurrent());
+    printf("Disconnected...\n");
+}
+
+int main (int argc, char **argv) {
+    signal(SIGPIPE, SIG_IGN);
+
+    CFRunLoopRef loop = CFRunLoopGetCurrent();
+    if( !loop ) {
+        printf("Error: Cannot get current run loop\n");
+        return 1;
+    }
+
+    redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
+    if (c->err) {
+        /* Let *c leak for now... */
+        printf("Error: %s\n", c->errstr);
+        return 1;
+    }
+
+    redisMacOSAttach(c, loop);
+
+    redisAsyncSetConnectCallback(c,connectCallback);
+    redisAsyncSetDisconnectCallback(c,disconnectCallback);
+
+    redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], 
strlen(argv[argc-1]));
+    redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key");
+
+    CFRunLoopRun();
+
+    return 0;
+}
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/examples/example-qt.cpp 
new/hiredis-0.13.3/examples/example-qt.cpp
--- old/hiredis-0.12.1/examples/example-qt.cpp  1970-01-01 01:00:00.000000000 
+0100
+++ new/hiredis-0.13.3/examples/example-qt.cpp  2015-09-16 12:25:02.000000000 
+0200
@@ -0,0 +1,46 @@
+#include <iostream>
+using namespace std;
+
+#include <QCoreApplication>
+#include <QTimer>
+
+#include "example-qt.h"
+
+void getCallback(redisAsyncContext *, void * r, void * privdata) {
+
+    redisReply * reply = static_cast<redisReply *>(r);
+    ExampleQt * ex = static_cast<ExampleQt *>(privdata);
+    if (reply == nullptr || ex == nullptr) return;
+
+    cout << "key: " << reply->str << endl;
+
+    ex->finish();
+}
+
+void ExampleQt::run() {
+
+    m_ctx = redisAsyncConnect("localhost", 6379);
+
+    if (m_ctx->err) {
+        cerr << "Error: " << m_ctx->errstr << endl;
+        redisAsyncFree(m_ctx);
+        emit finished();
+    }
+
+    m_adapter.setContext(m_ctx);
+
+    redisAsyncCommand(m_ctx, NULL, NULL, "SET key %s", m_value);
+    redisAsyncCommand(m_ctx, getCallback, this, "GET key");
+}
+
+int main (int argc, char **argv) {
+
+    QCoreApplication app(argc, argv);
+
+    ExampleQt example(argv[argc-1]);
+
+    QObject::connect(&example, SIGNAL(finished()), &app, SLOT(quit()));
+    QTimer::singleShot(0, &example, SLOT(run()));
+
+    return app.exec();
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/examples/example-qt.h 
new/hiredis-0.13.3/examples/example-qt.h
--- old/hiredis-0.12.1/examples/example-qt.h    1970-01-01 01:00:00.000000000 
+0100
+++ new/hiredis-0.13.3/examples/example-qt.h    2015-09-16 12:25:02.000000000 
+0200
@@ -0,0 +1,32 @@
+#ifndef __HIREDIS_EXAMPLE_QT_H
+#define __HIREDIS_EXAMPLE_QT_H
+
+#include <adapters/qt.h>
+
+class ExampleQt : public QObject {
+
+    Q_OBJECT
+
+    public:
+        ExampleQt(const char * value, QObject * parent = 0)
+            : QObject(parent), m_value(value) {}
+
+    signals:
+        void finished();
+
+    public slots:
+        void run();
+
+    private:
+        void finish() { emit finished(); }
+
+    private:
+        const char * m_value;
+        redisAsyncContext * m_ctx;
+        RedisQtAdapter m_adapter;
+
+    friend
+    void getCallback(redisAsyncContext *, void *, void *);
+};
+
+#endif /* !__HIREDIS_EXAMPLE_QT_H */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/hiredis.c new/hiredis-0.13.3/hiredis.c
--- old/hiredis-0.12.1/hiredis.c        2015-01-26 16:08:40.000000000 +0100
+++ new/hiredis-0.13.3/hiredis.c        2015-09-16 12:25:02.000000000 +0200
@@ -1,6 +1,8 @@
 /*
  * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
- * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+ * Copyright (c) 2010-2014, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+ * Copyright (c) 2015, Matt Stancliff <matt at genges dot com>,
+ *                     Jan-Erik Rediger <janerik at fnordig dot com>
  *
  * All rights reserved.
  *
@@ -598,6 +600,10 @@
     c->errstr[0] = '\0';
     c->obuf = sdsempty();
     c->reader = redisReaderCreate();
+    c->tcp.host = NULL;
+    c->tcp.source_addr = NULL;
+    c->unix_sock.path = NULL;
+    c->timeout = NULL;
 
     if (c->obuf == NULL || c->reader == NULL) {
         redisFree(c);
@@ -616,6 +622,14 @@
         sdsfree(c->obuf);
     if (c->reader != NULL)
         redisReaderFree(c->reader);
+    if (c->tcp.host)
+        free(c->tcp.host);
+    if (c->tcp.source_addr)
+        free(c->tcp.source_addr);
+    if (c->unix_sock.path)
+        free(c->unix_sock.path);
+    if (c->timeout)
+        free(c->timeout);
     free(c);
 }
 
@@ -626,6 +640,34 @@
     return fd;
 }
 
+int redisReconnect(redisContext *c) {
+    c->err = 0;
+    memset(c->errstr, '\0', strlen(c->errstr));
+
+    if (c->fd > 0) {
+        close(c->fd);
+    }
+
+    sdsfree(c->obuf);
+    redisReaderFree(c->reader);
+
+    c->obuf = sdsempty();
+    c->reader = redisReaderCreate();
+
+    if (c->connection_type == REDIS_CONN_TCP) {
+        return redisContextConnectBindTcp(c, c->tcp.host, c->tcp.port,
+                c->timeout, c->tcp.source_addr);
+    } else if (c->connection_type == REDIS_CONN_UNIX) {
+        return redisContextConnectUnix(c, c->unix_sock.path, c->timeout);
+    } else {
+        /* Something bad happened here and shouldn't have. There isn't
+           enough information in the context to reconnect. */
+        __redisSetError(c,REDIS_ERR_OTHER,"Not enough information to 
reconnect");
+    }
+
+    return REDIS_ERR;
+}
+
 /* Connect to a Redis instance. On error the field error in the returned
  * context will be set to the return value of the error function.
  * When no set of reply functions is given, the default set will be used. */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/hiredis.h new/hiredis-0.13.3/hiredis.h
--- old/hiredis-0.12.1/hiredis.h        2015-01-26 16:08:40.000000000 +0100
+++ new/hiredis-0.13.3/hiredis.h        2015-09-16 12:25:02.000000000 +0200
@@ -1,6 +1,8 @@
 /*
  * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
- * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+ * Copyright (c) 2010-2014, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+ * Copyright (c) 2015, Matt Stancliff <matt at genges dot com>,
+ *                     Jan-Erik Rediger <janerik at fnordig dot com>
  *
  * All rights reserved.
  *
@@ -38,8 +40,9 @@
 #include "sds.h" /* for sds */
 
 #define HIREDIS_MAJOR 0
-#define HIREDIS_MINOR 12
-#define HIREDIS_PATCH 1
+#define HIREDIS_MINOR 13
+#define HIREDIS_PATCH 3
+#define HIREDIS_SONAME 0.13
 
 /* Connection type can be blocking or non-blocking and is set in the
  * least significant bit of the flags field in redisContext. */
@@ -128,6 +131,11 @@
 void redisFreeCommand(char *cmd);
 void redisFreeSdsCommand(sds cmd);
 
+enum redisConnectionType {
+    REDIS_CONN_TCP,
+    REDIS_CONN_UNIX,
+};
+
 /* Context for a connection to Redis */
 typedef struct redisContext {
     int err; /* Error flags, 0 when there is no error */
@@ -136,6 +144,20 @@
     int flags;
     char *obuf; /* Write buffer */
     redisReader *reader; /* Protocol reader */
+
+    enum redisConnectionType connection_type;
+    struct timeval *timeout;
+
+    struct {
+        char *host;
+        char *source_addr;
+        int port;
+    } tcp;
+
+    struct {
+        char *path;
+    } unix_sock;
+
 } redisContext;
 
 redisContext *redisConnect(const char *ip, int port);
@@ -149,6 +171,18 @@
 redisContext *redisConnectUnixWithTimeout(const char *path, const struct 
timeval tv);
 redisContext *redisConnectUnixNonBlock(const char *path);
 redisContext *redisConnectFd(int fd);
+
+/**
+ * Reconnect the given context using the saved information.
+ *
+ * This re-uses the exact same connect options as in the initial connection.
+ * host, ip (or path), timeout and bind address are reused,
+ * flags are used unmodified from the existing context.
+ *
+ * Returns REDIS_OK on successfull connect or REDIS_ERR otherwise.
+ */
+int redisReconnect(redisContext *c);
+
 int redisSetTimeout(redisContext *c, const struct timeval tv);
 int redisEnableKeepAlive(redisContext *c);
 void redisFree(redisContext *c);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/net.c new/hiredis-0.13.3/net.c
--- old/hiredis-0.12.1/net.c    2015-01-26 16:08:40.000000000 +0100
+++ new/hiredis-0.13.3/net.c    2015-09-16 12:25:02.000000000 +0200
@@ -1,7 +1,9 @@
 /* Extracted from anet.c to work properly with Hiredis error reporting.
  *
- * Copyright (c) 2006-2011, Salvatore Sanfilippo <antirez at gmail dot com>
- * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+ * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
+ * Copyright (c) 2010-2014, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+ * Copyright (c) 2015, Matt Stancliff <matt at genges dot com>,
+ *                     Jan-Erik Rediger <janerik at fnordig dot com>
  *
  * All rights reserved.
  *
@@ -47,6 +49,7 @@
 #include <stdio.h>
 #include <poll.h>
 #include <limits.h>
+#include <stdlib.h>
 
 #include "net.h"
 #include "sds.h"
@@ -263,6 +266,44 @@
     int reuseaddr = (c->flags & REDIS_REUSEADDR);
     int reuses = 0;
 
+    c->connection_type = REDIS_CONN_TCP;
+    c->tcp.port = port;
+
+    /* We need to take possession of the passed parameters
+     * to make them reusable for a reconnect.
+     * We also carefully check we don't free data we already own,
+     * as in the case of the reconnect method.
+     *
+     * This is a bit ugly, but atleast it works and doesn't leak memory.
+     **/
+    if (c->tcp.host != addr) {
+        if (c->tcp.host)
+            free(c->tcp.host);
+
+        c->tcp.host = strdup(addr);
+    }
+
+    if (timeout) {
+        if (c->timeout != timeout) {
+            if (c->timeout == NULL)
+                c->timeout = malloc(sizeof(struct timeval));
+
+            memcpy(c->timeout, timeout, sizeof(struct timeval));
+        }
+    } else {
+        if (c->timeout)
+            free(c->timeout);
+        c->timeout = NULL;
+    }
+
+    if (source_addr == NULL) {
+        free(c->tcp.source_addr);
+        c->tcp.source_addr = NULL;
+    } else if (c->tcp.source_addr != source_addr) {
+        free(c->tcp.source_addr);
+        c->tcp.source_addr = strdup(source_addr);
+    }
+
     snprintf(_port, 6, "%d", port);
     memset(&hints,0,sizeof(hints));
     hints.ai_family = AF_INET;
@@ -273,7 +314,7 @@
      * as this would add latency to every connect. Otherwise a more sensible
      * route could be: Use IPv6 if both addresses are available and there is 
IPv6
      * connectivity. */
-    if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {
+    if ((rv = getaddrinfo(c->tcp.host,_port,&hints,&servinfo)) != 0) {
          hints.ai_family = AF_INET6;
          if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {
             __redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv));
@@ -288,10 +329,10 @@
         c->fd = s;
         if (redisSetBlocking(c,0) != REDIS_OK)
             goto error;
-        if (source_addr) {
+        if (c->tcp.source_addr) {
             int bound = 0;
             /* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */
-            if ((rv = getaddrinfo(source_addr, NULL, &hints, &bservinfo)) != 
0) {
+            if ((rv = getaddrinfo(c->tcp.source_addr, NULL, &hints, 
&bservinfo)) != 0) {
                 char buf[128];
                 snprintf(buf,sizeof(buf),"Can't get addr: 
%s",gai_strerror(rv));
                 __redisSetError(c,REDIS_ERR_OTHER,buf);
@@ -333,7 +374,7 @@
                     goto addrretry;
                 }
             } else {
-                if (redisContextWaitReady(c,timeout) != REDIS_OK)
+                if (redisContextWaitReady(c,c->timeout) != REDIS_OK)
                     goto error;
             }
         }
@@ -380,13 +421,30 @@
     if (redisSetBlocking(c,0) != REDIS_OK)
         return REDIS_ERR;
 
+    c->connection_type = REDIS_CONN_UNIX;
+    if (c->unix_sock.path != path)
+        c->unix_sock.path = strdup(path);
+
+    if (timeout) {
+        if (c->timeout != timeout) {
+            if (c->timeout == NULL)
+                c->timeout = malloc(sizeof(struct timeval));
+
+            memcpy(c->timeout, timeout, sizeof(struct timeval));
+        }
+    } else {
+        if (c->timeout)
+            free(c->timeout);
+        c->timeout = NULL;
+    }
+
     sa.sun_family = AF_LOCAL;
     strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);
     if (connect(c->fd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
         if (errno == EINPROGRESS && !blocking) {
             /* This is ok. */
         } else {
-            if (redisContextWaitReady(c,timeout) != REDIS_OK)
+            if (redisContextWaitReady(c,c->timeout) != REDIS_OK)
                 return REDIS_ERR;
         }
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/net.h new/hiredis-0.13.3/net.h
--- old/hiredis-0.12.1/net.h    2015-01-26 16:08:40.000000000 +0100
+++ new/hiredis-0.13.3/net.h    2015-09-16 12:25:02.000000000 +0200
@@ -1,7 +1,9 @@
 /* Extracted from anet.c to work properly with Hiredis error reporting.
  *
- * Copyright (c) 2006-2011, Salvatore Sanfilippo <antirez at gmail dot com>
- * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+ * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
+ * Copyright (c) 2010-2014, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+ * Copyright (c) 2015, Matt Stancliff <matt at genges dot com>,
+ *                     Jan-Erik Rediger <janerik at fnordig dot com>
  *
  * All rights reserved.
  *
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/read.c new/hiredis-0.13.3/read.c
--- old/hiredis-0.12.1/read.c   2015-01-26 16:08:40.000000000 +0100
+++ new/hiredis-0.13.3/read.c   2015-09-16 12:25:02.000000000 +0200
@@ -33,7 +33,9 @@
 #include "fmacros.h"
 #include <string.h>
 #include <stdlib.h>
+#ifndef _MSC_VER
 #include <unistd.h>
+#endif
 #include <assert.h>
 #include <errno.h>
 #include <ctype.h>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/sds.c new/hiredis-0.13.3/sds.c
--- old/hiredis-0.12.1/sds.c    2015-01-26 16:08:40.000000000 +0100
+++ new/hiredis-0.13.3/sds.c    2015-09-16 12:25:02.000000000 +0200
@@ -103,7 +103,7 @@
  * the output will be "6" as the string was modified but the logical length
  * remains 6 bytes. */
 void sdsupdatelen(sds s) {
-    struct sdshdr *sh = (void*) (s-sizeof *sh);;
+    struct sdshdr *sh = (void*) (s-sizeof *sh);
     int reallen = strlen(s);
     sh->free += (sh->len-reallen);
     sh->len = reallen;
@@ -114,7 +114,7 @@
  * so that next append operations will not require allocations up to the
  * number of bytes previously available. */
 void sdsclear(sds s) {
-    struct sdshdr *sh = (void*) (s-sizeof *sh);;
+    struct sdshdr *sh = (void*) (s-sizeof *sh);
     sh->free += sh->len;
     sh->len = 0;
     sh->buf[0] = '\0';
@@ -133,7 +133,7 @@
 
     if (free >= addlen) return s;
     len = sdslen(s);
-    sh = (void*) (s-sizeof *sh);;
+    sh = (void*) (s-sizeof *sh);
     newlen = (len+addlen);
     if (newlen < SDS_MAX_PREALLOC)
         newlen *= 2;
@@ -155,7 +155,7 @@
 sds sdsRemoveFreeSpace(sds s) {
     struct sdshdr *sh;
 
-    sh = (void*) (s-sizeof *sh);;
+    sh = (void*) (s-sizeof *sh);
     sh = realloc(sh, sizeof *sh+sh->len+1);
     sh->free = 0;
     return sh->buf;
@@ -169,7 +169,7 @@
  * 4) The implicit null term.
  */
 size_t sdsAllocSize(sds s) {
-    struct sdshdr *sh = (void*) (s-sizeof *sh);;
+    struct sdshdr *sh = (void*) (s-sizeof *sh);
 
     return sizeof(*sh)+sh->len+sh->free+1;
 }
@@ -198,7 +198,7 @@
  * sdsIncrLen(s, nread);
  */
 void sdsIncrLen(sds s, int incr) {
-    struct sdshdr *sh = (void*) (s-sizeof *sh);;
+    struct sdshdr *sh = (void*) (s-sizeof *sh);
 
     assert(sh->free >= incr);
     sh->len += incr;
@@ -240,7 +240,7 @@
 
     s = sdsMakeRoomFor(s,len);
     if (s == NULL) return NULL;
-    sh = (void*) (s-sizeof *sh);;
+    sh = (void*) (s-sizeof *sh);
     memcpy(s+curlen, t, len);
     sh->len = curlen+len;
     sh->free = sh->free-len;
@@ -267,13 +267,13 @@
 /* Destructively modify the sds string 's' to hold the specified binary
  * safe string pointed by 't' of length 'len' bytes. */
 sds sdscpylen(sds s, const char *t, size_t len) {
-    struct sdshdr *sh = (void*) (s-sizeof *sh);;
+    struct sdshdr *sh = (void*) (s-sizeof *sh);
     size_t totlen = sh->free+sh->len;
 
     if (totlen < len) {
         s = sdsMakeRoomFor(s,len-sh->len);
         if (s == NULL) return NULL;
-        sh = (void*) (s-sizeof *sh);;
+        sh = (void*) (s-sizeof *sh);
         totlen = sh->free+sh->len;
     }
     memcpy(s, t, len);
@@ -541,7 +541,7 @@
  * Output will be just "Hello World".
  */
 void sdstrim(sds s, const char *cset) {
-    struct sdshdr *sh = (void*) (s-sizeof *sh);;
+    struct sdshdr *sh = (void*) (s-sizeof *sh);
     char *start, *end, *sp, *ep;
     size_t len;
 
@@ -573,7 +573,7 @@
  * sdsrange(s,1,-1); => "ello World"
  */
 void sdsrange(sds s, int start, int end) {
-    struct sdshdr *sh = (void*) (s-sizeof *sh);;
+    struct sdshdr *sh = (void*) (s-sizeof *sh);
     size_t newlen, len = sdslen(s);
 
     if (len == 0) return;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/sds.h new/hiredis-0.13.3/sds.h
--- old/hiredis-0.12.1/sds.h    2015-01-26 16:08:40.000000000 +0100
+++ new/hiredis-0.13.3/sds.h    2015-09-16 12:25:02.000000000 +0200
@@ -35,6 +35,9 @@
 
 #include <sys/types.h>
 #include <stdarg.h>
+#ifdef _MSC_VER
+#include "win32.h"
+#endif
 
 typedef char *sds;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/test.c new/hiredis-0.13.3/test.c
--- old/hiredis-0.12.1/test.c   2015-01-26 16:08:40.000000000 +0100
+++ new/hiredis-0.13.3/test.c   2015-09-16 12:25:02.000000000 +0200
@@ -11,6 +11,7 @@
 #include <limits.h>
 
 #include "hiredis.h"
+#include "net.h"
 
 enum connection_type {
     CONN_TCP,
@@ -43,6 +44,13 @@
     return (((long long)tv.tv_sec)*1000000)+tv.tv_usec;
 }
 
+/* The assert() calls below have side effects, so we need assert()
+ * even if we are compiling without asserts (-DNDEBUG). */
+#ifdef NDEBUG
+#undef assert
+#define assert(e) (void)(e)
+#endif
+
 static redisContext *select_database(redisContext *c) {
     redisReply *reply;
 
@@ -343,6 +351,7 @@
          strcmp(c->errstr,"nodename nor servname provided, or not known") == 0 
||
          strcmp(c->errstr,"No address associated with hostname") == 0 ||
          strcmp(c->errstr,"Temporary failure in name resolution") == 0 ||
+         strcmp(c->errstr,"hostname nor servname provided, or not known") == 0 
||
          strcmp(c->errstr,"no address associated with name") == 0));
     redisFree(c);
 
@@ -436,6 +445,52 @@
     disconnect(c, 0);
 }
 
+static void test_blocking_connection_timeouts(struct config config) {
+    redisContext *c;
+    redisReply *reply;
+    ssize_t s;
+    const char *cmd = "DEBUG SLEEP 3\r\n";
+    struct timeval tv;
+
+    c = connect(config);
+    test("Successfully completes a command when the timeout is not exceeded: 
");
+    reply = redisCommand(c,"SET foo fast");
+    freeReplyObject(reply);
+    tv.tv_sec = 0;
+    tv.tv_usec = 10000;
+    redisSetTimeout(c, tv);
+    reply = redisCommand(c, "GET foo");
+    test_cond(reply != NULL && reply->type == REDIS_REPLY_STRING && 
memcmp(reply->str, "fast", 4) == 0);
+    freeReplyObject(reply);
+    disconnect(c, 0);
+
+    c = connect(config);
+    test("Does not return a reply when the command times out: ");
+    s = write(c->fd, cmd, strlen(cmd));
+    tv.tv_sec = 0;
+    tv.tv_usec = 10000;
+    redisSetTimeout(c, tv);
+    reply = redisCommand(c, "GET foo");
+    test_cond(s > 0 && reply == NULL && c->err == REDIS_ERR_IO && 
strcmp(c->errstr, "Resource temporarily unavailable") == 0);
+    freeReplyObject(reply);
+
+    test("Reconnect properly reconnects after a timeout: ");
+    redisReconnect(c);
+    reply = redisCommand(c, "PING");
+    test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && 
strcmp(reply->str, "PONG") == 0);
+    freeReplyObject(reply);
+
+    test("Reconnect properly uses owned parameters: ");
+    config.tcp.host = "foo";
+    config.unix.path = "foo";
+    redisReconnect(c);
+    reply = redisCommand(c, "PING");
+    test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && 
strcmp(reply->str, "PONG") == 0);
+    freeReplyObject(reply);
+
+    disconnect(c, 0);
+}
+
 static void test_blocking_io_errors(struct config config) {
     redisContext *c;
     redisReply *reply;
@@ -459,7 +514,7 @@
 
     test("Returns I/O error when the connection is lost: ");
     reply = redisCommand(c,"QUIT");
-    if (major >= 2 && minor > 0) {
+    if (major > 2 || (major == 2 && minor > 0)) {
         /* > 2.0 returns OK on QUIT and read() should be issued once more
          * to know the descriptor is at EOF. */
         test_cond(strcasecmp(reply->str,"OK") == 0 &&
@@ -722,6 +777,7 @@
     printf("\nTesting against TCP connection (%s:%d):\n", cfg.tcp.host, 
cfg.tcp.port);
     cfg.type = CONN_TCP;
     test_blocking_connection(cfg);
+    test_blocking_connection_timeouts(cfg);
     test_blocking_io_errors(cfg);
     test_invalid_timeout_errors(cfg);
     test_append_formatted_commands(cfg);
@@ -730,6 +786,7 @@
     printf("\nTesting against Unix socket connection (%s):\n", cfg.unix.path);
     cfg.type = CONN_UNIX;
     test_blocking_connection(cfg);
+    test_blocking_connection_timeouts(cfg);
     test_blocking_io_errors(cfg);
     if (throughput) test_throughput(cfg);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hiredis-0.12.1/win32.h new/hiredis-0.13.3/win32.h
--- old/hiredis-0.12.1/win32.h  1970-01-01 01:00:00.000000000 +0100
+++ new/hiredis-0.13.3/win32.h  2015-09-16 12:25:02.000000000 +0200
@@ -0,0 +1,42 @@
+#ifndef _WIN32_HELPER_INCLUDE
+#define _WIN32_HELPER_INCLUDE
+#ifdef _MSC_VER
+
+#ifndef inline
+#define inline __inline
+#endif
+
+#ifndef va_copy
+#define va_copy(d,s) ((d) = (s))
+#endif
+
+#ifndef snprintf
+#define snprintf c99_snprintf
+
+__inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list 
ap)
+{
+    int count = -1;
+
+    if (size != 0)
+        count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
+    if (count == -1)
+        count = _vscprintf(format, ap);
+
+    return count;
+}
+
+__inline int c99_snprintf(char* str, size_t size, const char* format, ...)
+{
+    int count;
+    va_list ap;
+
+    va_start(ap, format);
+    count = c99_vsnprintf(str, size, format, ap);
+    va_end(ap);
+
+    return count;
+}
+#endif
+
+#endif
+#endif
\ No newline at end of file


Reply via email to