psql-cm 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/History.md CHANGED
@@ -1,3 +1,15 @@
1
+ # 0.0.6 - 2012-04-20
2
+
3
+ Merged {base.sql, cm.sql} into a single sql-path/{database}/{schema}.sql file.
4
+
5
+ Base is now the first change in the {schema}.sql CM file.
6
+
7
+ Made Configuration Managment table name configurable via cli using -c|--cm-table=
8
+
9
+ Made debug message output more structured and clear.
10
+
11
+ Created {drop,create,setup,dump,restore} rake tasks for qa-ing.
12
+
1
13
  # 0.0.5 - 2012-04-18
2
14
 
3
15
  Added git repository feature to sql-path for dump action, a commit per run of
data/README.md CHANGED
@@ -15,8 +15,7 @@ combined with complimentary process and adherence.
15
15
 
16
16
  ## What psql-cm is not
17
17
 
18
- psql-cm is not intended on being a solution whatsoever for data backup.
19
-
18
+ psql-cm is not intended on being a solution for data backup.
20
19
  For backup of data instead use the
21
20
  [pg\_dump](http://www.postgresql.org/docs/current/static/app-pgdump.html)
22
21
  command line utility for backing up data in addition to a
@@ -61,12 +60,16 @@ database cluster.
61
60
 
62
61
  $ psql-cm --databases psqlcm_test --uri "postgres://127.0.0.1:5432" restore
63
62
 
63
+ ## Change
64
+
65
+ TODO: Document how to commit a change.
66
+
64
67
  ## Command line parameters
65
68
 
66
69
  --databases argument may take multiple database targets, to do this pass them
67
70
  in ',' separated format, no spaces. Specifically the format is,
68
71
 
69
- $ psql-cm --databases psqlcm_test,psqlcm_test2,... ...
72
+ $ psql-cm --databases adatabase,anotherdatabase,... ...
70
73
 
71
74
  --uri has the format,
72
75
 
@@ -119,16 +122,57 @@ Next we'll dump the schema to sql/ within our working directory
119
122
 
120
123
  $ psql-cm --databases psqlcm_test --uri "postgres://127.0.0.1:5432" dump
121
124
 
122
- At this point we have the base schema for the psqlcm\_test database recorded and
123
- we can test to see that this is true by droping the database and then running
124
- the psql-cm restore action.
125
+ At this point we have the base schema for the psqlcm\_test database recorded to
126
+ the filesystem. You can see the filesystem structure and contents with
127
+ a find command on \*nix:
128
+
129
+ $ find sql/psqlcm_test
130
+ sql/psqlcm_test
131
+ sql/psqlcm_test/public
132
+ sql/psqlcm_test/public/base.sql
133
+ sql/psqlcm_test/public/cm.sql
134
+ sql/psqlcm_test/schema_one
135
+ sql/psqlcm_test/schema_one/base.sql
136
+ sql/psqlcm_test/schema_one/cm.sql
137
+ sql/psqlcm_test/schema_two
138
+ sql/psqlcm_test/schema_two/base.sql
139
+ sql/psqlcm_test/schema_two/cm.sql
140
+
141
+ We can now do a restore restore by droping the database and then running the
142
+ psql-cm restore action.
125
143
 
126
144
  $ dropdb psqlcm_test
127
145
  $ psql-cm --databases psqlcm_test --uri "postgres://127.0.0.1:5432" restore
128
146
 
129
- Once again use yoru favorite client tool and verify that the schema is inded
130
- what it was after setup was run.
147
+ Once again useing a client tool and verify that the schema is inded what it was
148
+ after setup was run.
149
+
150
+ NOTE: one caveat is that psql-cm does not handle ROLEs and USERs so these will
151
+ have to be accounted for after doing a restore.
152
+
153
+ ## Debugging
154
+
155
+ Debugging output can be enabled by exporting DEBUG=true in the environment
156
+ before calling the psql-cm command:
157
+
158
+ $ export debug=true
159
+
160
+ ## Development
161
+
162
+ To play around inside of a running psql-cm Ruby environment use the console:
163
+
164
+ rake console # Development console, builds installs then runs console
165
+
166
+ The 'Walkthrough' from above is encoded as rake tasks, each step can be
167
+ seen including all debugging output by running:
131
168
 
132
- Note that one caveat is that psql-cm does not handle ROLEs and USERs so these
133
- will have to be accounted for after doing a restore.
169
+ rake clean # Remove the sql/ directory in the current working directory.
170
+ rake create # Create the development database psqlcm_development, including two schemas.
171
+ rake debug # Enable debugging using environment variable DEBUG
172
+ rake drop # Drop the development database psqlcm_development
173
+ rake dump # Remove sql/ from CWD and then run the psql-cm dump action on psqlcm_development
174
+ rake build # Build the psql-cm gem.
175
+ rake install # Build then install the psql-cm gem.
176
+ rake restore # Create psqlcm_development, run psql-cm actions {setup, dump, restore} in order.
177
+ rake setup # Create psqlcm_development and run psql-cm setup on it
134
178
 
data/lib/psql-cm/base.rb CHANGED
@@ -20,12 +20,13 @@ module PSQLCM
20
20
  def databases
21
21
  @databases = db.
22
22
  exec("SELECT datname as name FROM pg_database WHERE datname !~ 'template*|postgres';").
23
- map {|row| row["name"]}
23
+ map {|row| row['name']}
24
24
 
25
- unless config.databases.to_a.empty? # filter out databases not specified.
25
+ if config.databases.to_a.empty?
26
+ halt! 'A list of databases must be given:\n --databases={database_one}[,{database_two}[,...]]'
27
+ else # filter out databases not specified.
26
28
  @databases.select!{ |name| config.databases.include?(name) }
27
29
  end
28
-
29
30
  debug "databases> #{@databases}"
30
31
  @databases
31
32
  end
@@ -33,7 +34,10 @@ module PSQLCM
33
34
  def schemas(name = 'postgres')
34
35
  @schemas = db(name).
35
36
  exec("SELECT nspname AS name FROM pg_namespace WHERE nspname !~ '^pg_.*|information_schema';").
36
- map{|row| row["name"]}
37
+ map{|row| row['name']}
38
+
39
+ # Filter out schemas not specified, if specified.
40
+ @schemas.select!{ |name| config.schemas.include?(name) } if config.schemas
37
41
  debug "schemas> #{@schemas}"
38
42
  @schemas
39
43
  end
@@ -42,149 +46,88 @@ module PSQLCM
42
46
  return @tree if @tree
43
47
  @tree = {}
44
48
  databases.each do |dbname|
45
- @tree[dbname] = {}
46
- schemas(dbname).each do |schema|
47
- @tree[dbname][schema] = ['base.sql', 'cm.sql']
48
- end
49
+ @tree[dbname] = schemas(dbname)
49
50
  end
50
- debug "tree> tree: #{@tree}"
51
+ debug "tree> #{@tree}"
51
52
  @tree
52
53
  end
53
54
 
54
- def dump!
55
- unless config.sql_path
56
- $stdout.puts "Warning: --sql-path was not set, defaulting to $PWD/sql."
57
- config.sql_path = "#{ENV["PWD"]}/sql"
55
+ def run!(action = config.action)
56
+ case action
57
+ when 'console'
58
+ require 'psql-cm/cli'
59
+ ::PSQLCM::Console.run!
60
+ when 'dump'
61
+ dump!
62
+ when 'restore'
63
+ restore!
64
+ when 'setup'
65
+ setup!
66
+ when 'submit'
67
+ submit!
68
+ else
69
+ halt! "An action must be given! {setup, dump, restore}" if action.nil?
70
+ halt! "Action '#{action}' is not handled."
58
71
  end
72
+ end
59
73
 
60
- debug "dump> sql_path: #{config.sql_path}"
61
- FileUtils.mkdir(config.sql_path) unless File.directory?(config.sql_path)
62
- Dir.chdir(config.sql_path) do
63
- tree.each_pair do |database, schema_hash|
64
- debug "dump> database: #{database}"
65
-
66
- File.directory?(File.join(config.sql_path,database)) or
67
- FileUtils.mkdir(File.join(config.sql_path,database))
68
-
69
- schema_hash.each_pair do |schema, files|
70
- debug "dump> schema: #{schema}"
71
- File.directory?(File.join(config.sql_path,database,schema)) or
72
- FileUtils.mkdir(File.join(config.sql_path,database,schema))
73
-
74
- base_file = File.join(config.sql_path,database,schema,'base.sql')
75
- cm_file = File.join(config.sql_path,database,schema,'cm.sql')
76
-
77
- FileUtils.touch(base_file)
78
- FileUtils.touch(cm_file)
74
+ def sh(command)
75
+ debug "$ #{command}"
76
+ %x[#{command} 2>&1 | awk '! /NOTICE/']
77
+ end
79
78
 
80
- command = "pg_dump #{db(database).psql_args} --schema-only --no-owner --schema=#{schema} "
81
- if File.size(base_file) > 0
82
- command += "--file=#{cm_file} --table=psql_cm "
83
- else
84
- command += "--file=#{base_file} --exclude-table=psql_cm "
85
- end
86
- command += "#{database}"
87
- sh 'dump', command
88
- end
89
- end
79
+ def uri
80
+ return config.uri unless config.uri.to_s.empty?
81
+ $stdout.puts "NOTICE: uri is not set, defaulting to postgres://127.0.0.1:5432 (format: postgres://{user}:{password}@{host}:{port}/{database}\nwhere user, password, port and database are optional)"
82
+ config.uri = "postgres://127.0.0.1:5432"
83
+ end
90
84
 
91
- sh 'git', "git init; git add ." unless File.exists?('.git') && File.directory?('.git')
85
+ private
92
86
 
93
- sh 'git', "git commit -a -m 'PostgreSQL Change Management (psql-cm).\nDatabases: #{databases}\nTree: #{tree}'"
94
- end
95
- end # def dump!
96
-
97
- def setup!
98
- # Create psql_cm tables for each schema on the target db.
99
- debug "setup> Setting up pg_psql_cm table in each target schema."
100
- tree.each_pair do |database, schema_hash|
101
- schema_hash.keys.each do |schema|
102
- sql = <<-SQL
103
- SET search_path = #{schema}, public;
104
- CREATE TABLE IF NOT EXISTS #{schema}.pg_psql_cm
105
- (
106
- id bigserial NOT NULL PRIMARY KEY ,
107
- is_base boolean NOT NULL,
108
- created_at timestamp with time zone DEFAULT now(),
109
- implementer text NOT NULL,
110
- content text NOT NULL
111
- );
112
- SQL
113
- debug "setup:#{database}:#{schema}> sql\n#{sql}"
114
- db(database).exec sql
115
- end
87
+ def ensure_database_exists(database)
88
+ begin
89
+ db('postgres').exec("CREATE DATABASE #{database};")
90
+ debug "create> #{database}"
91
+ rescue => error
92
+ raise error unless error.message =~ /already exists/
116
93
  end
117
94
  end
118
95
 
119
- def restore!
120
- unless config.sql_path
121
- $stdout.puts "Warning: --sql-path was not set, defaulting to $PWD/sql."
122
- config.sql_path = "#{ENV["PWD"]}/sql"
123
- end
124
-
125
- debug "restore> sql_path: #{config.sql_path}"
126
- File.directory?(config.sql_path) or
127
- halt! "Cannot restore from a path that does not exist: #{config.sql_path}"
128
-
129
- Dir.chdir(config.sql_path) do
130
-
131
- Dir['*'].each do |database|
132
- next unless File.directory? database
133
-
134
- Dir.chdir(database) do
135
- sh "restore", "createdb #{db(database).psql_args} #{database}"
136
-
137
- debug "restore:#{database}>"
138
- Dir['*'].each do |schema|
139
- next unless File.directory? schema
140
-
141
- base_file = File.join(config.sql_path,database,schema,'base.sql')
142
- cm_file = File.join(config.sql_path,database,schema,'cm.sql')
143
-
144
- debug "restore:#{database}:#{schema}> #{base_file}"
145
- sh 'restore', "psql #{db(database).psql_args} #{database} < #{base_file}"
146
-
147
- next if File.size(cm_file) == 0
148
-
149
- debug "restore:#{database}:#{schema}> #{cm_file}"
150
- sh 'restore', "psql #{db(database).psql_args} #{database} < #{cm_file}"
151
- end
152
- end
153
- end
96
+ def ensure_schema_exists(database,schema)
97
+ begin
98
+ db(database).exec("CREATE SCHEMA #{schema};")
99
+ debug "create> #{database}.#{schema}"
100
+ rescue => error
101
+ raise error unless error.message =~ /already exists/
154
102
  end
155
- end # def restore!
156
-
157
- def change!
158
- puts "TODO: allow change string and/or file to be specified and add to the
159
- specified database scema control table"
160
103
  end
161
104
 
162
- def run!(action = config.action, parent_id = config.parent_id)
163
- case action
164
- when "console"
165
- ::PSQLCM.debug "Starting Console"
166
- require 'psql-cm/cli'
167
- ::PSQLCM::Console.run!
168
- when "dump"
169
- dump!
170
- when "restore"
171
- restore!
172
- when "setup"
173
- setup!
174
- when "change"
175
- change!
176
- else
177
- halt! "Action '#{action}' is not handled."
178
- end
105
+ def ensure_cm_table_exists(database,schema)
106
+ sql = <<-SQL
107
+ SET search_path = #{schema};
108
+ SET client_min_messages = warning;
109
+ CREATE TABLE IF NOT EXISTS #{schema}.#{config.cm_table}
110
+ (
111
+ id bigserial NOT NULL PRIMARY KEY ,
112
+ is_base boolean NOT NULL,
113
+ created_at timestamp with time zone DEFAULT now(),
114
+ implementer text NOT NULL,
115
+ content text NOT NULL
116
+ );
117
+ SQL
118
+ debug "create> #{database}.#{schema}.#{config.cm_table}"
119
+ db(database).exec(sql)
179
120
  end
180
121
 
181
- def sh(tag, command)
182
- debug "sh:#{tag}> #{command}"
183
- %x[#{command}]
122
+ def sql_path
123
+ return config.sql_path unless config.sql_path.to_s.empty?
124
+ $stdout.puts "NOTICE: sql_path is not set, defaulting to #{ENV["PWD"]}/sql"
125
+ config.sql_path = "#{ENV["PWD"]}/sql"
184
126
  end
185
127
 
186
128
  end # class << self
187
129
  end
188
130
 
189
131
  ::PSQLCM.config.debug = !!ENV['DEBUG']
132
+ ::PSQLCM.config.cm_table = 'pg_psql_cm' # Default --cm-table name.
190
133
 
data/lib/psql-cm/cli.rb CHANGED
@@ -6,36 +6,40 @@ module PSQLCM
6
6
  class << self
7
7
  def parse!(arguments)
8
8
  ::OptionParser.new do |options|
9
- options.banner = "Usage: psql-cm [options]"
10
- options.separator ""
11
- options.separator "Specific options:"
9
+ options.banner = 'Usage: psql-cm [options]'
10
+ options.separator ''
11
+ options.separator 'Specific options:'
12
12
 
13
- options.on("-s", "--sql-path PATH", "Path to dump SQL cm files into.") do |path|
13
+ options.on('-s', '--sql-path PATH', 'Path to dump SQL cm files into.') do |path|
14
14
  ::PSQLCM.config.sql_path = path
15
15
  end
16
16
 
17
- options.on("-a", "--databases NAMES", "A comma separated list of databases to cm.") do |names|
17
+ options.on('-a', '--databases=NAMES', 'A comma separated list of databases to cm.') do |names|
18
18
  ::PSQLCM.config.databases = names.split(',')
19
19
  end
20
20
 
21
- options.on("-u", "--uri URI", "Path to the sink database connection file.") do |uri|
21
+ options.on('-u', '--uri=URI', 'Path to the sink database connection file.') do |uri|
22
22
  ::PSQLCM.config.uri = uri
23
23
  end
24
24
 
25
- options.on("-D", "--[no-]debug", "Output debugging information.") do |debug|
25
+ options.on('-D', '--[no-]debug', 'Output debugging information.') do |debug|
26
26
  ::PSQLCM.config.debug = debug.nil? ? false : true
27
27
  end
28
28
 
29
- options.on("-v", "--[no-]verbose", "Output verbosley.") do |verbose|
29
+ options.on('-v', '--[no-]verbose', 'Output verbosley.') do |verbose|
30
30
  ::PSQLCM.config.verbose = verbose
31
31
  end
32
32
 
33
- options.on_tail("-h", "--help", "Print help and exit.") do
33
+ options.on('-c', '--cm-table=TABLE') do |cm_table|
34
+ ::PSQLCM.config.cm_table = cm_table
35
+ end
36
+
37
+ options.on_tail('-h', '--help', 'Print help and exit.') do
34
38
  puts options
35
39
  exit 0
36
40
  end
37
41
 
38
- options.on_tail("--version", "Print version and exit.") do
42
+ options.on_tail('--version', 'Print version and exit.') do
39
43
  require 'psql-cm/version'
40
44
  puts ::PSQLCM::Version
41
45
  exit 0
@@ -16,7 +16,7 @@ module PSQLCM
16
16
 
17
17
  def db
18
18
  unless @config[:dbname] == 'postgres'
19
- ::PSQLCM.sh 'createdb', "createdb #{psql_args} #{@config[:dbname]}"
19
+ ::PSQLCM.sh "createdb #{psql_args} #{@config[:dbname]}"
20
20
  end
21
21
 
22
22
  @db || connect!
@@ -69,9 +69,12 @@ module PSQLCM
69
69
  @db[name] = Connection.new(:dbname => name)
70
70
  end
71
71
 
72
- # "postgres://{user}:{password}@{host}:{port}/{database}"
73
72
  def configure!
74
- uri = URI.parse(::PSQLCM.config.uri)
73
+ begin
74
+ uri = URI.parse(::PSQLCM.uri)
75
+ rescue => error
76
+ halt! "PostgreSQL URI was incorrectly specified, format is:\n --uri=postgres://{user}:{password}@{host}:{port}/{database}\nwhere user, password, port and database are optional."
77
+ end
75
78
 
76
79
  query = uri.query.to_s.split('&')
77
80
 
@@ -0,0 +1,30 @@
1
+ module PSQLCM
2
+ class << self
3
+ def dump!
4
+ debug "dump> sql_path: #{sql_path}"
5
+ FileUtils.mkdir(sql_path) unless File.directory?(sql_path)
6
+ Dir.chdir(sql_path) do
7
+ debug "tree> #{tree}"
8
+ tree.each_pair do |database, database_schemas|
9
+ debug "dump> database: #{database}"
10
+ FileUtils.mkdir_p(File.join(sql_path,database))
11
+ database_schemas.each do |schema|
12
+ debug "dump> schema: #{schema}"
13
+ FileUtils.mkdir_p(File.join(sql_path,database))
14
+
15
+ cm_file = File.join(sql_path,database,"#{schema}.sql")
16
+
17
+ sh %W[ pg_dump #{db(database).psql_args}
18
+ --no-owner --schema=#{schema} --file=#{cm_file} --table=#{config.cm_table}
19
+ #{database} ].join(' ')
20
+ end
21
+ end
22
+
23
+ sh "git init; git add ." unless File.exists?('.git') && File.directory?('.git')
24
+
25
+ sh "git commit -a -m 'PostgreSQL Change Management (psql-cm).\nDatabases: #{databases.join(', ')}\nTree: #{tree}'"
26
+ end
27
+ end # def dump!
28
+
29
+ end
30
+ end
@@ -0,0 +1,49 @@
1
+ module PSQLCM
2
+ class << self
3
+ def restore!
4
+ File.directory?(sql_path) or
5
+ halt! "Cannot restore from sql-path (#{sql_path}), it does not exist!"
6
+
7
+ Dir.chdir(sql_path) do
8
+
9
+ Dir['*'].each do |database|
10
+ next unless File.directory? database
11
+
12
+ Dir.chdir(database) do
13
+ ensure_database_exists(database)
14
+
15
+ debug "restore> #{database}"
16
+ Dir['*.sql'].each do |cm_file|
17
+ next if File.size(cm_file) == 0
18
+
19
+ schema = cm_file.sub(".sql",'')
20
+ ensure_schema_exists(database,schema)
21
+
22
+ debug "restore> #{database}:#{schema} < #{cm_file}"
23
+ sh "psql #{db(database).psql_args} #{database} < #{cm_file}"
24
+
25
+ ensure_cm_table_exists(database,schema)
26
+ row = db(database).exec("SELECT content from #{schema}.#{config.cm_table}
27
+ WHERE is_base IS true ORDER BY created_at
28
+ DESC LIMIT 1;")
29
+ Tempfile.open('base.sql') do |temp_file|
30
+ temp_file.write(row)
31
+ sh "psql #{db(database).psql_args} #{database} < #{temp_file.path}"
32
+ end
33
+
34
+ sql = "SELECT content from #{schema}.#{config.cm_table} where is_base IS false ORDER BY created_at ASC;"
35
+ db(database).exec(sql).each do |row|
36
+ debug "restoring cm row: #{row}"
37
+ Tempfile.open('base.sql') do |temp_file|
38
+ temp_file.write(row)
39
+ sh "psql #{db(database).psql_args} #{database} < #{temp_file.path}"
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end # def restore!
47
+
48
+ end
49
+ end
@@ -0,0 +1,27 @@
1
+ module PSQLCM
2
+ class << self
3
+ def setup!
4
+ tree.each_pair do |database, schemas|
5
+ ensure_database_exists(database)
6
+ schemas(database).each do |schema|
7
+ ensure_schema_exists(database,schema)
8
+ ensure_cm_table_exists(database,schema)
9
+
10
+ Tempfile.open('base.sql') do |temp_file|
11
+ sh " pg_dump #{db(database).psql_args} --schema-only --no-owner --schema=#{schema} --file=#{temp_file.path} #{database}"
12
+
13
+ contents = %x{cat #{temp_file.path}}
14
+ implementer = %Q|#{%x[git config user.name].strip} <#{%x[git config user.email].strip}>|
15
+ db(database).exec(
16
+ "INSERT INTO #{schema}.#{config.cm_table} (is_base, implementer, content) VALUES (true, $1, $2);",
17
+ [implementer, contents]
18
+ )
19
+ end
20
+
21
+ end
22
+ end
23
+
24
+ dump!
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,14 @@
1
+ module PSQLCM
2
+ class << self
3
+ def submit!
4
+ puts "TODO: allow change string and/or file to be specified and add to the
5
+ specified database scema control table"
6
+
7
+ # TOOD: get values x,y,z
8
+ sql = "INSERT INTO #{schema}.#{config.cm_table} (is_base,implementer,content) VALUES (x,y,z)"
9
+ debug "submit:#{database}:#{schema}> sql\n#{sql}"
10
+ db(database).exec sql
11
+ end # def submit!
12
+ end
13
+ end
14
+
@@ -1,4 +1,4 @@
1
1
  module PSQLCM
2
- Version = '0.0.5'
2
+ Version = '0.0.6'
3
3
  end
4
4
 
data/lib/psql-cm.rb CHANGED
@@ -3,7 +3,12 @@ require 'fileutils'
3
3
  require 'ostruct'
4
4
  require 'uri'
5
5
  require 'delegate'
6
+ require 'tempfile'
6
7
 
7
8
  require_relative 'psql-cm/base'
8
9
  require_relative 'psql-cm/database'
10
+ require_relative 'psql-cm/setup'
11
+ require_relative 'psql-cm/dump'
12
+ require_relative 'psql-cm/restore'
13
+ require_relative 'psql-cm/submit'
9
14
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: psql-cm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-19 00:00:00.000000000 Z
12
+ date: 2012-04-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: pg
@@ -39,6 +39,10 @@ files:
39
39
  - lib/psql-cm/base.rb
40
40
  - lib/psql-cm/cli.rb
41
41
  - lib/psql-cm/database.rb
42
+ - lib/psql-cm/dump.rb
43
+ - lib/psql-cm/restore.rb
44
+ - lib/psql-cm/setup.rb
45
+ - lib/psql-cm/submit.rb
42
46
  - lib/psql-cm/version.rb
43
47
  - lib/psql-cm.rb
44
48
  - LICENCE