Module: Prick::SubCommand
- Extended by:
- Timer
- Defined in:
- lib/prick.rb,
lib/subcommand/prick-fox.rb,
lib/subcommand/prick-drop.rb,
lib/subcommand/prick-init.rb,
lib/subcommand/prick-make.rb,
lib/subcommand/prick-build.rb,
lib/subcommand/prick-setup.rb,
lib/subcommand/prick-create.rb,
lib/subcommand/prick-migrate.rb,
lib/subcommand/prick-release.rb,
lib/subcommand/prick-teardown.rb
Class Method Summary collapse
- .build(database, username, schema, builddir: "schema", force: false, timer: nil, dump: nil) ⇒ Object
- .create_migration(username, from_version, force: false, file: nil) ⇒ Object
- .drop_all(database) ⇒ Object
- .drop_database(database) ⇒ Object
- .drop_users(database) ⇒ Object
- .fox(database, username, files) ⇒ Object
- .init(dir, name, title, database, username) ⇒ Object
- .make(database, username, schema, timer: nil, dump: nil) ⇒ Object
- .mesg(*msgs) ⇒ Object
-
.migrate(database, username, file: nil) ⇒ Object
def self.migrate(database, username, file) TODO.
- .release(kind) ⇒ Object
- .setup(database, username) ⇒ Object
- .teardown(database, username) ⇒ Object
- .verb(*msgs) ⇒ Object
Methods included from Timer
file, file=, new, off!, off?, on!, on?, scale, scale=, time, time, unit, unit=
Class Method Details
.build(database, username, schema, builddir: "schema", force: false, timer: nil, dump: nil) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/subcommand/prick-build.rb', line 6 def self.build(database, username, schema, builddir: "schema", force: false, timer: nil, dump: nil) Timer.on! if timer time "Prick::Command#build" do begin super_conn = PgConn.new # Used to create new databases (doesn't make a # difference right now as the mikras user is # still a superuser) conn = nil builder = nil time "Load build object" do if super_conn.rdbms.exist? database conn = PgConn.new(database, username) exist = true else super_conn.rdbms.create database, owner: username conn = PgConn.new(database, username) exist = false end builder = Prick::Build::Builder.new(conn, builddir) if exist if force # Drop all schemas but re-creates the public schema super_conn.rdbms.empty!(database) else # Find schemas to refresh. This includes all schemas in the # database refresh_schemas = conn.schema.list # Find existing keep-schemas (but exclude target schema) keep_schemas = builder.keep_schemas.select { |s| conn.schema.exist?(s) && (schema.nil? || schema != s) } # Remove keep-schemas from list of schemas refresh_schemas -= keep_schemas # Eliminate keep schemas from build pool builder.pool.delete_schema(keep_schemas) # Drop refresh schemes refresh_schemas.each { |schema| conn.schema.drop(schema, cascade: true) } # Re-create public schema conn.schema.create("public", authorization: "postgres") conn.exec "grant usage, create on schema public to public" end end # Delete schemas after target scheme if present builder.pool.delete_schema(builder.pool.after_schema(schema)) if schema end case dump when :nodes; builder.nodes.reject { |node| node.is_a?(Build::BuildNode) }.map &:dump when :allnodes; builder.nodes.map &:dump when :batches; builder.dump when nil; else raise Prick::Error, "Illegal dump type: #{dump.inspect}" end && exit time "Execute build object" do builder.execute conn end rescue Prick::Error => ex $stderr.puts ex. exit 1 rescue ::Command::Error => ex $stderr.puts ex. exit 1 ensure super_conn&.terminate conn&.terminate end end end |
.create_migration(username, from_version, force: false, file: nil) ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/subcommand/prick-create.rb', line 4 def self.create_migration(username, from_version, force: false, file: nil) constrain from_version, PrickVersion Git.clean? or raise "Won't migrate: Repository is dirty" Git.synchronized? or raise "Won't migrate: Repository is not synchronized" from_version != PrickVersion.zero or raise Prick::Error, "Can't migrate from release 0.0.0" to_version = Prick.state.version migration_dir = "#{MIGRATION_DIR}/#{from_version}" migration_exist = File.directory? migration_dir force || file || !migration_exist or raise Prick::Fail, "Migration #{from_version} exists" $quiet = true if file if file && migration_exist File.open(file, "w") { |file| for diff_file in DIFF_FILES file.write File.read("#{migration_dir}/#{diff_file}") end } else from_version != to_version or raise Prick::Fail, "Can't migrate to same release" from_version < to_version or raise Prick::Fail, "Can't migrate backwards (why not?)" diff = nil if force || !migration_exist from_db = "#{Prick.state.name}-#{from_version}" to_db = "#{Prick.state.name}-#{to_version}" mesg "Migrating from #{from_version} to #{to_version}" begin origin = Git.origin # Local repos are supported to ease testing if File.directory?(origin) origin = File.(origin) end diff = Dir.mktmpdir { |tmpdir| Dir.chdir(tmpdir) { mesg " Building #{from_db}" Git.clone(origin, from_version, branch: from_version) Dir.chdir(from_version.to_s) { build(from_db, username, nil) } } mesg " Building #{to_db}" build(to_db, username, nil) mesg " Creating diff" Diff.new(from_db, to_db) } !diff.same? or raise Prick::Fail, "No changes" ensure drop_all(from_db) drop_all(to_db) end end diff.write(file) if file end if file File.open(file, "a") { |f| f.puts "-- UPDATE VERSION" f.puts File.readlines(SCHEMA_VERSION_PATH).grep_v(/^--/) } else FileUtils.rm_rf migration_dir if force FileUtils.mkdir_p migration_dir Command.command "cp -a #{SHARE_PATH}/migrate/migration/. #{migration_dir}" Dir.chdir(migration_dir) { diff.write(*DIFF_FILES, mark: true) } end end |
.drop_all(database) ⇒ Object
17 18 19 20 21 22 23 |
# File 'lib/subcommand/prick-drop.rb', line 17 def self.drop_all(database) PgConn.new("postgres") { |conn| users = conn.role.list(database: database) PgConn.new(database) { |db| db.role.drop(users, cascade: true) } conn.rdbms.drop database } end |
.drop_database(database) ⇒ Object
13 14 15 |
# File 'lib/subcommand/prick-drop.rb', line 13 def self.drop_database(database) PgConn.new("postgres") { |conn| conn.rdbms.drop database } end |
.drop_users(database) ⇒ Object
6 7 8 9 10 11 |
# File 'lib/subcommand/prick-drop.rb', line 6 def self.drop_users(database) PgConn.new("postgres") { |conn| users = conn.role.list(database: database) conn.role.drop(users, cascade: true) } end |
.fox(database, username, files) ⇒ Object
6 7 8 |
# File 'lib/subcommand/prick-fox.rb', line 6 def self.fox(database, username, files) Command.command "fox --state=#{FOX_STATE_PATH} --exec #{database} #{files.join(" ")}" end |
.init(dir, name, title, database, username) ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/subcommand/prick-init.rb', line 4 def self.init(dir, name, title, database, username) if dir !File.exist?(dir) or raise Prick::Error, "Directory #{dir} exists" FileUtils.mkdir_p(dir) Dir.chdir(dir) else dir = "." end name ||= File.basename(Dir.getwd) title ||= name database ||= name username ||= name Command.command %( git init . cp -a #{SHARE_PATH}/init/. . git add . git commit -am "Initial import" ), fail: false Command.status == 0 or raise Prick::Fail, "Init script failed" state = State.new state.name = name state.title = title state.prick_version = PrickVersion.new VERSION state.version = PrickVersion.new("0.0.0") state.environment = :development state.database = database state.username = username state.save Command.command %( set -e git commit -am "Release 0.0.0" git tag v0.0.0 ), fail: false Command.status == 0 or raise Prick::Fail, "Init script failed" [dir, state] end |
.make(database, username, schema, timer: nil, dump: nil) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/subcommand/prick-make.rb', line 6 def self.make(database, username, schema, timer: nil, dump: nil) Timer.on! if timer time "Prick::Command#build" do begin super_conn = PgConn.new conn = nil builder = nil built_at = EPOCH clean = false create_schemas = [] time "Load build object" do if super_conn.rdbms.exist? database conn = PgConn.new(database, username) if conn.schema.exist_table? "prick", "versions" && !conn.empty?("prick.versions") built_at = conn.value("select built_at from prick.versions") end else super_conn.rdbms.create database, owner: username conn = PgConn.new(database, username) clean = true end builder = Prick::Build::Builder.new(conn, "schema", clean) if schema builder.pool.after_schema(schema).each { |schema| conn.schema.drop(schema, cascade: true) builder.pool.delete_schema(schema) } end touched_nodes = builder.nodes.select { |node| File.mtime(node.path) > built_at } touched_phases = touched_nodes.map(&:phase).uniq.compact touched_kinds = touched_nodes.map(&:kind).uniq.compact touched_schema = touched_nodes.first&.schema missing_schema = builder.schemas.find { |schema| !conn.schema.exist?(schema) } build_schema = builder.schemas.find { |schema| [touched_schema, missing_schema].include? schema } if build_schema.nil? puts "#{database} is up to date" exit end if touched_phases.include?(:decl) || touched_phases.empty? create_schemas = [build_schema] + builder.pool.after_schema(build_schema) create_schemas.each { |schema| conn.schema.drop(schema, cascade: true) } builder.pool.delete_schema(builder.pool.before_schema(build_schema), exclude: [:seed]) elsif touched_phases.include?(:init) || touched_phases.include?(:term) builder.pool.clear(:decl, :seed) elsif touched_phases.include?(:seed) builder.pool.clear(:init, :decl, :term) end builder.group end case dump when :nodes; builder.nodes.reject { |node| node.is_a?(Build::BuildNode) }.map &:dump when :allnodes; builder.nodes.map &:dump when :batches; builder.dump when nil; else raise Prick::Error, "Illegal dump type: #{dump.inspect}" end exit if dump time "Execute build object" do builder.execute(conn, create_schemas: create_schemas) end rescue Prick::Build::Error => ex $stderr.puts ex. exit 1 rescue Command::Error => ex $stderr.puts ex. exit 1 end end end |
.mesg(*msgs) ⇒ Object
27 |
# File 'lib/prick.rb', line 27 def self.mesg(*msgs) puts msgs.join(" ") if !$quiet end |
.migrate(database, username, file: nil) ⇒ Object
def self.migrate(database, username, file) TODO
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/subcommand/prick-migrate.rb', line 5 def self.migrate(database, username, file: nil) PgConn.new(database, username) { |conn| conn.schema.exist_relation? "prick", "versions" or raise Prick::Fail, "Can't read version from database" from_version = PrickVersion.new(conn.value "select version from prick.versions") or raise Prick::Fail, "Illegal version in table prick.versions" if file conn.transaction { conn.exec File.read(file) } else to_version = Prick.state.version from_version != to_version or raise Prick::Fail, "Already up to date" from_version < to_version or raise Prick::Fail, "Can't migrate backwards" migration_dir = "#{MIGRATION_DIR}/#{from_version}" File.directory? migration_dir or raise Prick::Fail, "Can't migrate from #{from_version} to #{to_version}" puts "Migrating from #{from_version} to #{to_version}" builder = Prick::Build::Builder.new(conn, migration_dir) conn.transaction { builder.execute conn conn.exec File.read(SCHEMA_VERSION_PATH) } end } end |
.release(kind) ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/subcommand/prick-release.rb', line 4 def self.release(kind) constrain kind, :major, :minor, :patch Git.clean? or raise "Won't release: Repository is dirty" Git.synchronized? or raise "Won't release: Repository is not synchronized with origin" version = Prick.state.version.increment!(kind).to_s Prick.state.save Git.add(Prick.state.file) Git.add(Prick.state.schema_file) Git.commit "Release #{version}" Git.tag.create "v#{version}" Git.branch.create version Git.push puts version end |
.setup(database, username) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 |
# File 'lib/subcommand/prick-setup.rb', line 6 def self.setup(database, username) conn = PgConn.new("template1") # Connect to template1 because database might not exist if !conn.role.exist? username # FIXME Should not be created as superuser but we can't do that before we # have a super: option in build conn.role.create username, superuser: true, can_login: true, create_role: true end if !conn.rdbms.exist? database conn.rdbms.create database, owner: username end builder = Prick::Build::Builder.new(conn, "schema") # TODO Run builder setup scrips end |
.teardown(database, username) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 |
# File 'lib/subcommand/prick-teardown.rb', line 6 def self.teardown(database, username) conn = PgConn.new "postgres" # Superuser connection if conn.rdbms.exist? database conn.rdbms.drop database end if conn.role.exist? username conn.role.drop username, cascade: true end builder = Prick::Build::Builder.new(conn, "schema") # TODO Run builder teardown scrips end |
.verb(*msgs) ⇒ Object
28 |
# File 'lib/prick.rb', line 28 def self.verb(*msgs) puts msgs.join(" ") if $verbose && !$quiet end |