From a12ad9c4ea2dd61293dcbfe87916924ccb1c37e0 Mon Sep 17 00:00:00 2001 From: Chris Anderson Date: Sun, 15 Jun 2008 11:43:05 -0700 Subject: [PATCH] restart etc --- lib/couch_rest.rb | 5 ++ script/couchcontrol | 169 ++++++++++++++++++++++++++++++++++++++++ script/couchdir | 13 +++- spec/couch_rest_spec.rb | 6 ++ 4 files changed, 192 insertions(+), 1 deletion(-) create mode 100755 script/couchcontrol diff --git a/lib/couch_rest.rb b/lib/couch_rest.rb index b6652dc..93fe28c 100644 --- a/lib/couch_rest.rb +++ b/lib/couch_rest.rb @@ -25,6 +25,11 @@ class CouchRest CouchRest.get "#{@uri}/" end + # restart the couchdb instance + def restart! + CouchRest.post "#{@uri}/_restart" + end + # create a database def create_db name CouchRest.put "#{@uri}/#{name}" diff --git a/script/couchcontrol b/script/couchcontrol new file mode 100755 index 0000000..de8c3e2 --- /dev/null +++ b/script/couchcontrol @@ -0,0 +1,169 @@ +#!/usr/bin/env ruby + +commands = %w{pull push} + +command = ARGV[0] + +if !commands.include?(command) + puts <<-USAGE +Usage: script/views (pull|push) my-database-name +For help on pull and push run script/views (pull|push) without a database name. +USAGE + exit +end + +if ARGV.length == 1 + case command + when "pull" + puts <<-PULL +script/views pull my-database-name [id prefix (default is _design)] + +I will automagically create a "views" directory in your current working directory if none exists. +Then I copy the design documents and views into a directory structure like: + +./views/my-design-doc/view-name-map.js +./views/my-design-doc/view-name-reduce.js + +If your view names don't end in "map" or "reduce" I'll add those suffixes as a pull. On push I'll put them in new locations corresponding to these new names (overwriting the old design documents). I'm opinionated, but if these conventions don't work for you, the source code is right here. + + PULL + when "push" + puts <<-PUSH +script/views push my-database-name + +I'll push all the files in your views directory to the specified database. Because CouchDB caches the results of view calculation by function content, there's no performance penalty for duplicating the map function twice, which I'll do if you have a reduce function. This makes it possible to browse the results of just the map, which can be useful for both queries and debugging. + +./views/my-design-doc/view-name-map.js +./views/my-design-doc/view-name-reduce.js + + Pushed to => + + http://localhost:5984/my-database-name/_design/my-design-doc + { + "views" : { + "view-name-map" : { + "map" : "### contents of view-name-map.js ###" + }, + "view-name-reduce" : { + "map" : "### contents of view-name-map.js ###", + "reduce" : "### contents of view-name-reduce.js ###" + }, + } + } +PUSH + end + exit +end + +dbname = ARGV[1] +dirname = ARGV[2] || "views" +prefix = ARGV[3] || "_design" + +puts "Running #{command} into #{prefix} on #{dbname} from directory #{dirname}." + +# __END__ + +require File.expand_path(File.dirname(__FILE__)) + '/../couchrest' +require File.expand_path(File.dirname(__FILE__)) + '/../vendor/jsmin/lib/jsmin' +require 'fileutils' + +module Enumerable + def group_by + inject({}) do |groups, element| + (groups[yield(element)] ||= []) << element + groups + end + end if RUBY_VERSION < '1.9' +end + +# connect to couchdb +cr = CouchRest.new("http://localhost:5984") +db = cr.database(dbname) + +def readjs(file, libs=nil) + st = open(file).read + st.sub!(/\/\/include-lib/,libs) if libs + JSMin.minify(st) +end + +def readfile(file, libs=nil) + st = open(file).read +end + + +case command +when "push" # files to views + views = {} + viewfiles = Dir.glob(File.join(dirname,"**","*.*")) # todo support non-js views + libfiles = viewfiles.select{|f|/lib\.\w+/.match(f)} + libs = open(libfiles[0]).read if libfiles[0] + all = (viewfiles-libfiles).collect do |file| + fileparts = file.split('/') + filename = fileparts[0] + puts filename + controller = fileparts[1] + action = fileparts[2].sub(/\.\w+/,'') + path = file + [controller,action,path] + end + # puts all.inspect +# end +# __END__ + + controllers = all.group_by{|f|f[0]} + controllers.each do |cntrl,parts| + # puts "replace _design/#{design}? (enter to proceed, 'n' to skip)" + # rep = $stdin.gets.chomp + # next if rep == 'n' + actions = {} + parts.group_by{|p|p[1]}.each do |action,fs| + fs.each do |f| + # actions[action] ||= {} + actions[action] = readfile(f.last) + end + end + # save them to the db + control = db.get("#{prefix}/#{cntrl}") rescue nil + if (control && control['actions'] == actions) + puts "no change to #{prefix}/#{cntrl}. skipping..." + else + puts "replacing #{prefix}/#{cntrl}" + db.delete(control) rescue nil + db.save({ + "_id" => "#{prefix}/#{cntrl}", + :actions => actions + }) + end + end + +when "pull" # views to files + ds = db.documents(:startkey => '#{prefix}/', :endkey => '#{prefix}/ZZZZZZZZZ') + ds['rows'].collect{|r|r['id']}.each do |id| + puts directory = id.split('/').last + FileUtils.mkdir_p(File.join("views",directory)) + views = db.get(id)['views'] + + vgroups = views.keys.group_by{|k|k.sub(/\-(map|reduce)$/,'')} + vgroups.each do|g,vs| + mapname = vs.find {|v|views[v]["map"]} + if mapname + # save map + mapfunc = views[mapname]["map"] + mapfile = File.join(dirname,directory,"#{g}-map.js") # todo support non-js views + File.open(mapfile,'w') do |f| + f.write mapfunc + end + end + + reducename = vs.find {|v|views[v]["reduce"]} + if reducename + # save reduce + reducefunc = views[reducename]["reduce"] + reducefile = File.join(dirname,directory,"#{g}-reduce.js") # todo support non-js views + File.open(reducefile,'w') do |f| + f.write reducefunc + end + end + end + end +end diff --git a/script/couchdir b/script/couchdir index 77be4c1..d50e490 100755 --- a/script/couchdir +++ b/script/couchdir @@ -1,7 +1,15 @@ #!/usr/bin/env ruby +unless ARGV.length >= 2 + puts "usage: couchdir path/to/directory db-name" + exit +end + dirname = ARGV[0].sub(/\/$/,'') dbname = ARGV[1] + + + puts "Shoving #{dirname} into #{dbname}." require File.expand_path(File.dirname(__FILE__)) + '/../couchrest' @@ -34,6 +42,8 @@ puts attachments.keys.inspect doc = @db.get(dirname) rescue nil +# puts "get: #{doc.inspect}" + if doc doc["_attachments"] = attachments else @@ -43,5 +53,6 @@ else } end - +# puts "saving: #{doc.inspect}" @db.save(doc) +puts "saved" \ No newline at end of file diff --git a/spec/couch_rest_spec.rb b/spec/couch_rest_spec.rb index 97e06d1..8833051 100644 --- a/spec/couch_rest_spec.rb +++ b/spec/couch_rest_spec.rb @@ -40,6 +40,12 @@ describe CouchRest do @cr.info.class.should == Hash end end + + describe "description" do + it "should restart" do + @cr.restart! + end + end describe "initializing a database" do it "should return a db" do