Class: Prick::State

Inherits:
Object
  • Object
show all
Defined in:
lib/prick/state.rb

Overview

There is only one State object: Prick.state

FIXME Not how it is done The prick.state file contains the current database, username, and environment. It is controlled by prick(1) but you can set its values by using ‘prick database=asdf

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project_file, environment_file, reflections_file, state_file, fox_state_file) ⇒ State

Returns a new instance of State.



105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/prick/state.rb', line 105

def initialize(project_file, environment_file, reflections_file, state_file, fox_state_file)
  @project_file, @environment_file, @reflections_file, @state_file, @fox_state_file =
      project_file, environment_file, reflections_file, state_file, fox_state_file
  @project_loaded = @state_loaded = @environment_loaded = false

  if @project_file && File.exist?(@project_file)
    load_project_file
    load_state_file if @state_file && File.exist?(@state_file)
  end

  # FIXME The environment file should be loaded on-demand but it is hard to
  # do when the environments are accessed through a class-interface
  load_environment_file if @environment_file && File.exist?(@environment_file)
end

Instance Attribute Details

#databaseObject

Database name. nil if state file is absent



59
60
61
# File 'lib/prick/state.rb', line 59

def database
  @database
end

#database_environmentObject

Environment from PRICK.VERSIONS. Initialized by #connection



86
87
88
# File 'lib/prick/state.rb', line 86

def database_environment
  @database_environment
end

#database_prick_versionObject

Prick version from PRICK.VERSIONS. Initialized by #connection



83
84
85
# File 'lib/prick/state.rb', line 83

def database_prick_version
  @database_prick_version
end

#database_versionObject

Project version from PRICK.VERSIONS. Initialized by #connection



80
81
82
# File 'lib/prick/state.rb', line 80

def database_version
  @database_version
end

#environment_fileObject (readonly)

Environment file. Default ‘prick.environment’. Note that the file can be absent if the project doesn’t use environments



25
26
27
# File 'lib/prick/state.rb', line 25

def environment_file
  @environment_file
end

#environmentsObject (readonly)

Map from environment name to environment object



66
67
68
# File 'lib/prick/state.rb', line 66

def environments
  @environments
end

#fox_state_fileObject (readonly)

Fox state file. Default ‘.fox-state.yml’



35
36
37
# File 'lib/prick/state.rb', line 35

def fox_state_file
  @fox_state_file
end

#nameObject

Used as an identifier and the default database and username



46
47
48
# File 'lib/prick/state.rb', line 46

def name
  @name
end

#prick_versionObject

Version of prick in prick.yml. Note that this can be different than the current version of prick



56
57
58
# File 'lib/prick/state.rb', line 56

def prick_version
  @prick_version
end

#project_fileObject (readonly)

Project file. Default ‘prick.yml’



21
22
23
# File 'lib/prick/state.rb', line 21

def project_file
  @project_file
end

#reflections_fileObject (readonly)

Reflections file. Default ‘schema/reflections.yml’. May be nil if the file is absent



29
30
31
# File 'lib/prick/state.rb', line 29

def reflections_file
  @reflections_file
end

#state_fileObject (readonly)

State file. Default ‘.prick-state.yml’



32
33
34
# File 'lib/prick/state.rb', line 32

def state_file
  @state_file
end

#titleObject

Capitalized name of project



49
50
51
# File 'lib/prick/state.rb', line 49

def title
  @title
end

#usernameObject

Database owner name. Typically the same as the database name. nil if database is absent



63
64
65
# File 'lib/prick/state.rb', line 63

def username
  @username
end

#versionObject

Project version in prick.yml. Can be nil FIXME Can it?



52
53
54
# File 'lib/prick/state.rb', line 52

def version
  @version
end

Class Method Details

.connection(&block) ⇒ Object

Superuser connection. This is a connection to Postgres using the current user’s credentials. It is assumed that the current user has a postgres superuser account with the same name as the user’s. Memoized to connect only once



153
154
155
156
157
158
159
160
# File 'lib/prick/state.rb', line 153

def self.connection(&block)
  @@connection ||= PgConn.new("postgres")
  if block_given?
    yield @@connection
  else
    @@connection
  end
end

Instance Method Details

#bash_environment(all: true) ⇒ Object

Create a bash(1) environment (Hash). It is used for in-prick expansion of variables and is also injected into the enviroment of subprocesses

FIXME: Problems with BUNDLE_* variables FIXME Still a problem?

TODO: Explain handling of PRICK_<STANDARD-DIRECTORY>



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/prick/state.rb', line 176

def bash_environment(all: true)
  @bash_environment ||= begin
    hash = {
      "PATH" => Prick.state.executable_search_path
    }

    if all
      hash.merge!({
        "PRICK_DIR" => Prick.state.prick_dir,
        "PRICK_SCHEMADIR" =>  File.join(Prick.state.prick_dir, SCHEMA_DIR),
        "PRICK_BINDIR" =>  File.join(Prick.state.prick_dir, BIN_DIR),
        "PRICK_LIBEXECDIR" =>  File.join(Prick.state.prick_dir, LIBEXEC_DIR),
        "PRICK_VARDIR" =>  File.join(Prick.state.prick_dir, VAR_DIR),
        "PRICK_CACHEDIR" =>  File.join(Prick.state.prick_dir, CACHE_DIR),
        "PRICK_SPOOLDIR" =>  File.join(Prick.state.prick_dir, SPOOL_DIR),
        "PRICK_TMPDIR" =>  File.join(Prick.state.prick_dir, TMP_DIR),
        "PRICK_CLONEDIR" =>  File.join(Prick.state.prick_dir, CLONE_DIR),
        "PRICK_SPECDIR" =>  File.join(Prick.state.prick_dir, BIN_DIR),
      })
    end

    hash.merge!({
      "DATABASE" =>  Prick.state.database, # FIXME: Yt
      "USERNAME" =>  Prick.state.username, # FIXME: Yt
      "ENVIRONMENT" =>  Prick.state.environment.to_s, # FIXME: Yt except in build.yml parser
      "PRICK_NAME" => Prick.state.name,
      "PRICK_TITLE" => Prick.state.title,
      "PRICK_VERSION" => Prick.state.version,
      "PRICK_DATABASE" =>  Prick.state.database,
      "PRICK_USERNAME" =>  Prick.state.username,
      "PRICK_ENVIRONMENT" =>  Prick.state.environment&.to_s, # may be the empty string
    })

    # PRICK_ENVIRONMENT_* variables. Only defined if the environment is known
    if !Prick.state.environment.nil? && environments.key?(environment)
      hash.merge! environments[environment].bash_environment
    end
  end
end

#bash_source(vars = nil, scope: nil) ⇒ Object

declared local), or nil (variables are global but not exported)

Only non-text variables are emitted



220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/prick/state.rb', line 220

def bash_source(vars = nil, scope: nil)
  exclude = Array(exclude || []).flatten.map { _1.to_s }
  case scope
    when :global; prefix="export "
    when :local; prefix="local "
    when nil; prefix=""
  else
    raise ArgumentError, "Illegal value for scope: #{scope.inspect}"
  end

  vars ||= bash_environment&.keys || []
  assignments = []
  vars.each { |var|
    val = bash_environment[var]
#       next if val =~ /['"\n]/m # We don't quote
    if val.is_a?(Array)
      if val.first.is_a?(Array)
        val = val.map { |v| v.join("\n") }.join("\n")
      else
        val = val.join(" ")
      end
    end
    assignments << "#{prefix}#{var}='#{val}'\n"
  }
  assignments.join
end

#branchObject

Git branch. Lazy-evaluated



89
# File 'lib/prick/state.rb', line 89

def branch() @branch ||= Git.branch.current end

#clean?Boolean

True if the git repository is clean (not modified). Lazy-evaluated

Returns:

  • (Boolean)


100
101
102
103
# File 'lib/prick/state.rb', line 100

def clean?()
  return @clean if defined?(@clean)
  @clean = Git.clean?
end

#connection(database: nil, username: nil, environment: nil, &block) ⇒ Object Also known as: conn

Project user (owner) connection. Memoized to connect only once. TODO Rename. Also rename self.connection



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/prick/state.rb', line 122

def connection(database: nil, username: nil, environment: nil, &block)
  if @connection.nil?
    database ||= self.database
    username ||= self.username
    environment ||= self.environment
    !database.nil? or Prick.error "Can't connect to Postgres - no database specified"
#       exist_database_environment? or Prick.error "Database '#{database}' is not initialized"

    @connection = PgConn.new(database, username)

    # Set database_version/environment/prick members
    load_database_environment

    # Set environment if undefined and not overridden by :environment
    self.environment =
        environment ||
        Prick.state.environment ||
        environments.key?(database_environment) && database_environment ||
        DEFAULT_ENVIRONMENT
  end
  if block_given?
    yield @connection
  else
    @connection
  end
end

#dumpObject



307
308
309
310
311
312
313
314
315
316
317
318
# File 'lib/prick/state.rb', line 307

def dump
  puts "State"
  indent {
    for method in [
        :name, :title, :prick_version, :project_version,
        :database_version, :database_environment, :database, :username]
      puts "#{method}: #{self.send method}"
    end
    puts "environments:"
    indent { environments.dump }
  }
end

#environmentObject

Name of current environment. If not set in the state file, the enviroment is read from the database when the first connection is established by the #connection method. Use ‘#environments’ to get the corresponding Environment object



72
# File 'lib/prick/state.rb', line 72

def environment() @environment end

#environment=(env) ⇒ Object



73
74
75
76
77
# File 'lib/prick/state.rb', line 73

def environment=(env)
  constrain env, String, nil
  env.nil? || environments.key?(env) or raise "Illegal environment: '#{env}'"
  @environment = env
end

#environment_loaded?Boolean

Returns:

  • (Boolean)


43
# File 'lib/prick/state.rb', line 43

def environment_loaded? = @environment_loaded

#executable_search_pathObject

Prick executable search_path. This includes the bin and libexec directories



166
167
168
# File 'lib/prick/state.rb', line 166

def executable_search_path
  @executable_search_path ||= "#{ENV['PATH']}:#{prick_dir}/#{BIN_DIR}:#{prick_dir}/#{LIBEXEC_DIR}"
end

#prick_dirObject

Prick project dir. This is not a constant because prick can change directory through the -C option or the ‘init’ command



15
# File 'lib/prick/state.rb', line 15

def prick_dir() @prick_dir ||= Dir.getwd end

#project_loaded?Boolean

True if the configuration files has been loaded

Returns:

  • (Boolean)


41
# File 'lib/prick/state.rb', line 41

def project_loaded? = @project_loaded

#rev(kind: :long) ⇒ Object

Git revision (commit ID). Lazy-evaluated



92
93
94
95
96
97
# File 'lib/prick/state.rb', line 92

def rev(kind: :long)
  case kind
    when :short; @rev_short ||= rev()[0...8]
    when :long; @rev_long ||= Git.id
  end
end

#save_build(success = true) ⇒ Object



297
298
299
300
301
302
303
304
305
# File 'lib/prick/state.rb', line 297

def save_build(success = true)
  insert_record(
    "prick.builds",
        name: name,
        version: version.to_s, prick: Prick::VERSION,
        branch: branch, rev: rev(kind: :short), clean: clean?,
        environment: environment,
        success: success)
end

#save_build_beginObject

Save build-start information to PRICK.BUILDS. It is a nop if PRICK.BUILDS doesn’t exist, this happens on first build in a completely empty database



269
270
271
272
273
274
275
276
277
278
279
280
# File 'lib/prick/state.rb', line 269

def save_build_begin
  @build_id = nil # Used by save_build_end
  if conn.schema.exist_table?("prick", "builds")
    @build_id = insert_record(
        "prick.builds",
        name: name,
        version: version.to_s, prick: Prick::VERSION,
        branch: branch, rev: rev(kind: :short), clean: clean?,
        environment: environment)
  end
#           version: version.to_s, prick: prick_version,
end

#save_build_end(success, duration) ⇒ Object



282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/prick/state.rb', line 282

def save_build_end(success, duration)
  dt = Time.now - TIME
  if @build_id
    update_record("prick.builds", @build_id, success: success, duration: duration, prick_duration: dt)
  else
    insert_record(
        "prick.builds",
        name: name,
        version: version.to_s, prick: Prick::VERSION,
        branch: branch, rev: rev(kind: :short), clean: clean?,
        environment: environment,
        success: success, duration: duration, prick_duration: dt)
  end
end

#save_project(overwrite: false) ⇒ Object

It is an error if the project file exists.



248
249
250
251
252
# File 'lib/prick/state.rb', line 248

def save_project(overwrite: false)
  overwrite || !File.exists?(project_file) or Prick.error "Won't overwrite '#{project_file}'"
  hash = { name: name, title: title, version: version.to_s, prick: Prick::VERSION }
  save_yaml(project_file, hash)
end

#save_state(database = nil, username = nil, environment = nil) ⇒ Object

Used by ‘prick setup’



260
261
262
263
264
265
# File 'lib/prick/state.rb', line 260

def save_state(database = nil, username = nil, environment = nil)
  database ||= self.database or raise ArgumentError
  username ||= self.username or raise ArgumentError
  environment ||= self.environment
  save_yaml(state_file, database: database, username: username, environment: environment)
end

#save_versionObject

FIXME: Ugly



255
256
257
# File 'lib/prick/state.rb', line 255

def save_version
  system("sed -i 's/^version:.*/version: #{version.to_s} #{project_file}/'")
end

#schema_dirObject

Prick schema dir



18
# File 'lib/prick/state.rb', line 18

def schema_dir() @schema_dir ||= File.join(prick_dir, SCHEMA_DIR) end

#schema_fileObject

Schema data file. FIXME What is this?



38
# File 'lib/prick/state.rb', line 38

def schema_file() SCHEMA_VERSION_PATH end

#state_loaded?Boolean

Returns:

  • (Boolean)


42
# File 'lib/prick/state.rb', line 42

def state_loaded? = @state_loaded