tagging 0.11.0

git-svn-id: https://svn.apache.org/repos/asf/couchdb/tags/0.11.0@926123 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/share/www/script/test/changes.js b/share/www/script/test/changes.js
index a7703d7..b2c1a54 100644
--- a/share/www/script/test/changes.js
+++ b/share/www/script/test/changes.js
@@ -258,7 +258,8 @@
   var req = CouchDB.request("GET", 
     "/test_suite_db/_changes?filter=changes_filter/bop&style=all_docs");
   var resp = JSON.parse(req.responseText);
-  TEquals(3, resp.results.length, "should return matching rows");
+  var expect = (!is_safari && xhr) ? 3: 1;
+  TEquals(expect, resp.results.length, "should return matching rows");
   
   // test for userCtx
   run_on_modified_server(
diff --git a/share/www/script/test/replication.js b/share/www/script/test/replication.js
index c6f6ff6..c03ce43 100644
--- a/share/www/script/test/replication.js
+++ b/share/www/script/test/replication.js
@@ -329,12 +329,25 @@
 
   dbA.deleteDb();
   dbA.createDb();
-  dbB.deleteDb();
-  dbB.createDb();
 
-  T(dbA.save({_id:"foo1",value:"a"}).ok);
-  T(dbA.save({_id:"foo2",value:"b"}).ok);
-  T(dbA.save({_id:"foo3",value:"c"}).ok);
+  var all_docs = [
+    {
+      _id: "foo1",
+      value: "a"
+    },
+    {
+      _id: "foo2",
+      value: "b"
+    },
+    {
+      _id: "foo3",
+      value: "c"
+    }
+  ];
+
+  for (var i = 0; i < all_docs.length; i++) {
+    T(dbA.save(all_docs[i]).ok);
+  }
 
   var dbPairs = [
     {source:"test_suite_rep_docs_db_a",
@@ -347,34 +360,71 @@
       target:"http://" + host + "/test_suite_rep_docs_db_b"}
   ];
 
+  var target_doc_ids = [
+    ["foo1", "foo3", "foo666"],
+    ["foo1", "foo666"],
+    ["foo666", "foo2"],
+    ["foo2", "foo9999", "foo1"]
+  ];
+
   for (var i = 0; i < dbPairs.length; i++) {
-    var dbA = dbPairs[i].source;
-    var dbB = dbPairs[i].target;
+    var src_db = dbPairs[i].source;
+    var tgt_db = dbPairs[i].target;
 
-    var repResult = CouchDB.replicate(dbA, dbB, {
-      body: {"doc_ids": ["foo1", "foo3", "foo666"]}
-    });
+    for (var j = 0; j < target_doc_ids.length; j++) {
+      var doc_ids = target_doc_ids[j];
+      var valid_doc_ids = [];
+      var invalid_doc_ids = [];
 
-    T(repResult.ok);
-    T(repResult.docs_written === 2);
-    T(repResult.docs_read === 2);
-    T(repResult.doc_write_failures === 0);
+      $.each(doc_ids, function(index, id) {
+        var found = false;
 
-    dbB = new CouchDB("test_suite_rep_docs_db_b");
+        for (var k = 0; k < all_docs.length; k++) {
+          var doc = all_docs[k];
 
-    var docFoo1 = dbB.open("foo1");
-    T(docFoo1 !== null);
-    T(docFoo1.value === "a");
+          if (id === doc._id) {
+            found = true;
+            break;
+          }
+        }
 
-    var docFoo2 = dbB.open("foo2");
-    T(docFoo2 === null);
+        if (found) {
+          valid_doc_ids.push(id);
+        } else {
+          invalid_doc_ids.push(id);
+        }
+      });
 
-    var docFoo3 = dbB.open("foo3");
-    T(docFoo3 !== null);
-    T(docFoo3.value === "c");
+      dbB.deleteDb();
+      dbB.createDb();
 
-    var docFoo666 = dbB.open("foo666");
-    T(docFoo666 === null);
+      var repResult = CouchDB.replicate(src_db, tgt_db, {
+        body: {"doc_ids": doc_ids}
+      });
+
+      T(repResult.ok);
+      T(repResult.docs_written === valid_doc_ids.length);
+      T(repResult.docs_read === valid_doc_ids.length);
+      T(repResult.doc_write_failures === 0);
+
+      for (var k = 0; k < all_docs.length; k++) {
+        var doc = all_docs[k];
+        var tgt_doc = dbB.open(doc._id);
+
+        if ($.inArray(doc._id, doc_ids) >= 0) {
+          T(tgt_doc !== null);
+          T(tgt_doc.value === doc.value);
+        } else {
+          T(tgt_doc === null);
+        }
+      }
+
+      for (var k = 0; k < invalid_doc_ids.length; k++) {
+        var tgt_doc = dbB.open(invalid_doc_ids[k]);
+
+        T(tgt_doc === null);
+      }
+    }
   }
 
   // test filtered replication
diff --git a/src/couchdb/couch_rep.erl b/src/couchdb/couch_rep.erl
index c0010a9..b7f8790 100644
--- a/src/couchdb/couch_rep.erl
+++ b/src/couchdb/couch_rep.erl
@@ -451,14 +451,21 @@
     % Port = mochiweb_socket_server:get(couch_httpd, port),
     Src = get_rep_endpoint(UserCtx, proplists:get_value(<<"source">>, Props)),
     Tgt = get_rep_endpoint(UserCtx, proplists:get_value(<<"target">>, Props)),    
-    Filter = proplists:get_value(<<"filter">>, Props),
-    QueryParams = proplists:get_value(<<"query_params">>, Props),
-    Base = couch_util:to_hex(erlang:md5(
-        term_to_binary([HostName, Src, Tgt, Filter, QueryParams])
-    )),
+    Base = [HostName, Src, Tgt] ++
+        case proplists:get_value(<<"filter">>, Props) of
+        undefined ->
+            case proplists:get_value(<<"doc_ids">>, Props) of
+            undefined ->
+                [];
+            DocIds ->
+                [DocIds]
+            end;
+        Filter ->
+            [Filter, proplists:get_value(<<"query_params">>, Props, {[]})]
+        end,
     Extension = maybe_append_options(
         [<<"continuous">>, <<"create_target">>], Props),
-    {Base, Extension}.
+    {couch_util:to_hex(erlang:md5(term_to_binary(Base))), Extension}.
 
 maybe_add_trailing_slash(Url) ->
     re:replace(Url, "[^/]$", "&/", [{return, list}]).
diff --git a/test/etap/100-ref-counter.t b/test/etap/100-ref-counter.t
index 6f18d82..8f996d0 100755
--- a/test/etap/100-ref-counter.t
+++ b/test/etap/100-ref-counter.t
@@ -27,17 +27,14 @@
 
 loop() ->
     receive
-    {ping, From} ->
-        From ! pong
+        close -> ok
     end.
 
 wait() ->
     receive
-        _ ->
-            ok
-    after
-        1000 ->
-            throw(timeout_error)
+        {'DOWN', _, _, _, _} -> ok
+    after 1000 ->
+        throw(timeout_error)
     end.
 
 test() ->
@@ -94,11 +91,23 @@
         "Sanity checking that the Pid was re-added."
     ),
 
-    ChildPid1 ! {ping, self()},
+    erlang:monitor(process, ChildPid1),
+    ChildPid1 ! close,
     wait(),
-    etap:is(
-        couch_ref_counter:count(RefCtr),
-        1,
+    
+    CheckFun = fun
+        (Iter, nil) ->
+            case couch_ref_counter:count(RefCtr) of
+                1 -> Iter;
+                _ -> nil
+            end;
+        (_, Acc) ->
+            Acc
+    end,
+    Result = lists:foldl(CheckFun, nil, lists:seq(1, 10000)),
+    etap:isnt(
+        Result,
+        nil,
         "The referer count was decremented automatically on process exit."
     ),