dbox 0.5.3 → 0.6.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/History.txt +83 -0
 - data/README.md +31 -7
 - data/TODO.txt +1 -1
 - data/VERSION +1 -1
 - data/bin/dbox +2 -1
 - data/dbox.gemspec +13 -11
 - data/lib/dbox.rb +11 -2
 - data/lib/dbox/api.rb +130 -66
 - data/lib/dbox/cacert.pem +3376 -0
 - data/lib/dbox/database.rb +106 -8
 - data/lib/dbox/syncer.rb +103 -86
 - data/lib/dbox/utils.rb +82 -0
 - data/spec/dbox_spec.rb +201 -0
 - data/spec/spec_helper.rb +2 -2
 - data/vendor/dropbox-ruby-sdk/CHANGELOG +29 -0
 - data/vendor/{dropbox-client-ruby → dropbox-ruby-sdk}/LICENSE +1 -1
 - data/vendor/dropbox-ruby-sdk/README +7 -0
 - data/vendor/dropbox-ruby-sdk/cli_example.rb +197 -0
 - data/vendor/dropbox-ruby-sdk/dropbox_controller.rb +57 -0
 - data/vendor/dropbox-ruby-sdk/gemspec.rb +25 -0
 - data/vendor/dropbox-ruby-sdk/lib/dropbox_sdk.rb +690 -0
 - data/vendor/dropbox-ruby-sdk/web_file_browser.rb +184 -0
 - metadata +16 -14
 - data/vendor/dropbox-client-ruby/README +0 -17
 - data/vendor/dropbox-client-ruby/Rakefile +0 -41
 - data/vendor/dropbox-client-ruby/config/testing.json.example +0 -16
 - data/vendor/dropbox-client-ruby/lib/dropbox.rb +0 -259
 - data/vendor/dropbox-client-ruby/manifest +0 -9
 - data/vendor/dropbox-client-ruby/test/authenticator_test.rb +0 -53
 - data/vendor/dropbox-client-ruby/test/client_test.rb +0 -100
 - data/vendor/dropbox-client-ruby/test/util.rb +0 -21
 
    
        data/lib/dbox/utils.rb
    ADDED
    
    | 
         @@ -0,0 +1,82 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Dbox
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Utils
         
     | 
| 
      
 3 
     | 
    
         
            +
                def times_equal?(t1, t2)
         
     | 
| 
      
 4 
     | 
    
         
            +
                  time_to_s(t1) == time_to_s(t2)
         
     | 
| 
      
 5 
     | 
    
         
            +
                end
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def time_to_s(t)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  case t
         
     | 
| 
      
 9 
     | 
    
         
            +
                  when Time
         
     | 
| 
      
 10 
     | 
    
         
            +
                    # matches dropbox time format
         
     | 
| 
      
 11 
     | 
    
         
            +
                    t.utc.strftime("%a, %d %b %Y %H:%M:%S +0000")
         
     | 
| 
      
 12 
     | 
    
         
            +
                  when String
         
     | 
| 
      
 13 
     | 
    
         
            +
                    t
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def parse_time(t)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  case t
         
     | 
| 
      
 19 
     | 
    
         
            +
                  when Time
         
     | 
| 
      
 20 
     | 
    
         
            +
                    t
         
     | 
| 
      
 21 
     | 
    
         
            +
                  when String
         
     | 
| 
      
 22 
     | 
    
         
            +
                    Time.parse(t)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                # assumes local_path is defined
         
     | 
| 
      
 27 
     | 
    
         
            +
                def local_to_relative_path(path)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  if path.include?(local_path)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    path.sub(local_path, "").sub(/^\//, "")
         
     | 
| 
      
 30 
     | 
    
         
            +
                  else
         
     | 
| 
      
 31 
     | 
    
         
            +
                    raise BadPath, "Not a local path: #{path}"
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                # assumes remote_path is defined
         
     | 
| 
      
 36 
     | 
    
         
            +
                def remote_to_relative_path(path)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  if path.include?(remote_path)
         
     | 
| 
      
 38 
     | 
    
         
            +
                    path.sub(remote_path, "").sub(/^\//, "")
         
     | 
| 
      
 39 
     | 
    
         
            +
                  else
         
     | 
| 
      
 40 
     | 
    
         
            +
                    raise BadPath, "Not a remote path: #{path}"
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                # assumes local_path is defined
         
     | 
| 
      
 45 
     | 
    
         
            +
                def relative_to_local_path(path)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  if path && path.length > 0
         
     | 
| 
      
 47 
     | 
    
         
            +
                    File.join(local_path, path)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  else
         
     | 
| 
      
 49 
     | 
    
         
            +
                    local_path
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                # assumes remote_path is defined
         
     | 
| 
      
 54 
     | 
    
         
            +
                def relative_to_remote_path(path)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  if path && path.length > 0
         
     | 
| 
      
 56 
     | 
    
         
            +
                    File.join(remote_path, path)
         
     | 
| 
      
 57 
     | 
    
         
            +
                  else
         
     | 
| 
      
 58 
     | 
    
         
            +
                    remote_path
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                def calculate_hash(filepath)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 64 
     | 
    
         
            +
                    Digest::MD5.file(filepath).to_s
         
     | 
| 
      
 65 
     | 
    
         
            +
                  rescue Errno::EISDIR
         
     | 
| 
      
 66 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 67 
     | 
    
         
            +
                  rescue Errno::ENOENT
         
     | 
| 
      
 68 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 69 
     | 
    
         
            +
                  end
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                def find_nonconflicting_path(filepath)
         
     | 
| 
      
 73 
     | 
    
         
            +
                  proposed = filepath
         
     | 
| 
      
 74 
     | 
    
         
            +
                  while File.exists?(proposed)
         
     | 
| 
      
 75 
     | 
    
         
            +
                    dir, p = File.split(proposed)
         
     | 
| 
      
 76 
     | 
    
         
            +
                    p = p.sub(/^(.*?)( \((\d+)\))?(\..*?)?$/) { "#{$1} (#{$3 ? $3.to_i + 1 : 1})#{$4}" }
         
     | 
| 
      
 77 
     | 
    
         
            +
                    proposed = File.join(dir, p)
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
                  proposed
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
              end
         
     | 
| 
      
 82 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/dbox_spec.rb
    CHANGED
    
    | 
         @@ -122,6 +122,101 @@ describe Dbox do 
     | 
|
| 
       122 
122 
     | 
    
         
             
                  Dbox.pull(@local).should eql(:created => ["subdir", "subdir/one.txt"], :deleted => ["foo.txt"], :updated => ["", "baz.txt"], :failed => [])
         
     | 
| 
       123 
123 
     | 
    
         
             
                  Dbox.pull(@local).should eql(:created => [], :deleted => [], :updated => [], :failed => [])
         
     | 
| 
       124 
124 
     | 
    
         
             
                end
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                it "should be able to download a bunch of files at the same time" do
         
     | 
| 
      
 127 
     | 
    
         
            +
                  Dbox.create(@remote, @local)
         
     | 
| 
      
 128 
     | 
    
         
            +
                  @alternate = "#{ALTERNATE_LOCAL_TEST_PATH}/#{@name}"
         
     | 
| 
      
 129 
     | 
    
         
            +
                  Dbox.clone(@remote, @alternate)
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                  # generate 20 x 100kB files
         
     | 
| 
      
 132 
     | 
    
         
            +
                  20.times do
         
     | 
| 
      
 133 
     | 
    
         
            +
                    make_file "#{@alternate}/#{randname}.txt", 100
         
     | 
| 
      
 134 
     | 
    
         
            +
                  end
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                  Dbox.push(@alternate)
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                  res = Dbox.pull(@local)
         
     | 
| 
      
 139 
     | 
    
         
            +
                  res[:deleted].should eql([])
         
     | 
| 
      
 140 
     | 
    
         
            +
                  res[:updated].should eql([""])
         
     | 
| 
      
 141 
     | 
    
         
            +
                  res[:failed].should eql([])
         
     | 
| 
      
 142 
     | 
    
         
            +
                  res[:created].size.should eql(20)
         
     | 
| 
      
 143 
     | 
    
         
            +
                end
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
                it "should be able to pull a series of updates to the same file" do
         
     | 
| 
      
 146 
     | 
    
         
            +
                  Dbox.create(@remote, @local)
         
     | 
| 
      
 147 
     | 
    
         
            +
                  @alternate = "#{ALTERNATE_LOCAL_TEST_PATH}/#{@name}"
         
     | 
| 
      
 148 
     | 
    
         
            +
                  Dbox.clone(@remote, @alternate)
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                  make_file "#{@local}/hello.txt"
         
     | 
| 
      
 151 
     | 
    
         
            +
                  Dbox.push(@local)
         
     | 
| 
      
 152 
     | 
    
         
            +
                  Dbox.pull(@alternate).should eql(:created => ["hello.txt"], :deleted => [], :updated => [""], :failed => [])
         
     | 
| 
      
 153 
     | 
    
         
            +
                  make_file "#{@local}/hello.txt"
         
     | 
| 
      
 154 
     | 
    
         
            +
                  Dbox.push(@local)
         
     | 
| 
      
 155 
     | 
    
         
            +
                  Dbox.pull(@alternate).should eql(:created => [], :deleted => [], :updated => ["", "hello.txt"], :failed => [])
         
     | 
| 
      
 156 
     | 
    
         
            +
                  make_file "#{@local}/hello.txt"
         
     | 
| 
      
 157 
     | 
    
         
            +
                  Dbox.push(@local)
         
     | 
| 
      
 158 
     | 
    
         
            +
                  Dbox.pull(@alternate).should eql(:created => [], :deleted => [], :updated => ["", "hello.txt"], :failed => [])
         
     | 
| 
      
 159 
     | 
    
         
            +
                end
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
                it "should handle conflicting pulls of new files gracefully" do
         
     | 
| 
      
 162 
     | 
    
         
            +
                  Dbox.create(@remote, @local)
         
     | 
| 
      
 163 
     | 
    
         
            +
                  @alternate = "#{ALTERNATE_LOCAL_TEST_PATH}/#{@name}"
         
     | 
| 
      
 164 
     | 
    
         
            +
                  Dbox.clone(@remote, @alternate)
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                  make_file "#{@local}/hello.txt"
         
     | 
| 
      
 167 
     | 
    
         
            +
                  Dbox.push(@local)
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
                  make_file "#{@alternate}/hello.txt"
         
     | 
| 
      
 170 
     | 
    
         
            +
                  Dbox.pull(@alternate).should eql(:created => ["hello.txt"], :deleted => [], :updated => [""], :conflicts => [{:original => "hello.txt", :renamed => "hello (1).txt"}], :failed => [])
         
     | 
| 
      
 171 
     | 
    
         
            +
                end
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
                it "should handle conflicting pulls of updated files gracefully" do
         
     | 
| 
      
 174 
     | 
    
         
            +
                  Dbox.create(@remote, @local)
         
     | 
| 
      
 175 
     | 
    
         
            +
                  @alternate = "#{ALTERNATE_LOCAL_TEST_PATH}/#{@name}"
         
     | 
| 
      
 176 
     | 
    
         
            +
                  Dbox.clone(@remote, @alternate)
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
                  make_file "#{@local}/hello.txt"
         
     | 
| 
      
 179 
     | 
    
         
            +
                  Dbox.push(@local)
         
     | 
| 
      
 180 
     | 
    
         
            +
                  Dbox.pull(@alternate).should eql(:created => ["hello.txt"], :deleted => [], :updated => [""], :failed => [])
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
                  make_file "#{@local}/hello.txt"
         
     | 
| 
      
 183 
     | 
    
         
            +
                  Dbox.push(@local)
         
     | 
| 
      
 184 
     | 
    
         
            +
             
     | 
| 
      
 185 
     | 
    
         
            +
                  make_file "#{@alternate}/hello.txt"
         
     | 
| 
      
 186 
     | 
    
         
            +
                  Dbox.pull(@alternate).should eql(:created => [], :deleted => [], :updated => ["", "hello.txt"], :conflicts => [{:original => "hello.txt", :renamed => "hello (1).txt"}], :failed => [])
         
     | 
| 
      
 187 
     | 
    
         
            +
                end
         
     | 
| 
      
 188 
     | 
    
         
            +
             
     | 
| 
      
 189 
     | 
    
         
            +
                it "should deal with all sorts of weird filenames when renaming due to conflicts on pull" do
         
     | 
| 
      
 190 
     | 
    
         
            +
                  Dbox.create(@remote, @local)
         
     | 
| 
      
 191 
     | 
    
         
            +
                  @alternate = "#{ALTERNATE_LOCAL_TEST_PATH}/#{@name}"
         
     | 
| 
      
 192 
     | 
    
         
            +
                  Dbox.clone(@remote, @alternate)
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
                  make_file "#{@local}/hello.txt"
         
     | 
| 
      
 195 
     | 
    
         
            +
                  make_file "#{@local}/hello (1).txt"
         
     | 
| 
      
 196 
     | 
    
         
            +
                  make_file "#{@local}/goodbye.txt"
         
     | 
| 
      
 197 
     | 
    
         
            +
                  Dbox.push(@local)
         
     | 
| 
      
 198 
     | 
    
         
            +
             
     | 
| 
      
 199 
     | 
    
         
            +
                  make_file "#{@alternate}/hello.txt"
         
     | 
| 
      
 200 
     | 
    
         
            +
                  make_file "#{@alternate}/hello (1).txt"
         
     | 
| 
      
 201 
     | 
    
         
            +
                  make_file "#{@alternate}/hello (3).txt"
         
     | 
| 
      
 202 
     | 
    
         
            +
                  make_file "#{@alternate}/hello (4).txt"
         
     | 
| 
      
 203 
     | 
    
         
            +
                  make_file "#{@alternate}/hello (test).txt"
         
     | 
| 
      
 204 
     | 
    
         
            +
                  make_file "#{@alternate}/goodbye.txt"
         
     | 
| 
      
 205 
     | 
    
         
            +
                  make_file "#{@alternate}/goodbye (1).txt"
         
     | 
| 
      
 206 
     | 
    
         
            +
                  make_file "#{@alternate}/goodbye (2).txt"
         
     | 
| 
      
 207 
     | 
    
         
            +
                  make_file "#{@alternate}/goodbye (3).txt"
         
     | 
| 
      
 208 
     | 
    
         
            +
                  make_file "#{@alternate}/goodbye ().txt"
         
     | 
| 
      
 209 
     | 
    
         
            +
             
     | 
| 
      
 210 
     | 
    
         
            +
                  # there's a race condition, so the output could be one of two things
         
     | 
| 
      
 211 
     | 
    
         
            +
                  res = Dbox.pull(@alternate)
         
     | 
| 
      
 212 
     | 
    
         
            +
                  res[:created].should eql(["goodbye.txt", "hello (1).txt", "hello.txt"])
         
     | 
| 
      
 213 
     | 
    
         
            +
                  res[:updated].should eql([""])
         
     | 
| 
      
 214 
     | 
    
         
            +
                  res[:deleted].should eql([])
         
     | 
| 
      
 215 
     | 
    
         
            +
                  res[:failed].should eql([])
         
     | 
| 
      
 216 
     | 
    
         
            +
                  c = (res[:conflicts] == [{:original => "goodbye.txt", :renamed => "goodbye (4).txt"}, {:original => "hello (1).txt", :renamed => "hello (5).txt"}, {:original => "hello.txt", :renamed => "hello (2).txt"}]) ||
         
     | 
| 
      
 217 
     | 
    
         
            +
                    (res[:conflicts] == [{:original => "goodbye.txt", :renamed => "goodbye (4).txt"}, {:original => "hello (1).txt", :renamed => "hello (2).txt"}, {:original => "hello.txt", :renamed => "hello (5).txt"}])
         
     | 
| 
      
 218 
     | 
    
         
            +
                  c.should be_true
         
     | 
| 
      
 219 
     | 
    
         
            +
                end
         
     | 
| 
       125 
220 
     | 
    
         
             
              end
         
     | 
| 
       126 
221 
     | 
    
         | 
| 
       127 
222 
     | 
    
         
             
              describe "#push" do
         
     | 
| 
         @@ -230,6 +325,112 @@ describe Dbox do 
     | 
|
| 
       230 
325 
     | 
    
         
             
                  rm_rf @local
         
     | 
| 
       231 
326 
     | 
    
         
             
                  Dbox.clone(@remote, @local).should eql(:created => [crazy_name1, File.join(crazy_name1, "foo.txt")], :deleted => [], :updated => [""], :failed => [])
         
     | 
| 
       232 
327 
     | 
    
         
             
                end
         
     | 
| 
      
 328 
     | 
    
         
            +
             
     | 
| 
      
 329 
     | 
    
         
            +
                it "should be able to upload a bunch of files at the same time" do
         
     | 
| 
      
 330 
     | 
    
         
            +
                  Dbox.create(@remote, @local)
         
     | 
| 
      
 331 
     | 
    
         
            +
             
     | 
| 
      
 332 
     | 
    
         
            +
                  # generate 20 x 100kB files
         
     | 
| 
      
 333 
     | 
    
         
            +
                  20.times do
         
     | 
| 
      
 334 
     | 
    
         
            +
                    make_file "#{@local}/#{randname}.txt", 100
         
     | 
| 
      
 335 
     | 
    
         
            +
                  end
         
     | 
| 
      
 336 
     | 
    
         
            +
             
     | 
| 
      
 337 
     | 
    
         
            +
                  res = Dbox.push(@local)
         
     | 
| 
      
 338 
     | 
    
         
            +
                  res[:deleted].should eql([])
         
     | 
| 
      
 339 
     | 
    
         
            +
                  res[:updated].should eql([])
         
     | 
| 
      
 340 
     | 
    
         
            +
                  res[:failed].should eql([])
         
     | 
| 
      
 341 
     | 
    
         
            +
                  res[:created].size.should eql(20)
         
     | 
| 
      
 342 
     | 
    
         
            +
                end
         
     | 
| 
      
 343 
     | 
    
         
            +
             
     | 
| 
      
 344 
     | 
    
         
            +
                it "should be able to push a series of updates to the same file" do
         
     | 
| 
      
 345 
     | 
    
         
            +
                  Dbox.create(@remote, @local)
         
     | 
| 
      
 346 
     | 
    
         
            +
             
     | 
| 
      
 347 
     | 
    
         
            +
                  make_file "#{@local}/hello.txt"
         
     | 
| 
      
 348 
     | 
    
         
            +
                  Dbox.push(@local).should eql(:created => ["hello.txt"], :deleted => [], :updated => [], :failed => [])
         
     | 
| 
      
 349 
     | 
    
         
            +
                  make_file "#{@local}/hello.txt"
         
     | 
| 
      
 350 
     | 
    
         
            +
                  Dbox.push(@local).should eql(:created => [], :deleted => [], :updated => ["hello.txt"], :failed => [])
         
     | 
| 
      
 351 
     | 
    
         
            +
                  make_file "#{@local}/hello.txt"
         
     | 
| 
      
 352 
     | 
    
         
            +
                  Dbox.push(@local).should eql(:created => [], :deleted => [], :updated => ["hello.txt"], :failed => [])
         
     | 
| 
      
 353 
     | 
    
         
            +
                end
         
     | 
| 
      
 354 
     | 
    
         
            +
             
     | 
| 
      
 355 
     | 
    
         
            +
                it "should handle conflicting pushes of new files gracefully" do
         
     | 
| 
      
 356 
     | 
    
         
            +
                  Dbox.create(@remote, @local)
         
     | 
| 
      
 357 
     | 
    
         
            +
             
     | 
| 
      
 358 
     | 
    
         
            +
                  @alternate = "#{ALTERNATE_LOCAL_TEST_PATH}/#{@name}"
         
     | 
| 
      
 359 
     | 
    
         
            +
                  Dbox.clone(@remote, @alternate)
         
     | 
| 
      
 360 
     | 
    
         
            +
             
     | 
| 
      
 361 
     | 
    
         
            +
                  make_file "#{@local}/hello.txt"
         
     | 
| 
      
 362 
     | 
    
         
            +
                  Dbox.push(@local).should eql(:created => ["hello.txt"], :deleted => [], :updated => [], :failed => [])
         
     | 
| 
      
 363 
     | 
    
         
            +
             
     | 
| 
      
 364 
     | 
    
         
            +
                  make_file "#{@alternate}/hello.txt"
         
     | 
| 
      
 365 
     | 
    
         
            +
                  Dbox.push(@alternate).should eql(:created => [], :deleted => [], :updated => [], :conflicts => [{:original => "hello.txt", :renamed => "hello (1).txt"}], :failed => [])
         
     | 
| 
      
 366 
     | 
    
         
            +
                end
         
     | 
| 
      
 367 
     | 
    
         
            +
             
     | 
| 
      
 368 
     | 
    
         
            +
                it "should handle conflicting pushes of updated files gracefully" do
         
     | 
| 
      
 369 
     | 
    
         
            +
                  Dbox.create(@remote, @local)
         
     | 
| 
      
 370 
     | 
    
         
            +
                  make_file "#{@local}/hello.txt"
         
     | 
| 
      
 371 
     | 
    
         
            +
                  Dbox.push(@local)
         
     | 
| 
      
 372 
     | 
    
         
            +
             
     | 
| 
      
 373 
     | 
    
         
            +
                  @alternate = "#{ALTERNATE_LOCAL_TEST_PATH}/#{@name}"
         
     | 
| 
      
 374 
     | 
    
         
            +
                  Dbox.clone(@remote, @alternate)
         
     | 
| 
      
 375 
     | 
    
         
            +
             
     | 
| 
      
 376 
     | 
    
         
            +
                  make_file "#{@local}/hello.txt"
         
     | 
| 
      
 377 
     | 
    
         
            +
                  Dbox.push(@local).should eql(:created => [], :deleted => [], :updated => ["hello.txt"], :failed => [])
         
     | 
| 
      
 378 
     | 
    
         
            +
             
     | 
| 
      
 379 
     | 
    
         
            +
                  make_file "#{@alternate}/hello.txt"
         
     | 
| 
      
 380 
     | 
    
         
            +
                  Dbox.push(@alternate).should eql(:created => [], :deleted => [], :updated => [], :conflicts => [{:original => "hello.txt", :renamed => "hello (1).txt"}], :failed => [])
         
     | 
| 
      
 381 
     | 
    
         
            +
                end
         
     | 
| 
      
 382 
     | 
    
         
            +
              end
         
     | 
| 
      
 383 
     | 
    
         
            +
             
     | 
| 
      
 384 
     | 
    
         
            +
              describe "#sync" do
         
     | 
| 
      
 385 
     | 
    
         
            +
                it "should fail if the local dir is missing" do
         
     | 
| 
      
 386 
     | 
    
         
            +
                  expect { Dbox.sync(@local) }.to raise_error(Dbox::DatabaseError)
         
     | 
| 
      
 387 
     | 
    
         
            +
                end
         
     | 
| 
      
 388 
     | 
    
         
            +
             
     | 
| 
      
 389 
     | 
    
         
            +
                it "should be able to sync basic changes" do
         
     | 
| 
      
 390 
     | 
    
         
            +
                  Dbox.create(@remote, @local)
         
     | 
| 
      
 391 
     | 
    
         
            +
                  @alternate = "#{ALTERNATE_LOCAL_TEST_PATH}/#{@name}"
         
     | 
| 
      
 392 
     | 
    
         
            +
                  Dbox.clone(@remote, @alternate)
         
     | 
| 
      
 393 
     | 
    
         
            +
             
     | 
| 
      
 394 
     | 
    
         
            +
                  Dbox.sync(@local).should eql(:pull => { :created => [], :deleted => [], :updated => [], :failed => [] },
         
     | 
| 
      
 395 
     | 
    
         
            +
                                               :push => { :created => [], :deleted => [], :updated => [], :failed => [] })
         
     | 
| 
      
 396 
     | 
    
         
            +
                  Dbox.sync(@alternate).should eql(:pull => { :created => [], :deleted => [], :updated => [], :failed => [] },
         
     | 
| 
      
 397 
     | 
    
         
            +
                                                   :push => { :created => [], :deleted => [], :updated => [], :failed => [] })
         
     | 
| 
      
 398 
     | 
    
         
            +
             
     | 
| 
      
 399 
     | 
    
         
            +
                  make_file "#{@local}/hello.txt"
         
     | 
| 
      
 400 
     | 
    
         
            +
                  Dbox.sync(@local).should eql(:pull => { :created => [], :deleted => [], :updated => [], :failed => [] },
         
     | 
| 
      
 401 
     | 
    
         
            +
                                               :push => { :created => ["hello.txt"], :deleted => [], :updated => [], :failed => [] })
         
     | 
| 
      
 402 
     | 
    
         
            +
                  Dbox.sync(@alternate).should eql(:pull => { :created => ["hello.txt"], :deleted => [], :updated => [""], :failed => [] },
         
     | 
| 
      
 403 
     | 
    
         
            +
                                                   :push => { :created => [], :deleted => [], :updated => [], :failed => [] })
         
     | 
| 
      
 404 
     | 
    
         
            +
                end
         
     | 
| 
      
 405 
     | 
    
         
            +
             
     | 
| 
      
 406 
     | 
    
         
            +
                it "should be able to sync complex changes" do
         
     | 
| 
      
 407 
     | 
    
         
            +
                  Dbox.create(@remote, @local)
         
     | 
| 
      
 408 
     | 
    
         
            +
                  @alternate = "#{ALTERNATE_LOCAL_TEST_PATH}/#{@name}"
         
     | 
| 
      
 409 
     | 
    
         
            +
                  Dbox.clone(@remote, @alternate)
         
     | 
| 
      
 410 
     | 
    
         
            +
             
     | 
| 
      
 411 
     | 
    
         
            +
                  Dbox.sync(@local).should eql(:pull => { :created => [], :deleted => [], :updated => [], :failed => [] },
         
     | 
| 
      
 412 
     | 
    
         
            +
                                               :push => { :created => [], :deleted => [], :updated => [], :failed => [] })
         
     | 
| 
      
 413 
     | 
    
         
            +
                  Dbox.sync(@alternate).should eql(:pull => { :created => [], :deleted => [], :updated => [], :failed => [] },
         
     | 
| 
      
 414 
     | 
    
         
            +
                                                   :push => { :created => [], :deleted => [], :updated => [], :failed => [] })
         
     | 
| 
      
 415 
     | 
    
         
            +
             
     | 
| 
      
 416 
     | 
    
         
            +
                  make_file "#{@local}/hello.txt"
         
     | 
| 
      
 417 
     | 
    
         
            +
                  make_file "#{@local}/goodbye.txt"
         
     | 
| 
      
 418 
     | 
    
         
            +
                  make_file "#{@local}/so_long.txt"
         
     | 
| 
      
 419 
     | 
    
         
            +
                  make_file "#{@alternate}/hello.txt"
         
     | 
| 
      
 420 
     | 
    
         
            +
                  make_file "#{@alternate}/farewell.txt"
         
     | 
| 
      
 421 
     | 
    
         
            +
                  Dbox.sync(@local).should eql(:pull => { :created => [], :deleted => [], :updated => [], :failed => [] },
         
     | 
| 
      
 422 
     | 
    
         
            +
                                               :push => { :created => ["goodbye.txt", "hello.txt", "so_long.txt"], :deleted => [], :updated => [], :failed => [] })
         
     | 
| 
      
 423 
     | 
    
         
            +
                  Dbox.sync(@alternate).should eql(:pull => { :created => ["goodbye.txt", "hello.txt", "so_long.txt"], :deleted => [], :updated => [""], :failed => [], :conflicts => [{ :renamed => "hello (1).txt", :original => "hello.txt" }] },
         
     | 
| 
      
 424 
     | 
    
         
            +
                                                   :push => { :created => ["farewell.txt", "hello (1).txt"], :deleted => [], :updated => [], :failed => [] })
         
     | 
| 
      
 425 
     | 
    
         
            +
             
     | 
| 
      
 426 
     | 
    
         
            +
                  make_file "#{@alternate}/farewell.txt"
         
     | 
| 
      
 427 
     | 
    
         
            +
                  make_file "#{@alternate}/goodbye.txt"
         
     | 
| 
      
 428 
     | 
    
         
            +
                  make_file "#{@alternate}/au_revoir.txt"
         
     | 
| 
      
 429 
     | 
    
         
            +
                  Dbox.sync(@alternate).should eql(:pull => { :created => [], :deleted => [], :updated => [""], :failed => [] },
         
     | 
| 
      
 430 
     | 
    
         
            +
                                                   :push => { :created => ["au_revoir.txt"], :deleted => [], :updated => ["farewell.txt", "goodbye.txt"], :failed => [] })
         
     | 
| 
      
 431 
     | 
    
         
            +
                  Dbox.sync(@local).should eql(:pull => { :created => ["au_revoir.txt", "farewell.txt", "hello (1).txt"], :deleted => [], :updated => ["", "goodbye.txt"], :failed => [] },
         
     | 
| 
      
 432 
     | 
    
         
            +
                                               :push => { :created => [], :deleted => [], :updated => [], :failed => [] })
         
     | 
| 
      
 433 
     | 
    
         
            +
                end
         
     | 
| 
       233 
434 
     | 
    
         
             
              end
         
     | 
| 
       234 
435 
     | 
    
         | 
| 
       235 
436 
     | 
    
         
             
              describe "#move" do
         
     | 
    
        data/spec/spec_helper.rb
    CHANGED
    
    | 
         @@ -36,8 +36,8 @@ def log 
     | 
|
| 
       36 
36 
     | 
    
         
             
              LOGGER
         
     | 
| 
       37 
37 
     | 
    
         
             
            end
         
     | 
| 
       38 
38 
     | 
    
         | 
| 
       39 
     | 
    
         
            -
            def make_file(filepath)
         
     | 
| 
       40 
     | 
    
         
            -
               
     | 
| 
      
 39 
     | 
    
         
            +
            def make_file(filepath, size_in_kb=1)
         
     | 
| 
      
 40 
     | 
    
         
            +
              `dd if=/dev/urandom of="#{filepath.gsub('"','\"')}" bs=1024 count=#{size_in_kb} 1>/dev/null 2>/dev/null`
         
     | 
| 
       41 
41 
     | 
    
         
             
            end
         
     | 
| 
       42 
42 
     | 
    
         | 
| 
       43 
43 
     | 
    
         
             
            RSpec::Matchers.define :exist do
         
     | 
| 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            1.1 (2011-10-17)
         
     | 
| 
      
 2 
     | 
    
         
            +
            * Various bug fixes found during beta period
         
     | 
| 
      
 3 
     | 
    
         
            +
            * Improved documentation
         
     | 
| 
      
 4 
     | 
    
         
            +
            * Improved module structure
         
     | 
| 
      
 5 
     | 
    
         
            +
            * Removed dependency on the oauth module, using plaintext authentication over https
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            1.0 (2011-8-16)
         
     | 
| 
      
 8 
     | 
    
         
            +
            * Backwards compatibility broken
         
     | 
| 
      
 9 
     | 
    
         
            +
               - Changed interface
         
     | 
| 
      
 10 
     | 
    
         
            +
               - Change 'sandbox' references to 'app_folder'
         
     | 
| 
      
 11 
     | 
    
         
            +
            * Updated SDK to Dropbox API Version 1, supporting all calls
         
     | 
| 
      
 12 
     | 
    
         
            +
               - Added 'rev' parameter to metadata and get_file
         
     | 
| 
      
 13 
     | 
    
         
            +
               - Added 'parent_rev' parameter to put_file
         
     | 
| 
      
 14 
     | 
    
         
            +
               - Added search, share, media, revisions, and restore
         
     | 
| 
      
 15 
     | 
    
         
            +
               - put_file uses /files_put instead of multipart POST
         
     | 
| 
      
 16 
     | 
    
         
            +
               - Removed methods for calls that were removed from v1 of the REST API
         
     | 
| 
      
 17 
     | 
    
         
            +
            * Changed return format for calls
         
     | 
| 
      
 18 
     | 
    
         
            +
               - On error (non-200 response), an exception is raised
         
     | 
| 
      
 19 
     | 
    
         
            +
               - On success, the JSON is parsed and a Hash is returned
         
     | 
| 
      
 20 
     | 
    
         
            +
            * Updated examples
         
     | 
| 
      
 21 
     | 
    
         
            +
               - Improved CLI example
         
     | 
| 
      
 22 
     | 
    
         
            +
               - Added a Ruby on Rails 3 controller example
         
     | 
| 
      
 23 
     | 
    
         
            +
               - Added a web based file browser/uploader that uses Sinatra
         
     | 
| 
      
 24 
     | 
    
         
            +
            * put_file no longer takes a "name" arugment, only takes a full path
         
     | 
| 
      
 25 
     | 
    
         
            +
            * Removed reliance on config files
         
     | 
| 
      
 26 
     | 
    
         
            +
            * Assorted bugfixes and improvements
         
     | 
| 
      
 27 
     | 
    
         
            +
            * All calls are now made over SSL
         
     | 
| 
      
 28 
     | 
    
         
            +
            * Fully documented code for RDoc generation
         
     | 
| 
      
 29 
     | 
    
         
            +
            * Added a CHANGELOG
         
     | 
| 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Getting started with the Dropbox Ruby SDK:
         
     | 
| 
      
 2 
     | 
    
         
            +
            1.  Install json and oauth ruby gems with:
         
     | 
| 
      
 3 
     | 
    
         
            +
                gem install json oauth
         
     | 
| 
      
 4 
     | 
    
         
            +
            2.  Edit cli_example.rb to to include your APP_KEY and APP_SECRET
         
     | 
| 
      
 5 
     | 
    
         
            +
            3.  Try running the example app: 'ruby clie_example.rb'.
         
     | 
| 
      
 6 
     | 
    
         
            +
            4.  See dropbox_controller.rb for an example Ruby on Rails controller.  It needs an APP_KEY and APP_SECRET set too.
         
     | 
| 
      
 7 
     | 
    
         
            +
            5.  Check out the dropbox website for reference and help! http://dropbox.com/developers_beta
         
     | 
| 
         @@ -0,0 +1,197 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require './lib/dropbox_sdk'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'pp'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            ####
         
     | 
| 
      
 5 
     | 
    
         
            +
            # An example app using the Dropbox API Ruby Client
         
     | 
| 
      
 6 
     | 
    
         
            +
            #   This ruby script sets up a basic command line interface (CLI)
         
     | 
| 
      
 7 
     | 
    
         
            +
            #   that prompts a user to authenticate on the web, then
         
     | 
| 
      
 8 
     | 
    
         
            +
            #   allows them to type commands to manipulate their dropbox.
         
     | 
| 
      
 9 
     | 
    
         
            +
            ####
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            # You must use your Dropbox App key and secret to use the API.
         
     | 
| 
      
 12 
     | 
    
         
            +
            # Find this at https://www.dropbox.com/developers
         
     | 
| 
      
 13 
     | 
    
         
            +
            APP_KEY = ''
         
     | 
| 
      
 14 
     | 
    
         
            +
            APP_SECRET = ''
         
     | 
| 
      
 15 
     | 
    
         
            +
            ACCESS_TYPE = :app_folder #The two valid values here are :app_folder and :dropbox
         
     | 
| 
      
 16 
     | 
    
         
            +
                                      #The default is :app_folder, but your application might be
         
     | 
| 
      
 17 
     | 
    
         
            +
                                      #set to have full :dropbox access.  Check your app at
         
     | 
| 
      
 18 
     | 
    
         
            +
                                      #https://www.dropbox.com/developers/apps
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            class DropboxCLI
         
     | 
| 
      
 21 
     | 
    
         
            +
                LOGIN_REQUIRED = %w{put get cp mv rm ls mkdir info logout search}
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def initialize
         
     | 
| 
      
 24 
     | 
    
         
            +
                    if APP_KEY == '' or APP_SECRET == ''
         
     | 
| 
      
 25 
     | 
    
         
            +
                        puts "You must set your APP_KEY and APP_SECRET in cli_example.rb!"
         
     | 
| 
      
 26 
     | 
    
         
            +
                        puts "Find this in your apps page at https://www.dropbox.com/developers/"
         
     | 
| 
      
 27 
     | 
    
         
            +
                        exit
         
     | 
| 
      
 28 
     | 
    
         
            +
                    end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                    @session = DropboxSession.new(APP_KEY, APP_SECRET)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    @client = nil
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                def login
         
     | 
| 
      
 35 
     | 
    
         
            +
                    ########
         
     | 
| 
      
 36 
     | 
    
         
            +
                    # Instead of going to a authorize URL, you can set a access token key and secret
         
     | 
| 
      
 37 
     | 
    
         
            +
                    # from a previous session
         
     | 
| 
      
 38 
     | 
    
         
            +
                    ########
         
     | 
| 
      
 39 
     | 
    
         
            +
                    # @session.set_access_token('key', 'secret')
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                    if @session.authorized?
         
     | 
| 
      
 42 
     | 
    
         
            +
                       puts "already logged in!"
         
     | 
| 
      
 43 
     | 
    
         
            +
                    else
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                        # grab the request token for session
         
     | 
| 
      
 46 
     | 
    
         
            +
                        @session.get_request_token
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                        authorize_url = @session.get_authorize_url
         
     | 
| 
      
 49 
     | 
    
         
            +
                        puts "Got a request token.  Your request token key is #{@session.request_token.key} and your token secret is #{@session.request_token.secret}"
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                        # make the user log in and authorize this token
         
     | 
| 
      
 52 
     | 
    
         
            +
                        puts "AUTHORIZING", authorize_url, "Please visit that web page and hit 'Allow', then hit Enter here."
         
     | 
| 
      
 53 
     | 
    
         
            +
                        gets
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                        # get the access token from the server. Its then stored in the session.
         
     | 
| 
      
 56 
     | 
    
         
            +
                        @session.get_access_token
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                    end
         
     | 
| 
      
 59 
     | 
    
         
            +
                    puts "You are logged in.  Your access token key is #{@session.access_token.key} your secret is #{@session.access_token.secret}"
         
     | 
| 
      
 60 
     | 
    
         
            +
                    @client = DropboxClient.new(@session, ACCESS_TYPE)
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                def command_loop
         
     | 
| 
      
 64 
     | 
    
         
            +
                    puts "Enter a command or 'help' or 'exit'"
         
     | 
| 
      
 65 
     | 
    
         
            +
                    command_line = ''
         
     | 
| 
      
 66 
     | 
    
         
            +
                    while command_line.strip != 'exit'
         
     | 
| 
      
 67 
     | 
    
         
            +
                        begin
         
     | 
| 
      
 68 
     | 
    
         
            +
                            execute_dropbox_command(command_line)
         
     | 
| 
      
 69 
     | 
    
         
            +
                        rescue RuntimeError => e
         
     | 
| 
      
 70 
     | 
    
         
            +
                            puts "Command Line Error! #{e.class}: #{e}"
         
     | 
| 
      
 71 
     | 
    
         
            +
                            puts e.backtrace
         
     | 
| 
      
 72 
     | 
    
         
            +
                        end
         
     | 
| 
      
 73 
     | 
    
         
            +
                        print '> '
         
     | 
| 
      
 74 
     | 
    
         
            +
                        command_line = gets.strip
         
     | 
| 
      
 75 
     | 
    
         
            +
                    end
         
     | 
| 
      
 76 
     | 
    
         
            +
                    puts 'goodbye'
         
     | 
| 
      
 77 
     | 
    
         
            +
                    exit(0)
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                def execute_dropbox_command(cmd_line)
         
     | 
| 
      
 81 
     | 
    
         
            +
                    command = cmd_line.split
         
     | 
| 
      
 82 
     | 
    
         
            +
                    method = command.first
         
     | 
| 
      
 83 
     | 
    
         
            +
                    if LOGIN_REQUIRED.include? method
         
     | 
| 
      
 84 
     | 
    
         
            +
                        if @client
         
     | 
| 
      
 85 
     | 
    
         
            +
                            send(method.to_sym, command)
         
     | 
| 
      
 86 
     | 
    
         
            +
                        else
         
     | 
| 
      
 87 
     | 
    
         
            +
                            puts 'must be logged in; type \'login\' to get started.'
         
     | 
| 
      
 88 
     | 
    
         
            +
                        end
         
     | 
| 
      
 89 
     | 
    
         
            +
                    elsif ['login', 'help'].include? method
         
     | 
| 
      
 90 
     | 
    
         
            +
                        send(method.to_sym)
         
     | 
| 
      
 91 
     | 
    
         
            +
                    else
         
     | 
| 
      
 92 
     | 
    
         
            +
                        if command.first && !command.first.strip.empty?
         
     | 
| 
      
 93 
     | 
    
         
            +
                            puts 'invalid command. type \'help\' to see commands.'
         
     | 
| 
      
 94 
     | 
    
         
            +
                        end
         
     | 
| 
      
 95 
     | 
    
         
            +
                    end
         
     | 
| 
      
 96 
     | 
    
         
            +
                end
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                def logout(command)
         
     | 
| 
      
 99 
     | 
    
         
            +
                    @session.clear_access_token
         
     | 
| 
      
 100 
     | 
    
         
            +
                    puts "You are logged out."
         
     | 
| 
      
 101 
     | 
    
         
            +
                    @client = nil
         
     | 
| 
      
 102 
     | 
    
         
            +
                end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                def put(command)
         
     | 
| 
      
 105 
     | 
    
         
            +
                    fname = command[1]
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                    #If the user didn't specifiy the file name, just use the name of the file on disk
         
     | 
| 
      
 108 
     | 
    
         
            +
                    if command[2]
         
     | 
| 
      
 109 
     | 
    
         
            +
                        new_name = command[2]
         
     | 
| 
      
 110 
     | 
    
         
            +
                    else
         
     | 
| 
      
 111 
     | 
    
         
            +
                        new_name = File.basename(fname)
         
     | 
| 
      
 112 
     | 
    
         
            +
                    end
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                    if fname && !fname.empty? && File.exists?(fname) && (File.ftype(fname) == 'file') && File.stat(fname).readable?
         
     | 
| 
      
 115 
     | 
    
         
            +
                        #This is where we call the the Dropbox Client
         
     | 
| 
      
 116 
     | 
    
         
            +
                        pp @client.put_file(new_name, open(fname))
         
     | 
| 
      
 117 
     | 
    
         
            +
                    else
         
     | 
| 
      
 118 
     | 
    
         
            +
                        puts "couldn't find the file #{ fname }"
         
     | 
| 
      
 119 
     | 
    
         
            +
                    end
         
     | 
| 
      
 120 
     | 
    
         
            +
                end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                def get(command)
         
     | 
| 
      
 123 
     | 
    
         
            +
                    dest = command[2]
         
     | 
| 
      
 124 
     | 
    
         
            +
                    if !command[1] || command[1].empty?
         
     | 
| 
      
 125 
     | 
    
         
            +
                        puts "please specify item to get"
         
     | 
| 
      
 126 
     | 
    
         
            +
                    elsif !dest || dest.empty?
         
     | 
| 
      
 127 
     | 
    
         
            +
                        puts "please specify full local path to dest, i.e. the file to write to"
         
     | 
| 
      
 128 
     | 
    
         
            +
                    elsif File.exists?(dest)
         
     | 
| 
      
 129 
     | 
    
         
            +
                        puts "error: File #{dest} already exists."
         
     | 
| 
      
 130 
     | 
    
         
            +
                    else
         
     | 
| 
      
 131 
     | 
    
         
            +
                        src = clean_up(command[1])
         
     | 
| 
      
 132 
     | 
    
         
            +
                        out = @client.get_file('/' + src)
         
     | 
| 
      
 133 
     | 
    
         
            +
                        open(dest, 'w'){|f| f.puts out }
         
     | 
| 
      
 134 
     | 
    
         
            +
                        puts "wrote file #{dest}."
         
     | 
| 
      
 135 
     | 
    
         
            +
                    end
         
     | 
| 
      
 136 
     | 
    
         
            +
                end
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                def mkdir(command)
         
     | 
| 
      
 139 
     | 
    
         
            +
                    pp @client.file_create_folder(command[1])
         
     | 
| 
      
 140 
     | 
    
         
            +
                end
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                def thumbnail(command)
         
     | 
| 
      
 143 
     | 
    
         
            +
                    command[2] ||= 'small'
         
     | 
| 
      
 144 
     | 
    
         
            +
                    pp @client.thumbnail(command[1], command[2])
         
     | 
| 
      
 145 
     | 
    
         
            +
                end
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
                def cp(command)
         
     | 
| 
      
 148 
     | 
    
         
            +
                    src = clean_up(command[1])
         
     | 
| 
      
 149 
     | 
    
         
            +
                    dest = clean_up(command[2])
         
     | 
| 
      
 150 
     | 
    
         
            +
                    pp @client.file_copy(src, dest)
         
     | 
| 
      
 151 
     | 
    
         
            +
                end
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
                def mv(command)
         
     | 
| 
      
 154 
     | 
    
         
            +
                    src = clean_up(command[1])
         
     | 
| 
      
 155 
     | 
    
         
            +
                    dest = clean_up(command[2])
         
     | 
| 
      
 156 
     | 
    
         
            +
                    pp @client.file_move(src, dest)
         
     | 
| 
      
 157 
     | 
    
         
            +
                end
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                def rm(command)
         
     | 
| 
      
 160 
     | 
    
         
            +
                    pp @client.file_delete(clean_up(command[1]))
         
     | 
| 
      
 161 
     | 
    
         
            +
                end
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
                def search(command)
         
     | 
| 
      
 164 
     | 
    
         
            +
                    resp = @client.search('/',clean_up(command[1]))
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                    for item in resp
         
     | 
| 
      
 167 
     | 
    
         
            +
                        puts item['path']
         
     | 
| 
      
 168 
     | 
    
         
            +
                    end
         
     | 
| 
      
 169 
     | 
    
         
            +
                end
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                def info(command)
         
     | 
| 
      
 172 
     | 
    
         
            +
                    pp @client.account_info
         
     | 
| 
      
 173 
     | 
    
         
            +
                end
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
                def ls(command)
         
     | 
| 
      
 176 
     | 
    
         
            +
                    command[1] = '/' + clean_up(command[1] || '')
         
     | 
| 
      
 177 
     | 
    
         
            +
                    resp = @client.metadata(command[1])
         
     | 
| 
      
 178 
     | 
    
         
            +
             
     | 
| 
      
 179 
     | 
    
         
            +
                    if resp['contents'].length > 0
         
     | 
| 
      
 180 
     | 
    
         
            +
                        for item in resp['contents']
         
     | 
| 
      
 181 
     | 
    
         
            +
                            puts item['path']
         
     | 
| 
      
 182 
     | 
    
         
            +
                        end
         
     | 
| 
      
 183 
     | 
    
         
            +
                    end
         
     | 
| 
      
 184 
     | 
    
         
            +
                end
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
                def help
         
     | 
| 
      
 187 
     | 
    
         
            +
                    puts "commands are: login #{LOGIN_REQUIRED.join(' ')} help exit"
         
     | 
| 
      
 188 
     | 
    
         
            +
                end
         
     | 
| 
      
 189 
     | 
    
         
            +
             
     | 
| 
      
 190 
     | 
    
         
            +
                def clean_up(str)
         
     | 
| 
      
 191 
     | 
    
         
            +
                    return str.gsub(/^\/+/, '') if str
         
     | 
| 
      
 192 
     | 
    
         
            +
                    str
         
     | 
| 
      
 193 
     | 
    
         
            +
                end
         
     | 
| 
      
 194 
     | 
    
         
            +
            end
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
            cli = DropboxCLI.new
         
     | 
| 
      
 197 
     | 
    
         
            +
            cli.command_loop
         
     |