Class: Prick::Project
- Inherits:
-
Object
- Object
- Prick::Project
- Defined in:
- lib/prick/project.rb
Instance Attribute Summary collapse
-
#database ⇒ Object
readonly
The project database.
-
#features ⇒ Object
readonly
Hash from base-release name to feature.
-
#ignored_feature_nodes ⇒ Object
readonly
Ignored and orphaned objects.
-
#ignored_release_nodes ⇒ Object
readonly
Returns the value of attribute ignored_release_nodes.
-
#name ⇒ Object
readonly
Name of project.
-
#orphan_feature_nodes ⇒ Object
readonly
Returns the value of attribute orphan_feature_nodes.
-
#orphan_git_branches ⇒ Object
readonly
Returns the value of attribute orphan_git_branches.
-
#orphan_release_nodes ⇒ Object
readonly
Returns the value of attribute orphan_release_nodes.
-
#prereleases ⇒ Object
readonly
List of pre-releases.
-
#releases ⇒ Object
readonly
List of releases ordered from oldest to newest.
-
#schema ⇒ Object
readonly
Schema.
-
#user ⇒ Object
readonly
Name of Postgresql user that own the database(s).
Class Method Summary collapse
-
.initialize_directory(directory) ⇒ Object
Initialize an on-disk prick instance.
-
.initialize_project(name = File.basename(Dir.getwd), user = ) ⇒ Object
Create an initial release 0.0.0.
Instance Method Summary collapse
- #[](name_or_version) ⇒ Object
- #[]=(name_or_version, branch) ⇒ Object
-
#build(version = nil) ⇒ Object
Build the current database from the content of schema.
- #build?(name_or_version) ⇒ Boolean
-
#builds ⇒ Object
List of all builds.
-
#checkout(name) ⇒ Object
COMMON METHODS.
-
#cleanup(version = nil, project: false) ⇒ Object
Remove temporary files and databases.
- #commit_feature ⇒ Object
- #create_feature(name) ⇒ Object
- #create_migration ⇒ Object
- #create_prerelease(target_version) ⇒ Object
- #create_release(version = nil) ⇒ Object
-
#databases(all: false, project: true) ⇒ Object
Sorted list of databases associated with a release.
- #dirty? ⇒ Boolean
-
#feature(name) ⇒ Object
Create and switch to feature branch.
-
#feature? ⇒ Boolean
True if we’re on a feature branch.
-
#include_feature(feature_version) ⇒ Object
Note: Does not commit.
- #increment_prerelease ⇒ Object
-
#initialize(name = nil, user = nil) ⇒ Project
constructor
‘name` is the project name and `user` is the name of the Postgresql user.
-
#load_database(version, file = nil) ⇒ Object
Load file into the given database version.
-
#migrate ⇒ Object
Migrate the database from its current version to the current release on disk.
-
#path ⇒ Object
Returns the full path to the project directory (TODO: Test).
- #prepare_migration ⇒ Object
-
#prepare_release ⇒ Object
Create the first prerelease.
-
#prerelease? ⇒ Boolean
True if we’re on a pre-release branch.
- #rebase(version) ⇒ Object
-
#release ⇒ Object
The current release, prerelease or feature.
-
#release? ⇒ Boolean
True if we’re on a release branch.
-
#use_database(file = nil) ⇒ Object
Load file into current database.
Constructor Details
#initialize(name = nil, user = nil) ⇒ Project
‘name` is the project name and `user` is the name of the Postgresql user. `name` defaults to the name of the current directory and `user` defaults to `name`
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/prick/project.rb', line 77 def initialize(name = nil, user = nil) @name = name || File.basename(Dir.getwd) @name =~ PROJECT_NAME_RE or raise Error, "Illegal project name: #@name" @user = user || @name @user =~ USER_NAME_RE or raise Error, "Illegal postgres user name: #@user" # Rdbms.ensure_state(:user_exist, @user) Rdbms.create_user(@user) if !Rdbms.exist_user?(@user) # FIXME @schema = Schema.new(self) @database = Database.new(@name, @user) @builds_by_name = {} @builds_by_version = {} @releases = [] @prereleases = [] @features = {} @ignored_feature_nodes = [] @ignored_release_nodes = [] @orphan_feature_nodes = [] @orphan_release_nodes = [] # Includes prereleases @orphan_git_branches = [] load_project end |
Instance Attribute Details
#database ⇒ Object (readonly)
The project database. The project database has the same name as the project and doesn’t include a version. It does not have to exist
31 32 33 |
# File 'lib/prick/project.rb', line 31 def database @database end |
#features ⇒ Object (readonly)
Hash from base-release name to feature. Note that this doesn’t follow release history
44 45 46 |
# File 'lib/prick/project.rb', line 44 def features @features end |
#ignored_feature_nodes ⇒ Object (readonly)
Ignored and orphaned objects
47 48 49 |
# File 'lib/prick/project.rb', line 47 def ignored_feature_nodes @ignored_feature_nodes end |
#ignored_release_nodes ⇒ Object (readonly)
Returns the value of attribute ignored_release_nodes.
48 49 50 |
# File 'lib/prick/project.rb', line 48 def ignored_release_nodes @ignored_release_nodes end |
#name ⇒ Object (readonly)
Name of project. Used in database and release names. Defaults to the name of the current directory
18 19 20 |
# File 'lib/prick/project.rb', line 18 def name @name end |
#orphan_feature_nodes ⇒ Object (readonly)
Returns the value of attribute orphan_feature_nodes.
49 50 51 |
# File 'lib/prick/project.rb', line 49 def orphan_feature_nodes @orphan_feature_nodes end |
#orphan_git_branches ⇒ Object (readonly)
Returns the value of attribute orphan_git_branches.
51 52 53 |
# File 'lib/prick/project.rb', line 51 def orphan_git_branches @orphan_git_branches end |
#orphan_release_nodes ⇒ Object (readonly)
Returns the value of attribute orphan_release_nodes.
50 51 52 |
# File 'lib/prick/project.rb', line 50 def orphan_release_nodes @orphan_release_nodes end |
#prereleases ⇒ Object (readonly)
List of pre-releases
41 42 43 |
# File 'lib/prick/project.rb', line 41 def prereleases @prereleases end |
#releases ⇒ Object (readonly)
List of releases ordered from oldest to newest. Custom releases are sorted after regular releases and alphabetical between themselves
38 39 40 |
# File 'lib/prick/project.rb', line 38 def releases @releases end |
#schema ⇒ Object (readonly)
Schema. Represents the schema definition under the schemas/ directory
24 25 26 |
# File 'lib/prick/project.rb', line 24 def schema @schema end |
#user ⇒ Object (readonly)
Name of Postgresql user that own the database(s). Defaults to #name
21 22 23 |
# File 'lib/prick/project.rb', line 21 def user @user end |
Class Method Details
.initialize_directory(directory) ⇒ Object
Initialize an on-disk prick instance
144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/prick/project.rb', line 144 def self.initialize_directory(directory) FileUtils.mkdir_p(directory) Dir.chdir(directory) { DIRS.each { |dir| !File.exist?(dir) or raise Fail, "Already initialized: Directory '#{dir}' exists" } FileUtils.mkdir_p(DIRS) DIRS.each { |dir| FileUtils.touch("#{dir}/.keep") } } end |
.initialize_project(name = File.basename(Dir.getwd), user = ) ⇒ Object
Create an initial release 0.0.0. ::initialize_project expects to be executed in the project directory
158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/prick/project.rb', line 158 def self.initialize_project(name = File.basename(Dir.getwd), user = name || ENV['USER']) FileUtils.cp("#{SHARE_PATH}/gitignore", ".gitignore") FileUtils.cp("#{SHARE_PATH}/schemas/prick/schema.sql", "schemas/prick") FileUtils.cp("#{SHARE_PATH}/schemas/prick/data.sql", "schemas/prick") Git.init Git.add(".") Git.commit("Initial import") project = Project.new(name, user) release = Release.new(project, nil, Version.new("0.0.0")) release.create Git.delete_branch("master") end |
Instance Method Details
#[](name_or_version) ⇒ Object
105 106 107 108 109 110 111 112 113 114 |
# File 'lib/prick/project.rb', line 105 def [](name_or_version) name = version = name_or_version case name_or_version when String; @builds_by_name[name] when Version; @builds_by_version[version] when NilClass; nil else raise Internal, "Expected String or Version index, got #{name_or_version.class}" end end |
#[]=(name_or_version, branch) ⇒ Object
116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/prick/project.rb', line 116 def []=(name_or_version, branch) case name_or_version when String; name = name_or_version version = Version.new(name) when Version version = name_or_version name = version.to_s else raise Internal, "Expected String or Version index, got #{name_or_version.class}" end @builds_by_name[name] = @builds_by_version[version] = branch end |
#build(version = nil) ⇒ Object
Build the current database from the content of schema
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 |
# File 'lib/prick/project.rb', line 287 def build(version = nil) if version.nil? database.recreate schema.build else release = self[version] or raise Error, "Can't find release #{version}" release.database.recreate FileUtils.mkdir_p(CACHE_DIR) if !File.directory?(File.join(CLONE_DIR, ".git")) FileUtils.rm_rf(CLONE_DIR) Command.command "git clone . #{CLONE_DIR}" end Dir.chdir(CLONE_DIR) { Git.checkout_tag(version.to_s) project = Project.new(name, user) release.database.recreate project.schema.build(release.database) } release.cache end end |
#build?(name_or_version) ⇒ Boolean
132 133 134 135 136 137 138 139 140 141 |
# File 'lib/prick/project.rb', line 132 def build?(name_or_version) name = version = name_or_version case name_or_version when String; @builds_by_name.key?(name) when Version; @builds_by_version.key?(version) when NilClass; nil else raise Internal, "Expected String or Version index, got #{name_or_version.class}" end end |
#builds ⇒ Object
List of all builds
34 |
# File 'lib/prick/project.rb', line 34 def builds() @builds_by_name.values end |
#checkout(name) ⇒ Object
COMMON METHODS
177 178 179 180 |
# File 'lib/prick/project.rb', line 177 def checkout(name) check_clean Git.checkout_branch(name) end |
#cleanup(version = nil, project: false) ⇒ Object
Remove temporary files and databases
348 349 350 351 352 353 354 355 356 357 358 |
# File 'lib/prick/project.rb', line 348 def cleanup(version = nil, project: false) if version release = self[version] release.archive.delete release.database.drop else FileUtils::rm_rf CLONE_DIR FileUtils::rm_f Dir.glob(File.join(CACHE_DIR, Prick.dump_glob(name))) databases(all: true, project: project).each(&:drop) end end |
#commit_feature ⇒ Object
277 278 279 280 281 |
# File 'lib/prick/project.rb', line 277 def commit_feature msg = File.readlines(".git/MERGE_MSG").first.chomp Git.commit msg # Command.command "git commit -F .git/MERGE_MSG" end |
#create_feature(name) ⇒ Object
262 263 264 265 266 267 |
# File 'lib/prick/project.rb', line 262 def create_feature(name) check_clean release? or raise Error, "Need to be on a release branch to create a feature" feature = Feature.new(self, release, name) feature.create end |
#create_migration ⇒ Object
283 284 |
# File 'lib/prick/project.rb', line 283 def create_migration end |
#create_prerelease(target_version) ⇒ Object
248 249 250 251 252 253 |
# File 'lib/prick/project.rb', line 248 def create_prerelease(target_version) check_clean release? or raise Error, "Need to be on a release branch to create a pre-release" prerelease = Prerelease.new(self, release, target_version.increment(:pre, 0), target_version) prerelease.create end |
#create_release(version = nil) ⇒ Object
233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/prick/project.rb', line 233 def create_release(version = nil) check_clean if release? !version.nil? or raise Error, "Need version argument when on a release branch" new_release = Release.new(self, release, version) elsif prerelease? version.nil? or raise Error, "Can't use version argument when on a pre-release branch" new_release = release.target_release else raise Error, "Need to be on a release or pre-prelease branch to create a new release" end new_release.create new_release end |
#databases(all: false, project: true) ⇒ Object
Sorted list of databases associated with a release. Also include the project database if project. is true. If all: is true, also list databases that match the project but is without an associated release
65 66 67 68 69 70 71 72 |
# File 'lib/prick/project.rb', line 65 def databases(all: false, project: true) r = (project ? [database] : []) if all r + Rdbms.list_databases(Prick.database_re(name)).map { |name| Database.new(name, user) } else r + @releases.map(&:database) end end |
#feature(name) ⇒ Object
Create and switch to feature branch
195 196 197 198 199 200 |
# File 'lib/prick/project.rb', line 195 def feature(name) check_clean release? or raise Error, "Need to be on a release branch to create a feature" feature = Feature.new(self, release, name).ensure(:active) Git.commit "Created feature #{name}" end |
#feature? ⇒ Boolean
True if we’re on a feature branch
60 |
# File 'lib/prick/project.rb', line 60 def feature?() release && !release.version.feature.nil? end |
#include_feature(feature_version) ⇒ Object
Note: Does not commit
270 271 272 273 274 275 |
# File 'lib/prick/project.rb', line 270 def include_feature(feature_version) check_clean prerelease? || feature? or raise Error, "Need to be on a prerelease or feature branch to include features" Git.branch?(feature_version) or raise Error, "Can't find branch #{feature_version}" release.include_feature(self[feature_version]) end |
#increment_prerelease ⇒ Object
255 256 257 258 259 260 |
# File 'lib/prick/project.rb', line 255 def increment_prerelease check_clean prerelease? or raise Error, "Need to be on a pre-release branch to make an incremental pre-release" prerelease = Prerelease.new(self, release.base_release, release.version.increment(:pre)) prerelease.create end |
#load_database(version, file = nil) ⇒ Object
Load file into the given database version. If version is nil the current database is used. If file is nil, the database associated with the given version is used. Not both version and file can be nil
320 321 322 323 324 325 326 327 328 329 330 331 332 333 |
# File 'lib/prick/project.rb', line 320 def load_database(version, file = nil) check_clean !version.nil? || !file.nil? or raise Fail, "Not both version and file can be nil" if version release = self[version] file ||= release.archive.path File.file?(file) or raise Error, "Can't find #{file}" release.database.recreate release.database.load(file) else database.recreate database.load(file) end end |
#migrate ⇒ Object
Migrate the database from its current version to the current release on disk
183 184 185 186 187 188 189 190 |
# File 'lib/prick/project.rb', line 183 def migrate check_clean database.exist? or raise "Project database not found" history = release.history.keys.reverse.drop(1) history.select! { |release| release.version >= database.version } history.each { |release| release.migration.migrate(database.name) } database.version = release.version end |
#path ⇒ Object
Returns the full path to the project directory (TODO: Test)
173 |
# File 'lib/prick/project.rb', line 173 def path() File.(".") end |
#prepare_migration ⇒ Object
221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/prick/project.rb', line 221 def prepare_migration check_clean prerelease? || feature? or raise Error, "Need to be on a prerelease or feature branch to include features" base_database = release.base_release.database build(base_release.version) if !base_database.loaded? build # if !database.loaded? diff_sql = release.migration.diff_sql Migra.migrate(base_database.name, database.name, diff_sql) end |
#prepare_release ⇒ Object
Create the first prerelease
TODO Make it just copy files and commit them. Supports a single-user workflow. Requires a :prepared state
215 216 217 218 219 |
# File 'lib/prick/project.rb', line 215 def prepare_release check_clean release? or raise Error, "Need to be on a release branch to prepare a new release" release.prepare end |
#prerelease? ⇒ Boolean
True if we’re on a pre-release branch
57 |
# File 'lib/prick/project.rb', line 57 def prerelease?() release && !release.version.pre.nil? && !feature? end |
#rebase(version) ⇒ Object
202 203 204 205 206 207 |
# File 'lib/prick/project.rb', line 202 def rebase(version) check_clean feature? or raise Error, "Need to be on a feature branch to rebase" release.rebase(version) Git.commit "Rebased to #{version}" end |
#release ⇒ Object
The current release, prerelease or feature
27 |
# File 'lib/prick/project.rb', line 27 def release() @builds_by_name[Git.current_branch] end |
#release? ⇒ Boolean
True if we’re on a release branch
54 |
# File 'lib/prick/project.rb', line 54 def release?() release && release.version.pre.nil? && !feature? end |
#use_database(file = nil) ⇒ Object
Load file into current database
310 311 312 313 314 315 |
# File 'lib/prick/project.rb', line 310 def use_database(file = nil) check_clean File.file?(file) or raise Error, "Can't find #{file}" database.recreate database.load(file) end |