Class: Mortar::Command::Base

Inherits:
Object
  • Object
show all
Includes:
Helpers
Defined in:
lib/mortar/command/base.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Helpers

#action, #ask, #confirm, #copy_if_not_present_at_dest, #default_host, #deprecate, #display, #display_header, #display_object, #display_row, #display_table, #display_with_indent, #download_to_file, #ensure_dir_exists, #error, error_with_failure, error_with_failure=, extended, extended_into, #format_bytes, #format_date, #format_with_bang, #get_terminal_environment, #home_directory, #host, #hprint, #hputs, included, included_into, #installed_with_omnibus?, #json_decode, #json_encode, #line_formatter, #longest, #output_with_bang, #quantify, #redisplay, #retry_on_exception, #running_on_a_mac?, #running_on_windows?, #set_buffer, #shell, #spinner, #status, #string_distance, #styled_array, #styled_error, #styled_hash, #styled_header, #suggestion, #test_name, #ticking, #time_ago, #truncate, #warning, #with_tty, #write_to_file

Constructor Details

#initialize(args = [], options = {}) ⇒ Base

Returns a new instance of Base.



38
39
40
41
42
43
44
45
46
# File 'lib/mortar/command/base.rb', line 38

def initialize(args=[], options={})
  @args = args
  @options = options
  #We never want to override the command line options so we store them.
  @original_options = options.dup

  #Initialize defaults from .mortar-defaults
  load_defaults('DEFAULTS')
end

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



35
36
37
# File 'lib/mortar/command/base.rb', line 35

def args
  @args
end

#optionsObject (readonly)

Returns the value of attribute options.



36
37
38
# File 'lib/mortar/command/base.rb', line 36

def options
  @options
end

Class Method Details

.namespaceObject



31
32
33
# File 'lib/mortar/command/base.rb', line 31

def self.namespace
  self.to_s.split("::").last.downcase
end

Instance Method Details

#apiObject



82
83
84
# File 'lib/mortar/command/base.rb', line 82

def api
  Mortar::Auth.api
end

#ask_public(is_public) ⇒ Object



199
200
201
202
203
204
205
# File 'lib/mortar/command/base.rb', line 199

def ask_public(is_public)
  if is_public
    unless confirm("Public projects allow anyone to view and fork the code in this project\'s repository. Are you sure? (y/n)")
      error("Mortar project was not registered")
    end
  end
end

#config_parametersObject



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/mortar/command/base.rb', line 90

def config_parameters
  param_list = []
  begin
    if project.name
      vars = api.get_config_vars(project.name).body['config']
      unless vars.empty?
        vars.each{|k, v| param_list.push({"name"=>k, "value"=>v})}
      end
    end
  rescue Mortar::Command::CommandFailed, Mortar::API::Errors::ErrorWithResponse
      # When running locally we're not guaranteed this is a project
      # or that it has a config, so lets keep running.
      vars = []
  end
  param_list
end

#get_error_message_context(message) ⇒ Object



139
140
141
142
143
144
# File 'lib/mortar/command/base.rb', line 139

def get_error_message_context(message)
  if message.start_with? "Undefined parameter"
    return "Use -p, --parameter NAME=VALUE to set parameter NAME to value VALUE."
  end
  return ""
end

#gitObject



86
87
88
# File 'lib/mortar/command/base.rb', line 86

def git
  @git ||= Mortar::Git::Git.new
end

#initialize_embedded_project(api_registration_result) ⇒ Object



253
254
255
256
257
258
# File 'lib/mortar/command/base.rb', line 253

def initialize_embedded_project(api_registration_result)
  File.open(".mortar-project-remote", "w") do |f|
    f.puts api_registration_result["git_url"]
  end
  git.sync_embedded_project(project, "master", git_organization)
end

#pig_parametersObject



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/mortar/command/base.rb', line 107

def pig_parameters
  paramfile_params = {}
  if options[:param_file]
    File.open(options[:param_file], "r").each do |line|
      line = line.chomp
      # If the line isn't empty
      if not line.empty? and not line.match(/^;/) and not line.start_with?("#")
        name, value = line.split('=', 2)
        if not name or not value
          error("Parameter file is malformed")
        end
        paramfile_params[name] = value
      end
    end
  end
  
  
  paramoption_params = {}
  input_parameters = options[:parameter] ? Array(options[:parameter]) : []
  input_parameters.each do |name_equals_value|
    name, value = name_equals_value.split('=', 2)
    paramoption_params[name] = value
  end

  parameters = []
  paramfile_params.merge(paramoption_params).each do |name, value|
    parameters << {"name" => name, "value" => value}
  end

  return parameters
end

#projectObject



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/mortar/command/base.rb', line 48

def project
  unless @project
    project_name, project_dir, remote = 
    if project_from_dir = extract_project_in_dir()
      [project_from_dir[0], Dir.pwd, project_from_dir[1]]
    elsif project_from_dir = extract_project_in_dir_no_git()
      [project_from_dir[0], Dir.pwd, project_from_dir[1]]
    else
      raise Mortar::Command::CommandFailed, "No project found.\nThis command must be run from within a project folder."
    end
    
    # if we only have a project name, look for the remote in the current dir
    unless remote
      if project_from_dir = extract_project_in_dir(project_name)
        project_dir = Dir.pwd
        remote = project_from_dir[1]
      end
    end
    
    @project = Mortar::Project::Project.new(project_name, project_dir, remote)

    #Every time we get the project, we're going to check if its a forked version and
    #if it is we'll check for new updates to the base project.
    begin
      if git.is_fork_repo_updated(git_organization)
        warning("The repository this project was forked from has been updated.  To get the latest changes commit all of your work and do:\n\n\tgit merge #{git.fork_base_remote_name}/master\n\nYou may have conflicts that will need to be resolved manually.\n\n")
      end
    rescue 
      #Do nothing.  We'll repeat this call often enough that we don't care if it fails.
    end
  end
  @project
end

#register_api_call(name, is_public) ⇒ Object



207
208
209
210
211
212
213
214
215
216
217
# File 'lib/mortar/command/base.rb', line 207

def register_api_call(name, is_public)
  project_id = nil
  
  is_private = !is_public # is private required by restful api
  validate_project_name(name)
  'registering project....\n'
  action("Sending request to register project: #{name}") do
    project_id = api.post_project(name, is_private).body["project_id"]
  end
  return project_id
end

#register_do(name, is_public, is_embedded, project_id) ⇒ Object

Register logic

if project id is not created, just pass in nil



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/mortar/command/base.rb', line 165

def register_do(name, is_public, is_embedded, project_id)
  if is_embedded
    validate_project_structure()

    register_project(name, is_public, project_id) do |project_result|
      initialize_embedded_project(project_result)
    end
  else
    unless git.has_dot_git?
    # check if we're in the parent directory
      if File.exists? name
        error("mortar projects:register must be run from within the project directory.\nPlease \"cd #{name}\" and rerun this command.")
      else
        error("No git repository found in the current directory.\nTo register a project that is not its own git repository, use the --embedded option.\nIf you do want this project to be its own git repository, please initialize git in this directory, and then rerun the register command.\nTo initialize your project in git, use:\n\ngit init\ngit add .\ngit commit -a -m \"first commit\"")
      end
    end


    unless git.remotes(git_organization).empty?
      begin
        error("Currently in project: #{project.name}.  You can not register a new project inside of an existing mortar project.")
      rescue Mortar::Command::CommandFailed => cf
        error("Currently in an existing Mortar project.  You can not register a new project inside of an existing mortar project.")
      end
    end

    register_project(name, is_public, project_id) do |project_result|
      git.remote_add("mortar", project_result['git_url'])
      git.push_master
      display "Your project is ready for use.  Type 'mortar help' to see the commands you can perform on the project.\n\n"
    end
  end
end

#register_project(name, is_public, project_id) ⇒ Object



219
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
246
247
248
249
250
251
# File 'lib/mortar/command/base.rb', line 219

def register_project(name, is_public, project_id)
  if project_id == nil      
    project_id = register_api_call(name, is_public)
  end
  
  project_result = nil
  project_status = nil
  display
  ticking(polling_interval) do |ticks|
    project_result = api.get_project(project_id).body
    project_status = project_result.fetch("status_code", project_result["status"])
    project_description = project_result.fetch("status_description", project_status)
    is_finished = Mortar::API::Projects::STATUSES_COMPLETE.include?(project_status)

    redisplay("Status: %s %s" % [
      project_description + (is_finished ? "" : "..."),
      is_finished ? " " : spinner(ticks)],
      is_finished) # only display newline on last message
    if is_finished
      display
      break
    end
  end
  
  case project_status
  when Mortar::API::Projects::STATUS_FAILED
    error("Project registration failed.\nError message: #{project_result['error_message']}")
  when Mortar::API::Projects::STATUS_ACTIVE
    yield project_result
  else
    raise RuntimeError, "Unknown project status: #{project_status} for project_id: #{project_id}"
  end
end

#validate_project_name(name) ⇒ Object



146
147
148
149
150
151
# File 'lib/mortar/command/base.rb', line 146

def validate_project_name(name)
  project_names = api.get_projects().body["projects"].collect{|p| p['name']}
  if project_names.include? name
    error("Your account already contains a project named #{name}.\nPlease choose a different name for your new project, or clone the existing #{name} code using:\n\nmortar projects:clone #{name}")
  end
end

#validate_project_structureObject



153
154
155
156
157
158
159
160
161
# File 'lib/mortar/command/base.rb', line 153

def validate_project_structure()
  present_dirs = Dir.glob("*").select { |path| File.directory? path }
  required_dirs = ["controlscripts", "pigscripts", "macros", "udfs", "fixtures"]
  missing_dirs = required_dirs - present_dirs

  if missing_dirs.length > 0
    error("Project missing required directories: #{missing_dirs.to_s}")
  end
end