Class: Amp::Dispatch

Inherits:
Object show all
Defined in:
lib/amp/commands/dispatch.rb

Overview

Dispatch

This class handles parsing command-line options, finding commands, and running them.

Class Method Summary collapse

Class Method Details

.find_ampfile(dir = Dir.pwd) ⇒ String

Gets the path to the Ampfile if there is one.

Returns:

  • (String)

    the path to an Ampfile



139
140
141
142
143
144
145
146
147
148
149
# File 'lib/amp/commands/dispatch.rb', line 139

def self.find_ampfile(dir=Dir.pwd)
  rock_bottom = false
  begin
    rock_bottom = true if dir == "/" 
    ["ampfile","Ampfile","ampfile.rb","Ampfile.rb"].each do |pos|
      file = File.join(dir, pos)
      return file if File.exist? file
    end
    dir = File.dirname(dir)
  end until rock_bottom
end

.pick_command(cmd, config) ⇒ Amp::Command

Picks a command from the list of all possible commands, based on a couple simple rules.

  1. Look up the command by exact name. If no command is provided, supply “default”.

  2. Check for “synonyms” - “remove” is synonym’d as “rm”. This check occurs inside

the call to Amp::Command[].
  1. Check to see if there is only 1 command with our “cmd” as the prefix. For example,

if the user inputs "amp stat", and only one command starts with "stat" (ie "status"),
then return that command. If there is more than 1 match, then exit, showing an error
due to the ambiguity.

Parameters:

  • cmd (String)

    the command to look up

Returns:

  • (Amp::Command)

    the command object that was found, or nil if none was found.



165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/amp/commands/dispatch.rb', line 165

def self.pick_command(cmd, config)  
  my_flow = config["amp"]["workflow"]
  if c = Amp::Command.all_for_workflow(my_flow).keys.map {|k| k.to_s}.abbrev[cmd]
    Amp::Command.command_for_workflow(c, my_flow)
  else
    prefix_list = Amp::Command.all_for_workflow(my_flow).keys.map {|k| k.to_s}.select {|k| k.start_with? cmd.to_s }
    
    if prefix_list.size > 1
      puts "Ambiguous command: #{cmd}. Could mean: #{prefix_list.join(", ")}"
      exit(-1)
    end
    nil
  end
end

.runObject

This method essentially runs the amp executable. It first parses global options (–config) finds the subcommand (eg add, init, clone), parses the subcommand’s options, merges the two, and then runs the entire thing.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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
# File 'lib/amp/commands/dispatch.rb', line 17

def self.run
  # Get the subcommands so we can stop on them
  sub_commands = Amp::Command.all_commands.keys
  # Get the global options (everything before the subcommand)
  global_opts = Trollop::options do
    banner "Amp - some more crystal, sir?"
    version "Amp version #{Amp::VERSION} (#{Amp::VERSION_TITLE})"
    opt :debug_opts,      "Debug the command-line options", :short => "-d", :default => false, :type => :boolean
    opt :verbose,         "Verbose output"
    opt :profile,         "Profile the command being run, running it the given number of times"
    opt :repository,      "The path to the repository to use", :short => "-R", :type => :string, :default => Dir.pwd
    opt :"pure-ruby",     "Use only pure ruby (no C-extensions)"
    opt :testing,         "Running a test. Not for users to use"
    stop_on_unknown
  end
  global_opts = global_opts.first # we don't need the parser here
  
  # This loads the built-in ruby profiler - it's extremely slow. Use with care.
  if global_opts[:profile]
    require 'profile'
  end
  
  # Never load a C extension if we're in pure-ruby mode.
  if global_opts[:"pure-ruby"]
    $USE_RUBY = true
  end
  
  global_config = Amp::AmpConfig.new
  Amp::UI.config = global_config
  cmd = ARGV.shift # get the subcommand
  cmd ||= "default"
  
  opts_as_arr = ARGV.dup
  
  if global_opts[:debug_opts]
    global_config["debug", "messages"] = true
  end
  
  unless global_config["amp"]["workflow"]
    global_config["amp"]["workflow"] = :hg
    global_config.save! rescue Errno::EACCES
  end
  
  # the options to send to the command
  cmd_opts = {}
  
  # Load the repository
  #path_to_repo = find_repo(".", cmd_opts) unless global_opts[:repository]
  path_to_repo = ""
  
  if path_to_repo.empty?
    local_config = global_config
  else
    local_config = AmpConfig.new(:parent_config => global_config)
    local_config.read_file File.join(path_to_repo, ".hg", "hgrc")
  end
  
  begin
    cmd_opts[:repository] = Repositories.pick(local_config, global_opts[:repository])
  rescue
    unless Command::NO_REPO_ALLOWED[cmd] || Command::MAYBE_REPO_ALLOWED[cmd]
      raise
    end
  end
  
  if cmd_opts[:repository].respond_to? :config
    cmd_opts[:repository].config && local_config = cmd_opts[:repository].config
  end
  
  workflow = local_config["amp"]["workflow"]
  
  if File.exists?(File.expand_path(File.join(File.dirname(__FILE__), "commands/workflows/#{workflow}/")))
    require_dir { "amp/commands/commands/workflows/#{workflow}/**/*.rb" }
  end
  
  user_amprc = File.expand_path("~/.amprc")
  File.exist?(user_amprc) && load(user_amprc)  

  path_to_ampfile = find_ampfile
  load path_to_ampfile if path_to_ampfile
  
  command = pick_command cmd, local_config
  
  unless command
    puts "Invalid command! #{cmd}"
    exit(-1)
  end
  
  # get the sub-command's options
  # if there's a conflict, check to see that the newest value isn't nil
  cmd_opts.merge!(command.collect_options) {|k, v1, v2| v2 || v1 }
  
  cmd_opts[:global_config] = local_config
  if global_opts[:debug_opts]
    require 'yaml'
    puts "Current directory: #{Dir.pwd}"
    puts "Global options: \n#{global_opts.inspect.to_yaml}"
    puts "Subcommand: #{cmd.inspect}"
    puts "Subcommand options: \n#{cmd_opts.to_yaml}"
    puts "Remaining arguments: #{ARGV.inspect}"
    puts "\n"
    puts "Parsed and merged global config files:"
    puts local_config.config.to_s
    puts
  end
  
  # Run that fucker!!!
  begin
    full_backtrace_please do
      command.run cmd_opts, ARGV
    end
  rescue AbortError => e
    puts e.to_s
  end
  
  #Amp::Support::Logger.outdent.info("</#{command.name}>")
end