redis 3.0.0.rc2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.order +169 -0
- data/CHANGELOG.md +79 -9
- data/README.md +7 -0
- data/Rakefile +167 -0
- data/lib/redis.rb +1265 -1148
- data/lib/redis/client.rb +11 -18
- data/lib/redis/distributed.rb +337 -280
- data/lib/redis/pipeline.rb +12 -4
- data/lib/redis/version.rb +1 -1
- data/redis.gemspec +1 -1
- data/test/commands_on_lists_test.rb +0 -30
- data/test/commands_on_strings_test.rb +0 -6
- data/test/distributed_scripting_test.rb +102 -0
- data/test/internals_test.rb +33 -35
- data/test/lint/lists.rb +42 -12
- data/test/lint/strings.rb +6 -0
- data/test/lint/value_types.rb +10 -6
- data/test/scripting_test.rb +78 -0
- metadata +12 -8
    
        data/.order
    ADDED
    
    | @@ -0,0 +1,169 @@ | |
| 1 | 
            +
            {
         | 
| 2 | 
            +
              "connection": [
         | 
| 3 | 
            +
                "auth",
         | 
| 4 | 
            +
                "select",
         | 
| 5 | 
            +
                "ping",
         | 
| 6 | 
            +
                "echo",
         | 
| 7 | 
            +
                "quit"
         | 
| 8 | 
            +
              ],
         | 
| 9 | 
            +
              "server": [
         | 
| 10 | 
            +
                "bgrewriteaof",
         | 
| 11 | 
            +
                "bgsave",
         | 
| 12 | 
            +
                "config",
         | 
| 13 | 
            +
                "dbsize",
         | 
| 14 | 
            +
                "debug",
         | 
| 15 | 
            +
                "flushall",
         | 
| 16 | 
            +
                "flushdb",
         | 
| 17 | 
            +
                "info",
         | 
| 18 | 
            +
                "lastsave",
         | 
| 19 | 
            +
                "monitor",
         | 
| 20 | 
            +
                "save",
         | 
| 21 | 
            +
                "shutdown",
         | 
| 22 | 
            +
                "slaveof",
         | 
| 23 | 
            +
                "slowlog",
         | 
| 24 | 
            +
                "sync",
         | 
| 25 | 
            +
                "time"
         | 
| 26 | 
            +
              ],
         | 
| 27 | 
            +
              "generic": [
         | 
| 28 | 
            +
                "persist",
         | 
| 29 | 
            +
                "expire",
         | 
| 30 | 
            +
                "expireat",
         | 
| 31 | 
            +
                "ttl",
         | 
| 32 | 
            +
                "pexpire",
         | 
| 33 | 
            +
                "pexpireat",
         | 
| 34 | 
            +
                "pttl",
         | 
| 35 | 
            +
                "dump",
         | 
| 36 | 
            +
                "restore",
         | 
| 37 | 
            +
                "del",
         | 
| 38 | 
            +
                "exists",
         | 
| 39 | 
            +
                "keys",
         | 
| 40 | 
            +
                "migrate",
         | 
| 41 | 
            +
                "move",
         | 
| 42 | 
            +
                "object",
         | 
| 43 | 
            +
                "randomkey",
         | 
| 44 | 
            +
                "rename",
         | 
| 45 | 
            +
                "renamenx",
         | 
| 46 | 
            +
                "sort",
         | 
| 47 | 
            +
                "type"
         | 
| 48 | 
            +
              ],
         | 
| 49 | 
            +
              "string": [
         | 
| 50 | 
            +
                "decr",
         | 
| 51 | 
            +
                "decrby",
         | 
| 52 | 
            +
                "incr",
         | 
| 53 | 
            +
                "incrby",
         | 
| 54 | 
            +
                "incrbyfloat",
         | 
| 55 | 
            +
                "set",
         | 
| 56 | 
            +
                "setex",
         | 
| 57 | 
            +
                "psetex",
         | 
| 58 | 
            +
                "setnx",
         | 
| 59 | 
            +
                "mset",
         | 
| 60 | 
            +
                "mapped_mset",
         | 
| 61 | 
            +
                "msetnx",
         | 
| 62 | 
            +
                "mapped_msetnx",
         | 
| 63 | 
            +
                "get",
         | 
| 64 | 
            +
                "mget",
         | 
| 65 | 
            +
                "mapped_mget",
         | 
| 66 | 
            +
                "setrange",
         | 
| 67 | 
            +
                "getrange",
         | 
| 68 | 
            +
                "setbit",
         | 
| 69 | 
            +
                "getbit",
         | 
| 70 | 
            +
                "append",
         | 
| 71 | 
            +
                "bitcount",
         | 
| 72 | 
            +
                "getset",
         | 
| 73 | 
            +
                "strlen"
         | 
| 74 | 
            +
              ],
         | 
| 75 | 
            +
              "list": [
         | 
| 76 | 
            +
                "llen",
         | 
| 77 | 
            +
                "lpush",
         | 
| 78 | 
            +
                "lpushx",
         | 
| 79 | 
            +
                "rpush",
         | 
| 80 | 
            +
                "rpushx",
         | 
| 81 | 
            +
                "lpop",
         | 
| 82 | 
            +
                "rpop",
         | 
| 83 | 
            +
                "rpoplpush",
         | 
| 84 | 
            +
                "_bpop",
         | 
| 85 | 
            +
                "blpop",
         | 
| 86 | 
            +
                "brpop",
         | 
| 87 | 
            +
                "brpoplpush",
         | 
| 88 | 
            +
                "lindex",
         | 
| 89 | 
            +
                "linsert",
         | 
| 90 | 
            +
                "lrange",
         | 
| 91 | 
            +
                "lrem",
         | 
| 92 | 
            +
                "lset",
         | 
| 93 | 
            +
                "ltrim",
         | 
| 94 | 
            +
                "bitop"
         | 
| 95 | 
            +
              ],
         | 
| 96 | 
            +
              "set": [
         | 
| 97 | 
            +
                "scard",
         | 
| 98 | 
            +
                "sadd",
         | 
| 99 | 
            +
                "srem",
         | 
| 100 | 
            +
                "spop",
         | 
| 101 | 
            +
                "srandmember",
         | 
| 102 | 
            +
                "smove",
         | 
| 103 | 
            +
                "sismember",
         | 
| 104 | 
            +
                "smembers",
         | 
| 105 | 
            +
                "sdiff",
         | 
| 106 | 
            +
                "sdiffstore",
         | 
| 107 | 
            +
                "sinter",
         | 
| 108 | 
            +
                "sinterstore",
         | 
| 109 | 
            +
                "sunion",
         | 
| 110 | 
            +
                "sunionstore"
         | 
| 111 | 
            +
              ],
         | 
| 112 | 
            +
              "sorted_set": [
         | 
| 113 | 
            +
                "zcard",
         | 
| 114 | 
            +
                "zadd",
         | 
| 115 | 
            +
                "zincrby",
         | 
| 116 | 
            +
                "zrem",
         | 
| 117 | 
            +
                "zscore",
         | 
| 118 | 
            +
                "zrange",
         | 
| 119 | 
            +
                "zrevrange",
         | 
| 120 | 
            +
                "zrank",
         | 
| 121 | 
            +
                "zrevrank",
         | 
| 122 | 
            +
                "zremrangebyrank",
         | 
| 123 | 
            +
                "zrangebyscore",
         | 
| 124 | 
            +
                "zrevrangebyscore",
         | 
| 125 | 
            +
                "zremrangebyscore",
         | 
| 126 | 
            +
                "zcount",
         | 
| 127 | 
            +
                "zinterstore",
         | 
| 128 | 
            +
                "zunionstore"
         | 
| 129 | 
            +
              ],
         | 
| 130 | 
            +
              "hash": [
         | 
| 131 | 
            +
                "hlen",
         | 
| 132 | 
            +
                "hset",
         | 
| 133 | 
            +
                "hsetnx",
         | 
| 134 | 
            +
                "hmset",
         | 
| 135 | 
            +
                "mapped_hmset",
         | 
| 136 | 
            +
                "hget",
         | 
| 137 | 
            +
                "hmget",
         | 
| 138 | 
            +
                "mapped_hmget",
         | 
| 139 | 
            +
                "hdel",
         | 
| 140 | 
            +
                "hexists",
         | 
| 141 | 
            +
                "hincrby",
         | 
| 142 | 
            +
                "hincrbyfloat",
         | 
| 143 | 
            +
                "hkeys",
         | 
| 144 | 
            +
                "hvals",
         | 
| 145 | 
            +
                "hgetall"
         | 
| 146 | 
            +
              ],
         | 
| 147 | 
            +
              "pubsub": [
         | 
| 148 | 
            +
                "publish",
         | 
| 149 | 
            +
                "subscribed?",
         | 
| 150 | 
            +
                "subscribe",
         | 
| 151 | 
            +
                "unsubscribe",
         | 
| 152 | 
            +
                "psubscribe",
         | 
| 153 | 
            +
                "punsubscribe"
         | 
| 154 | 
            +
              ],
         | 
| 155 | 
            +
              "transactions": [
         | 
| 156 | 
            +
                "watch",
         | 
| 157 | 
            +
                "unwatch",
         | 
| 158 | 
            +
                "pipelined",
         | 
| 159 | 
            +
                "multi",
         | 
| 160 | 
            +
                "exec",
         | 
| 161 | 
            +
                "discard"
         | 
| 162 | 
            +
              ],
         | 
| 163 | 
            +
              "scripting": [
         | 
| 164 | 
            +
                "script",
         | 
| 165 | 
            +
                "_eval",
         | 
| 166 | 
            +
                "eval",
         | 
| 167 | 
            +
                "evalsha"
         | 
| 168 | 
            +
              ]
         | 
| 169 | 
            +
            }
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,26 +1,89 @@ | |
| 1 | 
            -
            # 3.0 | 
| 1 | 
            +
            # 3.0.0
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            ### Upgrading from 2.x to 3.0
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            The following items are the most important changes to review when
         | 
| 6 | 
            +
            upgrading from redis-rb 2.x. A full list of changes can be found below.
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            * The methods for the following commands have changed the arguments they
         | 
| 9 | 
            +
              take, their return value, or both.
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                * `BLPOP`, `BRPOP`, `BRPOPLPUSH`
         | 
| 12 | 
            +
                * `SORT`
         | 
| 13 | 
            +
                * `MSETNX`
         | 
| 14 | 
            +
                * `ZRANGE`, `ZREVRANGE`, `ZRANGEBYSCORE`, `ZREVRANGEBYSCORE`
         | 
| 15 | 
            +
                * `ZINCRBY`, `ZSCORE`
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            * The return value from `#pipelined` and `#multi` no longer contains
         | 
| 18 | 
            +
              unprocessed replies, but the same replies that would be returned if
         | 
| 19 | 
            +
              the command had not been executed in these blocks.
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            * The client raises custom errors on connection errors, instead of
         | 
| 22 | 
            +
              `RuntimeError` and errors in the `Errno` family.
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            ### Changes
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            * Added support for scripting commands (Redis 2.6).
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                Scripts can be executed using `#eval` and `#evalsha`. Both can
         | 
| 29 | 
            +
                commands can either take two arrays to specify `KEYS` and `ARGV`, or
         | 
| 30 | 
            +
                take a hash containing `:keys` and `:argv` to specify `KEYS` and
         | 
| 31 | 
            +
                `ARGV`.
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                ```ruby
         | 
| 34 | 
            +
                redis.eval("return ARGV[1] * ARGV[2]", :argv => [2, 3])
         | 
| 35 | 
            +
                  # => 6
         | 
| 36 | 
            +
                ```
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                Subcommands of the `SCRIPT` command can be executed via the
         | 
| 39 | 
            +
                `#script` method.
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                For example:
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                ```ruby
         | 
| 44 | 
            +
                redis.script(:load, "return ARGV[1] * ARGV[2]")
         | 
| 45 | 
            +
                  # => "58db5d365a1922f32e7aa717722141ea9c2b0cf3"
         | 
| 46 | 
            +
                redis.script(:exists, "58db5d365a1922f32e7aa717722141ea9c2b0cf3")
         | 
| 47 | 
            +
                  # => true
         | 
| 48 | 
            +
                redis.script(:flush)
         | 
| 49 | 
            +
                  # => "OK"
         | 
| 50 | 
            +
                ```
         | 
| 2 51 |  | 
| 3 52 | 
             
            * The repository now lives at [https://github.com/redis/redis-rb](https://github.com/redis/redis-rb).
         | 
| 4 53 | 
             
              Thanks, Ezra!
         | 
| 5 54 |  | 
| 6 | 
            -
            * Added support for `PEXPIRE`, ` | 
| 55 | 
            +
            * Added support for `PEXPIRE`, `PEXPIREAT`, `PTTL`, `PSETEX`,
         | 
| 7 56 | 
             
              `INCRYBYFLOAT`, `HINCRYBYFLOAT` and `TIME` (Redis 2.6).
         | 
| 8 57 |  | 
| 9 58 | 
             
            * `Redis.current` is now thread unsafe, because the client itself is thread safe.
         | 
| 10 59 |  | 
| 11 60 | 
             
                In the future you'll be able to do something like:
         | 
| 12 61 |  | 
| 13 | 
            -
             | 
| 62 | 
            +
                ```ruby
         | 
| 63 | 
            +
                Redis.current = Redis::Pool.connect
         | 
| 64 | 
            +
                ```
         | 
| 14 65 |  | 
| 15 66 | 
             
                This makes `Redis.current` actually usable in multi-threaded environments,
         | 
| 16 67 | 
             
                while not affecting those running a single thread.
         | 
| 17 68 |  | 
| 18 | 
            -
            * Change API for `BLPOP`, `BRPOP` and `BRPOPLPUSH`. | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 69 | 
            +
            * Change API for `BLPOP`, `BRPOP` and `BRPOPLPUSH`.
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                Both `BLPOP` and `BRPOP` now take a single argument equal to a
         | 
| 72 | 
            +
                string key, or an array with string keys, followed by an optional
         | 
| 73 | 
            +
                hash with a `:timeout` key. When not specified, the timeout defaults
         | 
| 74 | 
            +
                to `0` to not time out.
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                ```ruby
         | 
| 77 | 
            +
                redis.blpop(["list1", "list2"], :timeout => 1.0)
         | 
| 78 | 
            +
                ```
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                `BRPOPLPUSH` also takes an optional hash with a `:timeout` key as
         | 
| 81 | 
            +
                last argument for consistency. When not specified, the timeout
         | 
| 82 | 
            +
                defaults to `0` to not time out.
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                ```ruby
         | 
| 85 | 
            +
                redis.brpoplpush("some_list", "another_list", :timeout => 1.0)
         | 
| 86 | 
            +
                ```
         | 
| 24 87 |  | 
| 25 88 | 
             
            * When `SORT` is passed multiple key patterns to get via the `:get`
         | 
| 26 89 | 
             
              option, it now returns an array per result element, holding all `GET`
         | 
| @@ -32,6 +95,13 @@ | |
| 32 95 | 
             
              now return an array containing `[String, Float]` pairs when
         | 
| 33 96 | 
             
              `:with_scores => true` is passed.
         | 
| 34 97 |  | 
| 98 | 
            +
                For example:
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                ```ruby
         | 
| 101 | 
            +
                redis.zrange("zset", 0, -1, :with_scores => true)
         | 
| 102 | 
            +
                  # => [["foo", 1.0], ["bar", 2.0]]
         | 
| 103 | 
            +
                ```
         | 
| 104 | 
            +
             | 
| 35 105 | 
             
            * The `ZINCRBY` and `ZSCORE` commands now return a `Float` score instead
         | 
| 36 106 | 
             
              of a string holding a representation of the score.
         | 
| 37 107 |  | 
    
        data/README.md
    CHANGED
    
    | @@ -12,6 +12,13 @@ A Ruby client that tries to match Redis' API one-to-one, while still | |
| 12 12 | 
             
            providing an idiomatic interface. It features thread-safety, client-side
         | 
| 13 13 | 
             
            sharding, pipelining, and an obsession for performance.
         | 
| 14 14 |  | 
| 15 | 
            +
            ## Upgrading from 2.x to 3.0
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            Please refer to the [CHANGELOG][changelog-3.0.0] for a summary of the
         | 
| 18 | 
            +
            most important changes, as well as a full list of changes.
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            [changelog-3.0.0]: https://github.com/redis/redis-rb/blob/master/CHANGELOG.md#300
         | 
| 21 | 
            +
             | 
| 15 22 | 
             
            ## Getting started
         | 
| 16 23 |  | 
| 17 24 | 
             
            As of version 2.0 this client only targets Redis version 2.0 and higher.
         | 
    
        data/Rakefile
    CHANGED
    
    | @@ -148,6 +148,71 @@ namespace :doc do | |
| 148 148 | 
             
              end
         | 
| 149 149 | 
             
            end
         | 
| 150 150 |  | 
| 151 | 
            +
            class Source
         | 
| 152 | 
            +
             | 
| 153 | 
            +
              MATCHER = "(?:\\s{%d}#[^\\n]*\\n)*^\\s{%d}def ([a-z_?]+)(?:\(.*?\))?\\n.*?^\\s{%d}end\\n\\n"
         | 
| 154 | 
            +
             | 
| 155 | 
            +
              def initialize(data, options = {})
         | 
| 156 | 
            +
                @doc = parse(File.read(data), options)
         | 
| 157 | 
            +
              end
         | 
| 158 | 
            +
             | 
| 159 | 
            +
              def methods
         | 
| 160 | 
            +
                @doc.select do |d|
         | 
| 161 | 
            +
                  d.is_a?(Method)
         | 
| 162 | 
            +
                end.map do |d|
         | 
| 163 | 
            +
                  d.name
         | 
| 164 | 
            +
                end
         | 
| 165 | 
            +
              end
         | 
| 166 | 
            +
             | 
| 167 | 
            +
              def move(a, b)
         | 
| 168 | 
            +
                ao = @doc.find { |m| m.is_a?(Method) && m.name == a }
         | 
| 169 | 
            +
                bo = @doc.find { |m| m.is_a?(Method) && m.name == b }
         | 
| 170 | 
            +
                ai = @doc.index(ao)
         | 
| 171 | 
            +
                bi = @doc.index(bo)
         | 
| 172 | 
            +
             | 
| 173 | 
            +
                @doc.delete_at(ai)
         | 
| 174 | 
            +
                @doc.insert(bi, ao)
         | 
| 175 | 
            +
             | 
| 176 | 
            +
                nil
         | 
| 177 | 
            +
              end
         | 
| 178 | 
            +
             | 
| 179 | 
            +
              def to_s
         | 
| 180 | 
            +
                @doc.join
         | 
| 181 | 
            +
              end
         | 
| 182 | 
            +
             | 
| 183 | 
            +
              protected
         | 
| 184 | 
            +
             | 
| 185 | 
            +
              def parse(data, options = {})
         | 
| 186 | 
            +
                re = Regexp.new(MATCHER % ([options[:indent]] * 3), Regexp::MULTILINE)
         | 
| 187 | 
            +
                tail = data.dup
         | 
| 188 | 
            +
                doc = []
         | 
| 189 | 
            +
             | 
| 190 | 
            +
                while match = re.match(tail)
         | 
| 191 | 
            +
                  doc << match.pre_match
         | 
| 192 | 
            +
                  doc << Method.new(match)
         | 
| 193 | 
            +
                  tail = match.post_match
         | 
| 194 | 
            +
                end
         | 
| 195 | 
            +
             | 
| 196 | 
            +
                doc << tail if tail
         | 
| 197 | 
            +
                doc
         | 
| 198 | 
            +
              end
         | 
| 199 | 
            +
             | 
| 200 | 
            +
              class Method
         | 
| 201 | 
            +
             | 
| 202 | 
            +
                def initialize(match)
         | 
| 203 | 
            +
                  @match = match
         | 
| 204 | 
            +
                end
         | 
| 205 | 
            +
             | 
| 206 | 
            +
                def name
         | 
| 207 | 
            +
                  @match[1]
         | 
| 208 | 
            +
                end
         | 
| 209 | 
            +
             | 
| 210 | 
            +
                def to_s
         | 
| 211 | 
            +
                  @match[0]
         | 
| 212 | 
            +
                end
         | 
| 213 | 
            +
              end
         | 
| 214 | 
            +
            end
         | 
| 215 | 
            +
             | 
| 151 216 | 
             
            namespace :commands do
         | 
| 152 217 | 
             
              def redis_commands
         | 
| 153 218 | 
             
                $redis_commands ||= doc.keys.map do |key|
         | 
| @@ -164,6 +229,108 @@ namespace :commands do | |
| 164 229 | 
             
                end
         | 
| 165 230 | 
             
              end
         | 
| 166 231 |  | 
| 232 | 
            +
              task :order do
         | 
| 233 | 
            +
                require "json"
         | 
| 234 | 
            +
             | 
| 235 | 
            +
                reference = if File.exist?(".order")
         | 
| 236 | 
            +
                              JSON.parse(File.read(".order"))
         | 
| 237 | 
            +
                            else
         | 
| 238 | 
            +
                              {}
         | 
| 239 | 
            +
                            end
         | 
| 240 | 
            +
             | 
| 241 | 
            +
                buckets = {}
         | 
| 242 | 
            +
                doc.each do |k, v|
         | 
| 243 | 
            +
                  buckets[v["group"]] ||= []
         | 
| 244 | 
            +
                  buckets[v["group"]] << k.split.first.downcase
         | 
| 245 | 
            +
                  buckets[v["group"]].uniq!
         | 
| 246 | 
            +
                end
         | 
| 247 | 
            +
             | 
| 248 | 
            +
                result = (reference.keys + (buckets.keys - reference.keys)).map do |g|
         | 
| 249 | 
            +
                  [g, reference[g] + (buckets[g] - reference[g])]
         | 
| 250 | 
            +
                end
         | 
| 251 | 
            +
             | 
| 252 | 
            +
                File.open(".order", "w") do |f|
         | 
| 253 | 
            +
                  f.write(JSON.pretty_generate(Hash[result]))
         | 
| 254 | 
            +
                end
         | 
| 255 | 
            +
              end
         | 
| 256 | 
            +
             | 
| 257 | 
            +
              def reorder(file, options = {})
         | 
| 258 | 
            +
                require "json"
         | 
| 259 | 
            +
                require "set"
         | 
| 260 | 
            +
             | 
| 261 | 
            +
                STDERR.puts "reordering #{file}..."
         | 
| 262 | 
            +
             | 
| 263 | 
            +
                reference = if File.exist?(".order")
         | 
| 264 | 
            +
                              JSON.parse(File.read(".order"))
         | 
| 265 | 
            +
                            else
         | 
| 266 | 
            +
                              {}
         | 
| 267 | 
            +
                            end
         | 
| 268 | 
            +
             | 
| 269 | 
            +
                dst = Source.new(file, options)
         | 
| 270 | 
            +
             | 
| 271 | 
            +
                src_methods = reference.map { |k, v| v }.flatten
         | 
| 272 | 
            +
                dst_methods = dst.methods
         | 
| 273 | 
            +
             | 
| 274 | 
            +
                src_set = Set.new(src_methods)
         | 
| 275 | 
            +
                dst_set = Set.new(dst_methods)
         | 
| 276 | 
            +
             | 
| 277 | 
            +
                intersection = src_set & dst_set
         | 
| 278 | 
            +
                intersection.delete("initialize")
         | 
| 279 | 
            +
             | 
| 280 | 
            +
                loop do
         | 
| 281 | 
            +
                  src_methods = reference.map { |k, v| v }.flatten
         | 
| 282 | 
            +
                  dst_methods = dst.methods
         | 
| 283 | 
            +
             | 
| 284 | 
            +
                  src_methods = src_methods.select do |m|
         | 
| 285 | 
            +
                    intersection.include?(m)
         | 
| 286 | 
            +
                  end
         | 
| 287 | 
            +
             | 
| 288 | 
            +
                  dst_methods = dst_methods.select do |m|
         | 
| 289 | 
            +
                    intersection.include?(m)
         | 
| 290 | 
            +
                  end
         | 
| 291 | 
            +
             | 
| 292 | 
            +
                  if src_methods == dst_methods
         | 
| 293 | 
            +
                    break
         | 
| 294 | 
            +
                  end
         | 
| 295 | 
            +
             | 
| 296 | 
            +
                  rv = yield(src_methods, dst_methods, dst)
         | 
| 297 | 
            +
                  break if rv == false
         | 
| 298 | 
            +
                end
         | 
| 299 | 
            +
             | 
| 300 | 
            +
                File.open(file, "w") do |f|
         | 
| 301 | 
            +
                  f.write(dst.to_s)
         | 
| 302 | 
            +
                end
         | 
| 303 | 
            +
              end
         | 
| 304 | 
            +
             | 
| 305 | 
            +
              task :reorder do
         | 
| 306 | 
            +
                blk = lambda do |src_methods, dst_methods, dst|
         | 
| 307 | 
            +
                  src_methods.zip(dst_methods).each do |a, b|
         | 
| 308 | 
            +
                    if a != b
         | 
| 309 | 
            +
                      dst.move(a, b)
         | 
| 310 | 
            +
                      break
         | 
| 311 | 
            +
                    end
         | 
| 312 | 
            +
                  end
         | 
| 313 | 
            +
                end
         | 
| 314 | 
            +
             | 
| 315 | 
            +
                reorder "lib/redis.rb", :indent => 2, &blk
         | 
| 316 | 
            +
                reorder "lib/redis/distributed.rb", :indent => 4, &blk
         | 
| 317 | 
            +
              end
         | 
| 318 | 
            +
             | 
| 319 | 
            +
              def missing(file, options = {})
         | 
| 320 | 
            +
                src = Source.new(file, options)
         | 
| 321 | 
            +
             | 
| 322 | 
            +
                defined_methods = src.methods.map(&:downcase)
         | 
| 323 | 
            +
                required_methods = redis_commands.map(&:downcase)
         | 
| 324 | 
            +
             | 
| 325 | 
            +
                STDOUT.puts "missing in #{file}:"
         | 
| 326 | 
            +
                STDOUT.puts (required_methods - defined_methods).inspect
         | 
| 327 | 
            +
              end
         | 
| 328 | 
            +
             | 
| 329 | 
            +
              task :missing do
         | 
| 330 | 
            +
                missing "lib/redis.rb", :indent => 2
         | 
| 331 | 
            +
                missing "lib/redis/distributed.rb", :indent => 4
         | 
| 332 | 
            +
              end
         | 
| 333 | 
            +
             | 
| 167 334 | 
             
              def document(file)
         | 
| 168 335 | 
             
                source = File.read(file)
         | 
| 169 336 |  |