prick 0.4.0 → 0.9.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.
- checksums.yaml +4 -4
 - data/.gitignore +3 -0
 - data/TODO +7 -0
 - data/exe/prick +235 -163
 - data/lib/ext/fileutils.rb +7 -0
 - data/lib/prick.rb +7 -5
 - data/lib/prick/builder.rb +31 -8
 - data/lib/prick/cache.rb +34 -0
 - data/lib/prick/constants.rb +106 -54
 - data/lib/prick/database.rb +26 -20
 - data/lib/prick/diff.rb +103 -25
 - data/lib/prick/git.rb +31 -9
 - data/lib/prick/head.rb +183 -0
 - data/lib/prick/migration.rb +41 -181
 - data/lib/prick/program.rb +255 -0
 - data/lib/prick/project.rb +274 -0
 - data/lib/prick/rdbms.rb +3 -12
 - data/lib/prick/schema.rb +7 -11
 - data/lib/prick/state.rb +129 -74
 - data/lib/prick/version.rb +41 -28
 - data/prick.gemspec +3 -1
 - data/share/diff/diff.after-tables.sql +4 -0
 - data/share/diff/diff.before-tables.sql +4 -0
 - data/share/diff/diff.tables.sql +8 -0
 - data/share/migration/diff.tables.sql +8 -0
 - data/share/{release_migration → migration}/features.yml +0 -0
 - data/share/migration/migrate.sql +3 -0
 - data/share/{release_migration → migration}/migrate.yml +3 -0
 - data/share/migration/tables.sql +3 -0
 - data/share/{schemas → schema/schema}/build.yml +0 -0
 - data/share/{schemas → schema/schema}/prick/build.yml +0 -0
 - data/share/schema/schema/prick/data.sql +7 -0
 - data/share/{schemas → schema/schema}/prick/schema.sql +0 -0
 - data/share/{schemas → schema/schema}/prick/tables.sql +2 -2
 - data/share/{schemas → schema/schema}/public/.keep +0 -0
 - data/share/{schemas → schema/schema}/public/build.yml +0 -0
 - data/share/{schemas → schema/schema}/public/schema.sql +0 -0
 - data/test_refactor +34 -0
 - metadata +23 -21
 - data/file +0 -0
 - data/lib/prick/build.rb +0 -376
 - data/lib/prick/migra.rb +0 -22
 - data/share/feature_migration/diff.sql +0 -2
 - data/share/feature_migration/migrate.sql +0 -2
 - data/share/release_migration/diff.sql +0 -3
 - data/share/release_migration/migrate.sql +0 -5
 - data/share/schemas/prick/data.sql +0 -7
 
    
        data/lib/prick/program.rb
    CHANGED
    
    | 
         @@ -3,6 +3,261 @@ require "prick.rb" 
     | 
|
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            module Prick
         
     | 
| 
       5 
5 
     | 
    
         
             
              # Implements the command line commands
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Program
         
     | 
| 
      
 7 
     | 
    
         
            +
                # Lazy-constructed because Project can only be initialized when the
         
     | 
| 
      
 8 
     | 
    
         
            +
                # directory structure is present
         
     | 
| 
      
 9 
     | 
    
         
            +
                def project() @project ||= Project.load end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                attr_accessor :quiet
         
     | 
| 
      
 12 
     | 
    
         
            +
                attr_accessor :verbose
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def initialize(quiet: false, verbose: false)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @quiet = quiet
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @verbose = verbose
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                # Check if the git repository is clean. Raise an error if not
         
     | 
| 
      
 20 
     | 
    
         
            +
                def check_clean() 
         
     | 
| 
      
 21 
     | 
    
         
            +
                  Git.clean? or raise Error, "Repository is dirty - please commit your changes first" 
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                # Create project directory structure
         
     | 
| 
      
 25 
     | 
    
         
            +
                def init(name, user, directory)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  !Project.exist?(directory) or raise Error, "Directory #{directory} is already initialized"
         
     | 
| 
      
 27 
     | 
    
         
            +
                  Project.create(name, user, directory)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  if name != directory
         
     | 
| 
      
 29 
     | 
    
         
            +
                    mesg "Initialized project #{name} in #{directory}"
         
     | 
| 
      
 30 
     | 
    
         
            +
                  else
         
     | 
| 
      
 31 
     | 
    
         
            +
                    mesg "Initialized project #{name}"
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                def info
         
     | 
| 
      
 36 
     | 
    
         
            +
                  if project.tag?
         
     | 
| 
      
 37 
     | 
    
         
            +
                    puts "At v#{project.version} tag"
         
     | 
| 
      
 38 
     | 
    
         
            +
                  else
         
     | 
| 
      
 39 
     | 
    
         
            +
                    puts "On branch #{project.head.name}, #{project.version}"
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
                  puts "  Git is " + (Git.clean? ? "clean" : "dirty")
         
     | 
| 
      
 42 
     | 
    
         
            +
                  bv = project.head.version
         
     | 
| 
      
 43 
     | 
    
         
            +
                  dv = project.database.version
         
     | 
| 
      
 44 
     | 
    
         
            +
                  sv = project.head.schema.version
         
     | 
| 
      
 45 
     | 
    
         
            +
                  puts "  Database version: #{dv}" + (dv != bv ? " (mismatch)" : "")
         
     | 
| 
      
 46 
     | 
    
         
            +
                  puts "  Schema version  : #{sv}" + (sv != bv ? " (mismatch)" : "")
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                def list_releases(migrations: false, cancelled: false)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  raise NotYet
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                def list_migrations
         
     | 
| 
      
 54 
     | 
    
         
            +
                  raise NotYet
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                def list_upgrades(from = nil, to = nil)
         
     | 
| 
      
 58 
     | 
    
         
            +
                  raise NotYet
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                def list_cache
         
     | 
| 
      
 62 
     | 
    
         
            +
                  project.cache.list.each { |l| puts l }
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                def build(database, version, nocache)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  into_mesg = database && "into #{database}"
         
     | 
| 
      
 67 
     | 
    
         
            +
                  version_mesg = version ? "v#{version}" : "current schema"
         
     | 
| 
      
 68 
     | 
    
         
            +
                  version &&= Version.new(version)
         
     | 
| 
      
 69 
     | 
    
         
            +
                  version.nil? || Git.tag?(version) or raise Error, "Can't find tag v#{version}"
         
     | 
| 
      
 70 
     | 
    
         
            +
                  database = database ? Database.new(database, project.user) : project.database(version)
         
     | 
| 
      
 71 
     | 
    
         
            +
                  project.build(database, version: version)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  project.save(database) if version && !nocache
         
     | 
| 
      
 73 
     | 
    
         
            +
                  mesg "Built", version_mesg, into_mesg
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                def make(database, version, nocache)
         
     | 
| 
      
 77 
     | 
    
         
            +
                  version &&= Version.new(version)
         
     | 
| 
      
 78 
     | 
    
         
            +
                  version.nil? || Git.tag?(version) or raise Error, "Can't find tag v#{version}"
         
     | 
| 
      
 79 
     | 
    
         
            +
                  if !nocache && version && project.cache.exist?(version)
         
     | 
| 
      
 80 
     | 
    
         
            +
                    load(database, version)
         
     | 
| 
      
 81 
     | 
    
         
            +
                  else
         
     | 
| 
      
 82 
     | 
    
         
            +
                    build(database, version, nocache)
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                def make_clean(all)
         
     | 
| 
      
 87 
     | 
    
         
            +
                  project.cache.clean.each { |file| mesg "Removed cache file #{File.basename(file)}" }
         
     | 
| 
      
 88 
     | 
    
         
            +
                  drop(nil, all)
         
     | 
| 
      
 89 
     | 
    
         
            +
                end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                def load(database, file_or_version)
         
     | 
| 
      
 92 
     | 
    
         
            +
                  check_owned(database) if database
         
     | 
| 
      
 93 
     | 
    
         
            +
                  into_mesg = database && "into #{database}"
         
     | 
| 
      
 94 
     | 
    
         
            +
                  if version = Version.try(file_or_version)
         
     | 
| 
      
 95 
     | 
    
         
            +
                    database = database ? Database.new(database, project.user) : project.database(version)
         
     | 
| 
      
 96 
     | 
    
         
            +
                    project.load(database, version: version)
         
     | 
| 
      
 97 
     | 
    
         
            +
                    mesg "Loaded v#{version}", into_mesg, "from cache"
         
     | 
| 
      
 98 
     | 
    
         
            +
                  else file = file_or_version
         
     | 
| 
      
 99 
     | 
    
         
            +
                    project.load(database, file: file)
         
     | 
| 
      
 100 
     | 
    
         
            +
                    mesg "Loaded #{File.basename(file)}", into_mesg
         
     | 
| 
      
 101 
     | 
    
         
            +
                  end
         
     | 
| 
      
 102 
     | 
    
         
            +
                end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                def save(version, file)
         
     | 
| 
      
 105 
     | 
    
         
            +
                  database = project.database(version)
         
     | 
| 
      
 106 
     | 
    
         
            +
                  database.exist? or raise "Can't find database '#{database}'"
         
     | 
| 
      
 107 
     | 
    
         
            +
                  subj_mesg = file ? file : "cache"
         
     | 
| 
      
 108 
     | 
    
         
            +
                  project.save(database, file: file)
         
     | 
| 
      
 109 
     | 
    
         
            +
                  mesg "Saved #{database} to #{subj_mesg}"
         
     | 
| 
      
 110 
     | 
    
         
            +
                end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                def drop(database, all)
         
     | 
| 
      
 113 
     | 
    
         
            +
                  database.nil? || !all or raise Error, "Can't use --all when database is given"
         
     | 
| 
      
 114 
     | 
    
         
            +
                  if database
         
     | 
| 
      
 115 
     | 
    
         
            +
                    check_owned(database)
         
     | 
| 
      
 116 
     | 
    
         
            +
                    dbs = [database]
         
     | 
| 
      
 117 
     | 
    
         
            +
                  else
         
     | 
| 
      
 118 
     | 
    
         
            +
                    dbs = Rdbms.list_databases(Prick.database_re(project.name))
         
     | 
| 
      
 119 
     | 
    
         
            +
                    dbs << project.name if all && project.database.exist?
         
     | 
| 
      
 120 
     | 
    
         
            +
                  end
         
     | 
| 
      
 121 
     | 
    
         
            +
                  dbs += Rdbms.list_databases(Prick.tmp_databases_re(project.name)) # FIXME: Only used in dev
         
     | 
| 
      
 122 
     | 
    
         
            +
                  dbs.each { |db|
         
     | 
| 
      
 123 
     | 
    
         
            +
                    Rdbms.drop_database(db)
         
     | 
| 
      
 124 
     | 
    
         
            +
                    mesg "Dropped database #{db}"
         
     | 
| 
      
 125 
     | 
    
         
            +
                  }
         
     | 
| 
      
 126 
     | 
    
         
            +
                end
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                # `select` is a tri-state variable that can be :tables, :no_tables, or :all
         
     | 
| 
      
 129 
     | 
    
         
            +
                # (or any other value)
         
     | 
| 
      
 130 
     | 
    
         
            +
                def diff(from, to, mark, select)
         
     | 
| 
      
 131 
     | 
    
         
            +
                  diff = project.diff(from && Version.new(from), to && Version.new(to))
         
     | 
| 
      
 132 
     | 
    
         
            +
                  if !diff.same?
         
     | 
| 
      
 133 
     | 
    
         
            +
                    if select != :tables && !diff.before_table_changes.empty?
         
     | 
| 
      
 134 
     | 
    
         
            +
                      puts "-- BEFORE TABLE CHANGES" if mark
         
     | 
| 
      
 135 
     | 
    
         
            +
                      puts diff.before_table_changes
         
     | 
| 
      
 136 
     | 
    
         
            +
                    end
         
     | 
| 
      
 137 
     | 
    
         
            +
                    if select != :no_tables && !diff.table_changes.empty?
         
     | 
| 
      
 138 
     | 
    
         
            +
                      puts "-- TABLE CHANGES" if mark
         
     | 
| 
      
 139 
     | 
    
         
            +
                      puts diff.table_changes
         
     | 
| 
      
 140 
     | 
    
         
            +
                    end
         
     | 
| 
      
 141 
     | 
    
         
            +
                    if select != :tables && !diff.after_table_changes.empty?
         
     | 
| 
      
 142 
     | 
    
         
            +
                      puts "-- AFTER TABLE CHANGES" if mark
         
     | 
| 
      
 143 
     | 
    
         
            +
                      puts diff.after_table_changes
         
     | 
| 
      
 144 
     | 
    
         
            +
                    end
         
     | 
| 
      
 145 
     | 
    
         
            +
                  end
         
     | 
| 
      
 146 
     | 
    
         
            +
                end
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                def migrate
         
     | 
| 
      
 149 
     | 
    
         
            +
                  raise NotYet
         
     | 
| 
      
 150 
     | 
    
         
            +
                end
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                def prepare_release(fork)
         
     | 
| 
      
 153 
     | 
    
         
            +
                  project.prepare_release(fork)
         
     | 
| 
      
 154 
     | 
    
         
            +
                end
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
                def prepare_feature(name)
         
     | 
| 
      
 157 
     | 
    
         
            +
                  raise NotYet
         
     | 
| 
      
 158 
     | 
    
         
            +
                end
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
                def prepare_migration(from = nil)
         
     | 
| 
      
 161 
     | 
    
         
            +
                  raise NotYet
         
     | 
| 
      
 162 
     | 
    
         
            +
                end
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
      
 164 
     | 
    
         
            +
                def prepare_schema(name)
         
     | 
| 
      
 165 
     | 
    
         
            +
                  project.prepare_schema(name)
         
     | 
| 
      
 166 
     | 
    
         
            +
                end
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
                def prepare_diff(version = nil)
         
     | 
| 
      
 169 
     | 
    
         
            +
                  # Helpful check to ensure the user has built the current version
         
     | 
| 
      
 170 
     | 
    
         
            +
            #     Diff.same?(to_db, database) or 
         
     | 
| 
      
 171 
     | 
    
         
            +
            #         raise Error, "Schema and project database are not synchronized"
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
                  project.prepare_diff(version || project.version)
         
     | 
| 
      
 174 
     | 
    
         
            +
                  if FileUtils.compare_file(TABLES_DIFF_PATH, TABLES_DIFF_SHARE_PATH)
         
     | 
| 
      
 175 
     | 
    
         
            +
                    mesg "Created diff. No table changes found, no manual migration updates needed"
         
     | 
| 
      
 176 
     | 
    
         
            +
                  else
         
     | 
| 
      
 177 
     | 
    
         
            +
                    mesg "Created diff. Please inspect #{TABLES_DIFF_PATH} and incorporate the"
         
     | 
| 
      
 178 
     | 
    
         
            +
                    mesg "changes in #{MIGRATION_DIR}/migrate.sql"
         
     | 
| 
      
 179 
     | 
    
         
            +
                  end
         
     | 
| 
      
 180 
     | 
    
         
            +
                end
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
                def include(name)
         
     | 
| 
      
 183 
     | 
    
         
            +
                  raise NotYet
         
     | 
| 
      
 184 
     | 
    
         
            +
                end
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
                def check
         
     | 
| 
      
 187 
     | 
    
         
            +
                  version ||= 
         
     | 
| 
      
 188 
     | 
    
         
            +
                      if project.prerelease? || project.migration?
         
     | 
| 
      
 189 
     | 
    
         
            +
                        project.branch.base_version
         
     | 
| 
      
 190 
     | 
    
         
            +
                      else
         
     | 
| 
      
 191 
     | 
    
         
            +
                        project.branch.version
         
     | 
| 
      
 192 
     | 
    
         
            +
                      end
         
     | 
| 
      
 193 
     | 
    
         
            +
                  project.check_migration(version)
         
     | 
| 
      
 194 
     | 
    
         
            +
                end
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
                def create_release(version = nil)
         
     | 
| 
      
 197 
     | 
    
         
            +
                  if project.prerelease_branch?
         
     | 
| 
      
 198 
     | 
    
         
            +
                    raise NotYet
         
     | 
| 
      
 199 
     | 
    
         
            +
                  elsif project.release_branch?
         
     | 
| 
      
 200 
     | 
    
         
            +
                    project.create_release(Version.new(version))
         
     | 
| 
      
 201 
     | 
    
         
            +
                  else
         
     | 
| 
      
 202 
     | 
    
         
            +
                    raise Error, "You need to be on a release or pre-release branch to create a new release"
         
     | 
| 
      
 203 
     | 
    
         
            +
                  end
         
     | 
| 
      
 204 
     | 
    
         
            +
                  mesg "Created release v#{project.head.version}"
         
     | 
| 
      
 205 
     | 
    
         
            +
                end
         
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
      
 207 
     | 
    
         
            +
                def create_prerelease(version = nil)
         
     | 
| 
      
 208 
     | 
    
         
            +
                  raise NotYet
         
     | 
| 
      
 209 
     | 
    
         
            +
                end
         
     | 
| 
      
 210 
     | 
    
         
            +
             
     | 
| 
      
 211 
     | 
    
         
            +
                def create_feature(name)
         
     | 
| 
      
 212 
     | 
    
         
            +
                  raise NotYet
         
     | 
| 
      
 213 
     | 
    
         
            +
                end 
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
                def cancel(version)
         
     | 
| 
      
 216 
     | 
    
         
            +
                  raise NotYet
         
     | 
| 
      
 217 
     | 
    
         
            +
                end
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
      
 219 
     | 
    
         
            +
                def generate_schema
         
     | 
| 
      
 220 
     | 
    
         
            +
                  project.generate_schema
         
     | 
| 
      
 221 
     | 
    
         
            +
                end
         
     | 
| 
      
 222 
     | 
    
         
            +
             
     | 
| 
      
 223 
     | 
    
         
            +
                def generate_migration
         
     | 
| 
      
 224 
     | 
    
         
            +
                  project.generate_migration
         
     | 
| 
      
 225 
     | 
    
         
            +
                end
         
     | 
| 
      
 226 
     | 
    
         
            +
             
     | 
| 
      
 227 
     | 
    
         
            +
                def upgrade
         
     | 
| 
      
 228 
     | 
    
         
            +
                  raise NotYet
         
     | 
| 
      
 229 
     | 
    
         
            +
                end
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
      
 231 
     | 
    
         
            +
                # TODO: Create a Backup class and a Project#backup_store object
         
     | 
| 
      
 232 
     | 
    
         
            +
                def backup(file = nil) 
         
     | 
| 
      
 233 
     | 
    
         
            +
                  file = file || File.join(SPOOL_DIR, "#{project.name}-#{Time.now.utc.strftime("%Y%m%d-%H%M%S")}.sql.gz")
         
     | 
| 
      
 234 
     | 
    
         
            +
                  project.save(file: file) 
         
     | 
| 
      
 235 
     | 
    
         
            +
                  mesg "Backed-up database to #{file}"
         
     | 
| 
      
 236 
     | 
    
         
            +
                end
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
      
 238 
     | 
    
         
            +
                def restore(file_arg = nil)
         
     | 
| 
      
 239 
     | 
    
         
            +
                  file = file_arg || Dir.glob(File.join(SPOOL_DIR, "#{name}-*.sql.gz")).sort.last
         
     | 
| 
      
 240 
     | 
    
         
            +
                  File.exist?(file) or raise Error, "Can't find #{file_arg || "any backup file"}"
         
     | 
| 
      
 241 
     | 
    
         
            +
                  project.load(file: file)
         
     | 
| 
      
 242 
     | 
    
         
            +
                  mesg "Restored database from #{file}"
         
     | 
| 
      
 243 
     | 
    
         
            +
                end
         
     | 
| 
      
 244 
     | 
    
         
            +
             
     | 
| 
      
 245 
     | 
    
         
            +
              protected
         
     | 
| 
      
 246 
     | 
    
         
            +
                def check_owned(database)
         
     | 
| 
      
 247 
     | 
    
         
            +
                  database =~ ALL_DATABASES_RE or raise Error, "Not a prick database: #{database}"
         
     | 
| 
      
 248 
     | 
    
         
            +
                  project_name = $1
         
     | 
| 
      
 249 
     | 
    
         
            +
                  project_name == project.name or raise Error, "Database not owned by this prick project: #{database}"
         
     | 
| 
      
 250 
     | 
    
         
            +
                end
         
     | 
| 
      
 251 
     | 
    
         
            +
             
     | 
| 
      
 252 
     | 
    
         
            +
                def mesg(*args) puts args.compact.grep(/\S/).join(' ') if !quiet end
         
     | 
| 
      
 253 
     | 
    
         
            +
                def verb(*args) puts args.compact.grep(/\S/).join(' ') if verbose end
         
     | 
| 
      
 254 
     | 
    
         
            +
              end
         
     | 
| 
      
 255 
     | 
    
         
            +
            end
         
     | 
| 
      
 256 
     | 
    
         
            +
             
     | 
| 
      
 257 
     | 
    
         
            +
            __END__
         
     | 
| 
      
 258 
     | 
    
         
            +
             
     | 
| 
      
 259 
     | 
    
         
            +
             
     | 
| 
      
 260 
     | 
    
         
            +
            module Prick
         
     | 
| 
       6 
261 
     | 
    
         
             
              class Program
         
     | 
| 
       7 
262 
     | 
    
         
             
                def project() @project ||= Project.load end
         
     | 
| 
       8 
263 
     | 
    
         | 
    
        data/lib/prick/project.rb
    CHANGED
    
    | 
         @@ -2,6 +2,280 @@ require "prick/state.rb" 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require "tmpdir"
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
      
 5 
     | 
    
         
            +
            module Prick
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Project
         
     | 
| 
      
 7 
     | 
    
         
            +
                attr_reader :name
         
     | 
| 
      
 8 
     | 
    
         
            +
                attr_reader :user # Database user
         
     | 
| 
      
 9 
     | 
    
         
            +
                attr_reader :head # Current branch/tag
         
     | 
| 
      
 10 
     | 
    
         
            +
                attr_reader :schema
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                # Return the versioned database or the project database if `version` is nil
         
     | 
| 
      
 13 
     | 
    
         
            +
                def database(version = nil)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  version ? Database.new("#{name}-#{version}", user) : @database
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                attr_reader :cache
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                def initialize(name, user, head)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @name = name
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @user = user || ENV['USER']
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @head = head
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @schema = Schema.new
         
     | 
| 
      
 24 
     | 
    
         
            +
                  @database = Database.new(name, user)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @cache = Cache.new
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                forward_methods :version, :base_version, :@head
         
     | 
| 
      
 29 
     | 
    
         
            +
                forward_methods :clean?, :@head
         
     | 
| 
      
 30 
     | 
    
         
            +
                forward_methods :tag?, :release_tag?, :migration_tag?, :@head
         
     | 
| 
      
 31 
     | 
    
         
            +
                forward_methods :branch?, :release_branch?, :prerelease_branch?, :feature_branch?, :migration_branch?, :@head
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def self.exist?(directory) 
         
     | 
| 
      
 34 
     | 
    
         
            +
                  File.directory?(directory) && Dir.chdir(directory) { ProjectState.new.exist? } 
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                def self.create(name, user, directory)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  user ||= ENV['USER']
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  FileUtils.mkdir(directory) if directory != "."
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  Dir.chdir(directory) {
         
     | 
| 
      
 43 
     | 
    
         
            +
                    # Initialize git instance
         
     | 
| 
      
 44 
     | 
    
         
            +
                    Git.init
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                    # Create prick version file
         
     | 
| 
      
 47 
     | 
    
         
            +
                    PrickVersion.new.write(VERSION)
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                    # Create project state file
         
     | 
| 
      
 50 
     | 
    
         
            +
                    ProjectState.new(name: name, user: user).write
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                    # Directories
         
     | 
| 
      
 53 
     | 
    
         
            +
                    FileUtils.mkdir_p(DIRS)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    DIRS.each { |dir| FileUtils.touch("#{dir}/.keep") }
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                    # Copy default gitignore and schema files
         
     | 
| 
      
 57 
     | 
    
         
            +
                    Share.cp("gitignore", ".gitignore")
         
     | 
| 
      
 58 
     | 
    
         
            +
                    Share.cp("schema/schema", ".")
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                    # Add .prick-migration file
         
     | 
| 
      
 61 
     | 
    
         
            +
                    MigrationState.new(version: Version.zero).create
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                    # Add everything so far
         
     | 
| 
      
 64 
     | 
    
         
            +
                    Git.add(".")
         
     | 
| 
      
 65 
     | 
    
         
            +
                    Git.commit("Initial import")
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                    # Rename branch "master"/"main" to "0.0.0_initial"
         
     | 
| 
      
 68 
     | 
    
         
            +
                    from_branch = Git.branch?("master") ? "master" : "main"
         
     | 
| 
      
 69 
     | 
    
         
            +
                    Git.rename_branch(from_branch, "0.0.0_initial")
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                    # Create schema
         
     | 
| 
      
 72 
     | 
    
         
            +
                    schema = Schema.new
         
     | 
| 
      
 73 
     | 
    
         
            +
                    schema.version = Version.zero
         
     | 
| 
      
 74 
     | 
    
         
            +
                    Git.add schema.version_file
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                    # Create release
         
     | 
| 
      
 77 
     | 
    
         
            +
                    Git.commit "Created release v0.0.0"
         
     | 
| 
      
 78 
     | 
    
         
            +
                    Git.create_tag(Version.zero)
         
     | 
| 
      
 79 
     | 
    
         
            +
                    Git.checkout_tag(Version.zero)
         
     | 
| 
      
 80 
     | 
    
         
            +
                  }
         
     | 
| 
      
 81 
     | 
    
         
            +
                end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                # Initialize from disk
         
     | 
| 
      
 84 
     | 
    
         
            +
                #
         
     | 
| 
      
 85 
     | 
    
         
            +
                # TODO Handle migrations
         
     | 
| 
      
 86 
     | 
    
         
            +
                def self.load
         
     | 
| 
      
 87 
     | 
    
         
            +
                  if Git.detached?
         
     | 
| 
      
 88 
     | 
    
         
            +
                    name = "v#{Git.current_tag}"
         
     | 
| 
      
 89 
     | 
    
         
            +
                  else
         
     | 
| 
      
 90 
     | 
    
         
            +
                    name = Git.current_branch
         
     | 
| 
      
 91 
     | 
    
         
            +
                  end
         
     | 
| 
      
 92 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 93 
     | 
    
         
            +
                    branch = Head.load(name)
         
     | 
| 
      
 94 
     | 
    
         
            +
                  rescue Version::FormatError
         
     | 
| 
      
 95 
     | 
    
         
            +
                    raise Fail, "Illegal branch name: #{name}"
         
     | 
| 
      
 96 
     | 
    
         
            +
                  end
         
     | 
| 
      
 97 
     | 
    
         
            +
                  state = ProjectState.new.read
         
     | 
| 
      
 98 
     | 
    
         
            +
                  Project.new(state.name, state.user, branch)
         
     | 
| 
      
 99 
     | 
    
         
            +
                end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                def build(database = self.database, version: nil)
         
     | 
| 
      
 102 
     | 
    
         
            +
                  database.clean
         
     | 
| 
      
 103 
     | 
    
         
            +
                  if version
         
     | 
| 
      
 104 
     | 
    
         
            +
                    FileUtils.mkdir_p(TMP_DIR)
         
     | 
| 
      
 105 
     | 
    
         
            +
                    Dir.mktmpdir("clone-", TMP_DIR) { |dir|
         
     | 
| 
      
 106 
     | 
    
         
            +
                      Command.command "git clone . #{dir}"
         
     | 
| 
      
 107 
     | 
    
         
            +
                      Dir.chdir(dir) {
         
     | 
| 
      
 108 
     | 
    
         
            +
                        Git.checkout_tag(version)
         
     | 
| 
      
 109 
     | 
    
         
            +
                        project = Project.load
         
     | 
| 
      
 110 
     | 
    
         
            +
                        project.head.build(database)
         
     | 
| 
      
 111 
     | 
    
         
            +
                      }
         
     | 
| 
      
 112 
     | 
    
         
            +
                    }
         
     | 
| 
      
 113 
     | 
    
         
            +
                  else
         
     | 
| 
      
 114 
     | 
    
         
            +
                    head.build(database)
         
     | 
| 
      
 115 
     | 
    
         
            +
                  end
         
     | 
| 
      
 116 
     | 
    
         
            +
                  self
         
     | 
| 
      
 117 
     | 
    
         
            +
                end
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                def load(database = self.database, version: nil, file: nil)
         
     | 
| 
      
 120 
     | 
    
         
            +
                  version.nil? ^ file.nil? or raise Internal, "Need exactly one of :file and :version to be defined"
         
     | 
| 
      
 121 
     | 
    
         
            +
                  database.clean
         
     | 
| 
      
 122 
     | 
    
         
            +
                  if version
         
     | 
| 
      
 123 
     | 
    
         
            +
                    cache.exist?(version) or raise Internal, "Can't find cache file for database #{database}"
         
     | 
| 
      
 124 
     | 
    
         
            +
                    cache.load(database, version)
         
     | 
| 
      
 125 
     | 
    
         
            +
                  else
         
     | 
| 
      
 126 
     | 
    
         
            +
                    database.load(file)
         
     | 
| 
      
 127 
     | 
    
         
            +
                  end
         
     | 
| 
      
 128 
     | 
    
         
            +
                  self
         
     | 
| 
      
 129 
     | 
    
         
            +
                end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                def save(database = nil, file: nil)
         
     | 
| 
      
 132 
     | 
    
         
            +
                  !database.nil? || file or raise Internal, "Need a database when saving to file"
         
     | 
| 
      
 133 
     | 
    
         
            +
                  database ||= self.database
         
     | 
| 
      
 134 
     | 
    
         
            +
                  if file
         
     | 
| 
      
 135 
     | 
    
         
            +
                    database.save(file)
         
     | 
| 
      
 136 
     | 
    
         
            +
                  else
         
     | 
| 
      
 137 
     | 
    
         
            +
                    cache.save(database)
         
     | 
| 
      
 138 
     | 
    
         
            +
                  end
         
     | 
| 
      
 139 
     | 
    
         
            +
                  self
         
     | 
| 
      
 140 
     | 
    
         
            +
                end
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                # Create a schema diff between two database versions. to_version defaults to the
         
     | 
| 
      
 143 
     | 
    
         
            +
                # current version. Returns the Diff object
         
     | 
| 
      
 144 
     | 
    
         
            +
                def diff(from_version, to_version)
         
     | 
| 
      
 145 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 146 
     | 
    
         
            +
                    from_db = Database.new("#{name}-base", user)
         
     | 
| 
      
 147 
     | 
    
         
            +
                    to_db = Database.new("#{name}-next", user)
         
     | 
| 
      
 148 
     | 
    
         
            +
                    from_version ||= version
         
     | 
| 
      
 149 
     | 
    
         
            +
                    build(from_db, version: from_version)
         
     | 
| 
      
 150 
     | 
    
         
            +
                    build(to_db, version: to_version)
         
     | 
| 
      
 151 
     | 
    
         
            +
                    Diff.new(from_db, to_db)
         
     | 
| 
      
 152 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 153 
     | 
    
         
            +
                    from_db&.drop
         
     | 
| 
      
 154 
     | 
    
         
            +
                    to_db&.drop
         
     | 
| 
      
 155 
     | 
    
         
            +
                  end
         
     | 
| 
      
 156 
     | 
    
         
            +
                end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                def prepare_release(fork = nil)
         
     | 
| 
      
 159 
     | 
    
         
            +
                  check_clean(:release_tag)
         
     | 
| 
      
 160 
     | 
    
         
            +
                  @head = ReleaseBranch.new(fork, version).create
         
     | 
| 
      
 161 
     | 
    
         
            +
                  submit "Prepared new release based on v#{version}", true
         
     | 
| 
      
 162 
     | 
    
         
            +
                  self
         
     | 
| 
      
 163 
     | 
    
         
            +
                end
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
                def prepare_schema(name, commit: true)
         
     | 
| 
      
 166 
     | 
    
         
            +
                  path = File.join(SCHEMA_DIR, name)
         
     | 
| 
      
 167 
     | 
    
         
            +
                  FileUtils.mkdir_p(path)
         
     | 
| 
      
 168 
     | 
    
         
            +
                  Git.add Share.cp("schema/schema.sql", path, clobber: false, templates: { 'SCHEMA' => name })
         
     | 
| 
      
 169 
     | 
    
         
            +
                  Git.add Share.cp("schema/build.yml", path, clobber: false)
         
     | 
| 
      
 170 
     | 
    
         
            +
                  File.open(Schema.yml_file, "a") { |f| f.write("- #{name}\n") }
         
     | 
| 
      
 171 
     | 
    
         
            +
                  Git.add(Schema.yml_file)
         
     | 
| 
      
 172 
     | 
    
         
            +
                  submit "Added schema #{name}", commit
         
     | 
| 
      
 173 
     | 
    
         
            +
                end
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
                def prepare_diff(from_version = version)
         
     | 
| 
      
 176 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 177 
     | 
    
         
            +
                    from_name = "#{name}-base"
         
     | 
| 
      
 178 
     | 
    
         
            +
                    from_db = Database.new(from_name, user)
         
     | 
| 
      
 179 
     | 
    
         
            +
                    build(from_db, version: from_version)
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                    to_name = "#{name}-next"
         
     | 
| 
      
 182 
     | 
    
         
            +
                    to_db = Database.new(to_name, user)
         
     | 
| 
      
 183 
     | 
    
         
            +
                    build(to_db)
         
     | 
| 
      
 184 
     | 
    
         
            +
             
     | 
| 
      
 185 
     | 
    
         
            +
                    if prerelease_branch?
         
     | 
| 
      
 186 
     | 
    
         
            +
                      head.migrate_features(from_db)
         
     | 
| 
      
 187 
     | 
    
         
            +
                    end
         
     | 
| 
      
 188 
     | 
    
         
            +
             
     | 
| 
      
 189 
     | 
    
         
            +
                    diff = Diff.new(from_db, to_db)
         
     | 
| 
      
 190 
     | 
    
         
            +
                    for path, lines, tables in [
         
     | 
| 
      
 191 
     | 
    
         
            +
                        [BEFORE_TABLES_DIFF_PATH, diff.before_table_changes, false], 
         
     | 
| 
      
 192 
     | 
    
         
            +
                        [TABLES_DIFF_PATH, diff.table_changes, true], 
         
     | 
| 
      
 193 
     | 
    
         
            +
                        [AFTER_TABLES_DIFF_PATH, diff.after_table_changes, false]]
         
     | 
| 
      
 194 
     | 
    
         
            +
                      if lines.empty?
         
     | 
| 
      
 195 
     | 
    
         
            +
                        if File.exist?(path)
         
     | 
| 
      
 196 
     | 
    
         
            +
                          if tables
         
     | 
| 
      
 197 
     | 
    
         
            +
                            Share.cp(File.join("diff", File.basename(path)), path)
         
     | 
| 
      
 198 
     | 
    
         
            +
                            Git.add(path)
         
     | 
| 
      
 199 
     | 
    
         
            +
                          else
         
     | 
| 
      
 200 
     | 
    
         
            +
                            Git.rm(path)
         
     | 
| 
      
 201 
     | 
    
         
            +
                          end
         
     | 
| 
      
 202 
     | 
    
         
            +
                        end
         
     | 
| 
      
 203 
     | 
    
         
            +
                      else
         
     | 
| 
      
 204 
     | 
    
         
            +
                        Share.cp(File.join("diff", File.basename(path)), path)
         
     | 
| 
      
 205 
     | 
    
         
            +
                        File.open(path, "a") { |f| f.puts lines }
         
     | 
| 
      
 206 
     | 
    
         
            +
                        Git.add(path) if !tables
         
     | 
| 
      
 207 
     | 
    
         
            +
                      end
         
     | 
| 
      
 208 
     | 
    
         
            +
                    end
         
     | 
| 
      
 209 
     | 
    
         
            +
                    self
         
     | 
| 
      
 210 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 211 
     | 
    
         
            +
                    from_db&.drop
         
     | 
| 
      
 212 
     | 
    
         
            +
                    to_db&.drop
         
     | 
| 
      
 213 
     | 
    
         
            +
                  end
         
     | 
| 
      
 214 
     | 
    
         
            +
                end
         
     | 
| 
      
 215 
     | 
    
         
            +
             
     | 
| 
      
 216 
     | 
    
         
            +
                def create_release(new_version) 
         
     | 
| 
      
 217 
     | 
    
         
            +
                  check_clean(:release_branch)
         
     | 
| 
      
 218 
     | 
    
         
            +
                  head = ReleaseTag.new(new_version, version)
         
     | 
| 
      
 219 
     | 
    
         
            +
                  check_migration(head.migration)
         
     | 
| 
      
 220 
     | 
    
         
            +
                  (@head = head).create
         
     | 
| 
      
 221 
     | 
    
         
            +
                  self
         
     | 
| 
      
 222 
     | 
    
         
            +
                end
         
     | 
| 
      
 223 
     | 
    
         
            +
             
     | 
| 
      
 224 
     | 
    
         
            +
                def generate_schema
         
     | 
| 
      
 225 
     | 
    
         
            +
                  build = SchemaBuilder.new(database, SCHEMA_DIR).build(execute: false)
         
     | 
| 
      
 226 
     | 
    
         
            +
                  puts build.lines
         
     | 
| 
      
 227 
     | 
    
         
            +
                end
         
     | 
| 
      
 228 
     | 
    
         
            +
             
     | 
| 
      
 229 
     | 
    
         
            +
                def generate_migration
         
     | 
| 
      
 230 
     | 
    
         
            +
                  build = MigrationBuilder.new(database, MIGRATION_DIR).build(execute: false)
         
     | 
| 
      
 231 
     | 
    
         
            +
                  puts build.lines
         
     | 
| 
      
 232 
     | 
    
         
            +
                end
         
     | 
| 
      
 233 
     | 
    
         
            +
             
     | 
| 
      
 234 
     | 
    
         
            +
              private
         
     | 
| 
      
 235 
     | 
    
         
            +
                def check(kind) self.send(:"#{kind}?") end
         
     | 
| 
      
 236 
     | 
    
         
            +
                def check_clean(kind = nil)
         
     | 
| 
      
 237 
     | 
    
         
            +
                  clean? or raise Internal, "Dirty repository" 
         
     | 
| 
      
 238 
     | 
    
         
            +
                  kind.nil? || check(kind) or raise Internal, "Not on a #{kind} tag/branh"
         
     | 
| 
      
 239 
     | 
    
         
            +
                end
         
     | 
| 
      
 240 
     | 
    
         
            +
             
     | 
| 
      
 241 
     | 
    
         
            +
                def check_branch() branch? or raise Internal, "Not on a branch" end
         
     | 
| 
      
 242 
     | 
    
         
            +
                def check_tag() tag? or raise Internal, "Not on a tag" end
         
     | 
| 
      
 243 
     | 
    
         
            +
             
     | 
| 
      
 244 
     | 
    
         
            +
                # FIXME: Use Cache::file
         
     | 
| 
      
 245 
     | 
    
         
            +
                def cache_file(version) File.join(CACHE_DIR, "#{database(version)}.sql.gz") end
         
     | 
| 
      
 246 
     | 
    
         
            +
             
     | 
| 
      
 247 
     | 
    
         
            +
                def submit(msg, commit = true)
         
     | 
| 
      
 248 
     | 
    
         
            +
                  Git.commit msg if commit
         
     | 
| 
      
 249 
     | 
    
         
            +
                  @message = msg
         
     | 
| 
      
 250 
     | 
    
         
            +
                end
         
     | 
| 
      
 251 
     | 
    
         
            +
             
     | 
| 
      
 252 
     | 
    
         
            +
                def clean(database) # FIXME: Use Database#clean
         
     | 
| 
      
 253 
     | 
    
         
            +
                  if database.exist?
         
     | 
| 
      
 254 
     | 
    
         
            +
                    database.recreate if database.loaded?
         
     | 
| 
      
 255 
     | 
    
         
            +
                  else
         
     | 
| 
      
 256 
     | 
    
         
            +
                    database.create
         
     | 
| 
      
 257 
     | 
    
         
            +
                  end
         
     | 
| 
      
 258 
     | 
    
         
            +
                end
         
     | 
| 
      
 259 
     | 
    
         
            +
             
     | 
| 
      
 260 
     | 
    
         
            +
                def check_migration(migration)
         
     | 
| 
      
 261 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 262 
     | 
    
         
            +
                    from_version = migration.base_version
         
     | 
| 
      
 263 
     | 
    
         
            +
                    from_db = Database.new("#{name}-base", user)
         
     | 
| 
      
 264 
     | 
    
         
            +
                    to_db = Database.new("#{name}-next", user)
         
     | 
| 
      
 265 
     | 
    
         
            +
                    build(from_db, version: from_version)
         
     | 
| 
      
 266 
     | 
    
         
            +
                    build(to_db)
         
     | 
| 
      
 267 
     | 
    
         
            +
                    migration.migrate(from_db)
         
     | 
| 
      
 268 
     | 
    
         
            +
                    Diff.new(from_db, to_db).same? or raise Error, "Schema/migration mismatch"
         
     | 
| 
      
 269 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 270 
     | 
    
         
            +
                    from_db&.drop
         
     | 
| 
      
 271 
     | 
    
         
            +
                    to_db&.drop
         
     | 
| 
      
 272 
     | 
    
         
            +
                  end
         
     | 
| 
      
 273 
     | 
    
         
            +
                end
         
     | 
| 
      
 274 
     | 
    
         
            +
              end
         
     | 
| 
      
 275 
     | 
    
         
            +
            end
         
     | 
| 
      
 276 
     | 
    
         
            +
             
     | 
| 
      
 277 
     | 
    
         
            +
            __END__
         
     | 
| 
      
 278 
     | 
    
         
            +
             
     | 
| 
       5 
279 
     | 
    
         
             
            module Prick
         
     | 
| 
       6 
280 
     | 
    
         
             
              class Project
         
     | 
| 
       7 
281 
     | 
    
         
             
                # Name of project. Persisted in the project state file
         
     |