amp 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.hgignore +26 -0
- data/AUTHORS +2 -0
- data/History.txt +6 -0
- data/LICENSE +37 -0
- data/MANIFESTO +7 -0
- data/Manifest.txt +294 -0
- data/README.md +129 -0
- data/Rakefile +102 -0
- data/SCHEDULE.markdown +12 -0
- data/STYLE +27 -0
- data/TODO.markdown +149 -0
- data/ampfile.rb +47 -0
- data/bin/amp +30 -0
- data/bin/amp1.9 +30 -0
- data/ext/amp/bz2/README.txt +39 -0
- data/ext/amp/bz2/bz2.c +1582 -0
- data/ext/amp/bz2/extconf.rb +77 -0
- data/ext/amp/bz2/mkmf.log +29 -0
- data/ext/amp/mercurial_patch/extconf.rb +5 -0
- data/ext/amp/mercurial_patch/mpatch.c +405 -0
- data/ext/amp/priority_queue/extconf.rb +5 -0
- data/ext/amp/priority_queue/priority_queue.c +947 -0
- data/ext/amp/support/extconf.rb +5 -0
- data/ext/amp/support/support.c +250 -0
- data/lib/amp.rb +200 -0
- data/lib/amp/commands/command.rb +507 -0
- data/lib/amp/commands/command_support.rb +137 -0
- data/lib/amp/commands/commands/config.rb +143 -0
- data/lib/amp/commands/commands/help.rb +29 -0
- data/lib/amp/commands/commands/init.rb +10 -0
- data/lib/amp/commands/commands/templates.rb +137 -0
- data/lib/amp/commands/commands/version.rb +7 -0
- data/lib/amp/commands/commands/workflow.rb +28 -0
- data/lib/amp/commands/commands/workflows/git/add.rb +65 -0
- data/lib/amp/commands/commands/workflows/git/copy.rb +27 -0
- data/lib/amp/commands/commands/workflows/git/mv.rb +23 -0
- data/lib/amp/commands/commands/workflows/git/rm.rb +60 -0
- data/lib/amp/commands/commands/workflows/hg/add.rb +53 -0
- data/lib/amp/commands/commands/workflows/hg/addremove.rb +86 -0
- data/lib/amp/commands/commands/workflows/hg/annotate.rb +46 -0
- data/lib/amp/commands/commands/workflows/hg/archive.rb +126 -0
- data/lib/amp/commands/commands/workflows/hg/branch.rb +28 -0
- data/lib/amp/commands/commands/workflows/hg/branches.rb +30 -0
- data/lib/amp/commands/commands/workflows/hg/bundle.rb +115 -0
- data/lib/amp/commands/commands/workflows/hg/clone.rb +95 -0
- data/lib/amp/commands/commands/workflows/hg/commit.rb +42 -0
- data/lib/amp/commands/commands/workflows/hg/copy.rb +31 -0
- data/lib/amp/commands/commands/workflows/hg/debug/dirstate.rb +32 -0
- data/lib/amp/commands/commands/workflows/hg/debug/index.rb +36 -0
- data/lib/amp/commands/commands/workflows/hg/default.rb +9 -0
- data/lib/amp/commands/commands/workflows/hg/diff.rb +30 -0
- data/lib/amp/commands/commands/workflows/hg/forget.rb +11 -0
- data/lib/amp/commands/commands/workflows/hg/heads.rb +25 -0
- data/lib/amp/commands/commands/workflows/hg/identify.rb +23 -0
- data/lib/amp/commands/commands/workflows/hg/import.rb +135 -0
- data/lib/amp/commands/commands/workflows/hg/incoming.rb +85 -0
- data/lib/amp/commands/commands/workflows/hg/info.rb +18 -0
- data/lib/amp/commands/commands/workflows/hg/log.rb +21 -0
- data/lib/amp/commands/commands/workflows/hg/manifest.rb +13 -0
- data/lib/amp/commands/commands/workflows/hg/merge.rb +53 -0
- data/lib/amp/commands/commands/workflows/hg/move.rb +28 -0
- data/lib/amp/commands/commands/workflows/hg/outgoing.rb +61 -0
- data/lib/amp/commands/commands/workflows/hg/pull.rb +74 -0
- data/lib/amp/commands/commands/workflows/hg/push.rb +20 -0
- data/lib/amp/commands/commands/workflows/hg/remove.rb +45 -0
- data/lib/amp/commands/commands/workflows/hg/resolve.rb +83 -0
- data/lib/amp/commands/commands/workflows/hg/revert.rb +53 -0
- data/lib/amp/commands/commands/workflows/hg/root.rb +13 -0
- data/lib/amp/commands/commands/workflows/hg/serve.rb +38 -0
- data/lib/amp/commands/commands/workflows/hg/status.rb +116 -0
- data/lib/amp/commands/commands/workflows/hg/tag.rb +69 -0
- data/lib/amp/commands/commands/workflows/hg/tags.rb +27 -0
- data/lib/amp/commands/commands/workflows/hg/tip.rb +13 -0
- data/lib/amp/commands/commands/workflows/hg/update.rb +27 -0
- data/lib/amp/commands/commands/workflows/hg/verify.rb +9 -0
- data/lib/amp/commands/commands/workflows/hg/view.rb +36 -0
- data/lib/amp/commands/dispatch.rb +181 -0
- data/lib/amp/commands/hooks.rb +81 -0
- data/lib/amp/dependencies/amp_support.rb +1 -0
- data/lib/amp/dependencies/amp_support/ruby_amp_support.rb +103 -0
- data/lib/amp/dependencies/minitar.rb +979 -0
- data/lib/amp/dependencies/priority_queue.rb +18 -0
- data/lib/amp/dependencies/priority_queue/c_priority_queue.rb +1 -0
- data/lib/amp/dependencies/priority_queue/poor_priority_queue.rb +46 -0
- data/lib/amp/dependencies/priority_queue/ruby_priority_queue.rb +525 -0
- data/lib/amp/dependencies/python_config.rb +211 -0
- data/lib/amp/dependencies/trollop.rb +713 -0
- data/lib/amp/dependencies/zip/ioextras.rb +155 -0
- data/lib/amp/dependencies/zip/stdrubyext.rb +111 -0
- data/lib/amp/dependencies/zip/tempfile_bugfixed.rb +186 -0
- data/lib/amp/dependencies/zip/zip.rb +1850 -0
- data/lib/amp/dependencies/zip/zipfilesystem.rb +609 -0
- data/lib/amp/dependencies/zip/ziprequire.rb +90 -0
- data/lib/amp/encoding/base85.rb +97 -0
- data/lib/amp/encoding/binary_diff.rb +82 -0
- data/lib/amp/encoding/difflib.rb +166 -0
- data/lib/amp/encoding/mercurial_diff.rb +378 -0
- data/lib/amp/encoding/mercurial_patch.rb +1 -0
- data/lib/amp/encoding/patch.rb +292 -0
- data/lib/amp/encoding/pure_ruby/ruby_mercurial_patch.rb +123 -0
- data/lib/amp/extensions/ditz.rb +41 -0
- data/lib/amp/extensions/lighthouse.rb +167 -0
- data/lib/amp/graphs/ancestor.rb +147 -0
- data/lib/amp/graphs/copies.rb +261 -0
- data/lib/amp/merges/merge_state.rb +164 -0
- data/lib/amp/merges/merge_ui.rb +322 -0
- data/lib/amp/merges/simple_merge.rb +450 -0
- data/lib/amp/profiling_hacks.rb +36 -0
- data/lib/amp/repository/branch_manager.rb +234 -0
- data/lib/amp/repository/dir_state.rb +950 -0
- data/lib/amp/repository/journal.rb +203 -0
- data/lib/amp/repository/lock.rb +207 -0
- data/lib/amp/repository/repositories/bundle_repository.rb +214 -0
- data/lib/amp/repository/repositories/http_repository.rb +377 -0
- data/lib/amp/repository/repositories/local_repository.rb +2661 -0
- data/lib/amp/repository/repository.rb +94 -0
- data/lib/amp/repository/store.rb +485 -0
- data/lib/amp/repository/tag_manager.rb +319 -0
- data/lib/amp/repository/updatable.rb +532 -0
- data/lib/amp/repository/verification.rb +431 -0
- data/lib/amp/repository/versioned_file.rb +475 -0
- data/lib/amp/revlogs/bundle_revlogs.rb +246 -0
- data/lib/amp/revlogs/changegroup.rb +217 -0
- data/lib/amp/revlogs/changelog.rb +338 -0
- data/lib/amp/revlogs/changeset.rb +521 -0
- data/lib/amp/revlogs/file_log.rb +165 -0
- data/lib/amp/revlogs/index.rb +493 -0
- data/lib/amp/revlogs/manifest.rb +195 -0
- data/lib/amp/revlogs/node.rb +18 -0
- data/lib/amp/revlogs/revlog.rb +1032 -0
- data/lib/amp/revlogs/revlog_support.rb +126 -0
- data/lib/amp/server/amp_user.rb +44 -0
- data/lib/amp/server/extension/amp_extension.rb +396 -0
- data/lib/amp/server/extension/authorization.rb +201 -0
- data/lib/amp/server/fancy_http_server.rb +252 -0
- data/lib/amp/server/fancy_views/_browser.haml +28 -0
- data/lib/amp/server/fancy_views/_diff_file.haml +13 -0
- data/lib/amp/server/fancy_views/_navbar.haml +17 -0
- data/lib/amp/server/fancy_views/changeset.haml +31 -0
- data/lib/amp/server/fancy_views/commits.haml +32 -0
- data/lib/amp/server/fancy_views/file.haml +35 -0
- data/lib/amp/server/fancy_views/file_diff.haml +23 -0
- data/lib/amp/server/fancy_views/harshcss/all_hallows_eve.css +72 -0
- data/lib/amp/server/fancy_views/harshcss/amy.css +147 -0
- data/lib/amp/server/fancy_views/harshcss/twilight.css +138 -0
- data/lib/amp/server/fancy_views/stylesheet.sass +175 -0
- data/lib/amp/server/http_server.rb +140 -0
- data/lib/amp/server/repo_user_management.rb +287 -0
- data/lib/amp/support/amp_config.rb +164 -0
- data/lib/amp/support/amp_ui.rb +287 -0
- data/lib/amp/support/docs.rb +54 -0
- data/lib/amp/support/generator.rb +78 -0
- data/lib/amp/support/ignore.rb +144 -0
- data/lib/amp/support/loaders.rb +93 -0
- data/lib/amp/support/logger.rb +103 -0
- data/lib/amp/support/match.rb +151 -0
- data/lib/amp/support/multi_io.rb +87 -0
- data/lib/amp/support/openers.rb +121 -0
- data/lib/amp/support/ruby_19_compatibility.rb +66 -0
- data/lib/amp/support/support.rb +1095 -0
- data/lib/amp/templates/blank.commit.erb +23 -0
- data/lib/amp/templates/blank.log.erb +18 -0
- data/lib/amp/templates/default.commit.erb +23 -0
- data/lib/amp/templates/default.log.erb +26 -0
- data/lib/amp/templates/template.rb +165 -0
- data/site/Rakefile +24 -0
- data/site/src/about/ampfile.haml +57 -0
- data/site/src/about/commands.haml +106 -0
- data/site/src/about/index.haml +33 -0
- data/site/src/about/performance.haml +31 -0
- data/site/src/about/workflows.haml +34 -0
- data/site/src/contribute/index.haml +65 -0
- data/site/src/contribute/style.haml +297 -0
- data/site/src/css/active4d.css +114 -0
- data/site/src/css/all_hallows_eve.css +72 -0
- data/site/src/css/all_themes.css +3299 -0
- data/site/src/css/amp.css +260 -0
- data/site/src/css/amy.css +147 -0
- data/site/src/css/blackboard.css +88 -0
- data/site/src/css/brilliance_black.css +605 -0
- data/site/src/css/brilliance_dull.css +599 -0
- data/site/src/css/cobalt.css +149 -0
- data/site/src/css/cur_amp.css +185 -0
- data/site/src/css/dawn.css +121 -0
- data/site/src/css/eiffel.css +121 -0
- data/site/src/css/espresso_libre.css +109 -0
- data/site/src/css/idle.css +62 -0
- data/site/src/css/iplastic.css +80 -0
- data/site/src/css/lazy.css +73 -0
- data/site/src/css/mac_classic.css +123 -0
- data/site/src/css/magicwb_amiga.css +104 -0
- data/site/src/css/pastels_on_dark.css +188 -0
- data/site/src/css/reset.css +55 -0
- data/site/src/css/slush_poppies.css +85 -0
- data/site/src/css/spacecadet.css +51 -0
- data/site/src/css/sunburst.css +180 -0
- data/site/src/css/twilight.css +137 -0
- data/site/src/css/zenburnesque.css +91 -0
- data/site/src/get/index.haml +32 -0
- data/site/src/helpers.rb +121 -0
- data/site/src/images/amp_logo.png +0 -0
- data/site/src/images/carbonica.png +0 -0
- data/site/src/images/revolution.png +0 -0
- data/site/src/images/tab-bg.png +0 -0
- data/site/src/images/tab-sliding-left.png +0 -0
- data/site/src/images/tab-sliding-right.png +0 -0
- data/site/src/include/_footer.haml +22 -0
- data/site/src/include/_header.haml +17 -0
- data/site/src/index.haml +104 -0
- data/site/src/learn/index.haml +46 -0
- data/site/src/scripts/jquery-1.3.2.min.js +19 -0
- data/site/src/scripts/jquery.cookie.js +96 -0
- data/tasks/stats.rake +155 -0
- data/tasks/yard.rake +171 -0
- data/test/dirstate_tests/dirstate +0 -0
- data/test/dirstate_tests/hgrc +5 -0
- data/test/dirstate_tests/test_dir_state.rb +192 -0
- data/test/functional_tests/resources/.hgignore +2 -0
- data/test/functional_tests/resources/STYLE.txt +25 -0
- data/test/functional_tests/resources/command.rb +372 -0
- data/test/functional_tests/resources/commands/annotate.rb +57 -0
- data/test/functional_tests/resources/commands/experimental/lolcats.rb +17 -0
- data/test/functional_tests/resources/commands/heads.rb +22 -0
- data/test/functional_tests/resources/commands/manifest.rb +12 -0
- data/test/functional_tests/resources/commands/status.rb +90 -0
- data/test/functional_tests/resources/version2/.hgignore +5 -0
- data/test/functional_tests/resources/version2/STYLE.txt +25 -0
- data/test/functional_tests/resources/version2/command.rb +372 -0
- data/test/functional_tests/resources/version2/commands/annotate.rb +45 -0
- data/test/functional_tests/resources/version2/commands/experimental/lolcats.rb +17 -0
- data/test/functional_tests/resources/version2/commands/heads.rb +22 -0
- data/test/functional_tests/resources/version2/commands/manifest.rb +12 -0
- data/test/functional_tests/resources/version2/commands/status.rb +90 -0
- data/test/functional_tests/resources/version3/.hgignore +5 -0
- data/test/functional_tests/resources/version3/STYLE.txt +31 -0
- data/test/functional_tests/resources/version3/command.rb +376 -0
- data/test/functional_tests/resources/version3/commands/annotate.rb +45 -0
- data/test/functional_tests/resources/version3/commands/experimental/lolcats.rb +17 -0
- data/test/functional_tests/resources/version3/commands/heads.rb +22 -0
- data/test/functional_tests/resources/version3/commands/manifest.rb +12 -0
- data/test/functional_tests/resources/version3/commands/status.rb +90 -0
- data/test/functional_tests/resources/version4/.hgignore +5 -0
- data/test/functional_tests/resources/version4/STYLE.txt +31 -0
- data/test/functional_tests/resources/version4/command.rb +376 -0
- data/test/functional_tests/resources/version4/commands/experimental/lolcats.rb +17 -0
- data/test/functional_tests/resources/version4/commands/heads.rb +22 -0
- data/test/functional_tests/resources/version4/commands/manifest.rb +12 -0
- data/test/functional_tests/resources/version4/commands/stats.rb +25 -0
- data/test/functional_tests/resources/version4/commands/status.rb +90 -0
- data/test/functional_tests/resources/version5_1/.hgignore +5 -0
- data/test/functional_tests/resources/version5_1/STYLE.txt +2 -0
- data/test/functional_tests/resources/version5_1/command.rb +374 -0
- data/test/functional_tests/resources/version5_1/commands/experimental/lolcats.rb +17 -0
- data/test/functional_tests/resources/version5_1/commands/heads.rb +22 -0
- data/test/functional_tests/resources/version5_1/commands/manifest.rb +12 -0
- data/test/functional_tests/resources/version5_1/commands/stats.rb +25 -0
- data/test/functional_tests/resources/version5_1/commands/status.rb +90 -0
- data/test/functional_tests/resources/version5_2/.hgignore +5 -0
- data/test/functional_tests/resources/version5_2/STYLE.txt +14 -0
- data/test/functional_tests/resources/version5_2/command.rb +376 -0
- data/test/functional_tests/resources/version5_2/commands/experimental/lolcats.rb +17 -0
- data/test/functional_tests/resources/version5_2/commands/manifest.rb +12 -0
- data/test/functional_tests/resources/version5_2/commands/newz.rb +12 -0
- data/test/functional_tests/resources/version5_2/commands/stats.rb +25 -0
- data/test/functional_tests/resources/version5_2/commands/status.rb +90 -0
- data/test/functional_tests/test_functional.rb +604 -0
- data/test/localrepo_tests/test_local_repo.rb +121 -0
- data/test/localrepo_tests/testrepo.tar.gz +0 -0
- data/test/manifest_tests/00manifest.i +0 -0
- data/test/manifest_tests/test_manifest.rb +72 -0
- data/test/merge_tests/base.txt +10 -0
- data/test/merge_tests/expected.local.txt +16 -0
- data/test/merge_tests/local.txt +11 -0
- data/test/merge_tests/remote.txt +11 -0
- data/test/merge_tests/test_merge.rb +26 -0
- data/test/revlog_tests/00changelog.i +0 -0
- data/test/revlog_tests/revision_added_changelog.i +0 -0
- data/test/revlog_tests/test_adding_index.i +0 -0
- data/test/revlog_tests/test_revlog.rb +333 -0
- data/test/revlog_tests/testindex.i +0 -0
- data/test/store_tests/store.tar.gz +0 -0
- data/test/store_tests/test_fncache_store.rb +122 -0
- data/test/test_amp.rb +9 -0
- data/test/test_base85.rb +14 -0
- data/test/test_bdiff.rb +42 -0
- data/test/test_commands.rb +122 -0
- data/test/test_difflib.rb +50 -0
- data/test/test_helper.rb +15 -0
- data/test/test_journal.rb +29 -0
- data/test/test_match.rb +134 -0
- data/test/test_mdiff.rb +74 -0
- data/test/test_mpatch.rb +14 -0
- data/test/test_support.rb +24 -0
- metadata +385 -0
@@ -0,0 +1,507 @@
|
|
1
|
+
require 'amp/commands/command_support.rb'
|
2
|
+
|
3
|
+
module Amp
|
4
|
+
|
5
|
+
##
|
6
|
+
# Represents a command within the Amp system. Simply instantiating a new
|
7
|
+
# command will make it available to the Amp executable. You configure the
|
8
|
+
# command by filling out a block in the command's initializer.
|
9
|
+
# @example
|
10
|
+
# Command.new "add" do |c|
|
11
|
+
# c.workflow :hg
|
12
|
+
# c.opt :include, "Paths to include",
|
13
|
+
# :options => {:short => "-I", :multi => true}
|
14
|
+
# c.opt :print_names, :desc => "Print the filenames",
|
15
|
+
# :options => {:short => "-p" ,
|
16
|
+
# :default => false,
|
17
|
+
# :type => :boolean}
|
18
|
+
# c.on_run do |options, arguments|
|
19
|
+
# if options[:print_names]
|
20
|
+
# arguments.each do |filename|
|
21
|
+
# puts filename
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
# c.help "This is the help text when the user runs `amp help add`"
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
class Command
|
29
|
+
include CommandSupport
|
30
|
+
|
31
|
+
# The current namespace to append to any new commands
|
32
|
+
# Not thread-safe at all
|
33
|
+
@current_namespaces = []
|
34
|
+
|
35
|
+
# All the commands registered in the system
|
36
|
+
@all_commands = {}
|
37
|
+
|
38
|
+
# Synonyms for commands. Used as a backup.
|
39
|
+
@all_synonyms = {}
|
40
|
+
|
41
|
+
# Workflows for splitting up commands into groups.
|
42
|
+
# The hash will automatically fill slots with empty hashes
|
43
|
+
# upon reads if they are empty.
|
44
|
+
#
|
45
|
+
# Workflows are doubly linked, in that the cvar +self.class.workflows+ keeps track of
|
46
|
+
# what commands belong to it, and the commands themselves keep track of which
|
47
|
+
# workflows they belong to.
|
48
|
+
@workflows = Hash.new {|h, k| h[k] = {} }
|
49
|
+
|
50
|
+
# These are options that all commands support. Allows the user to put
|
51
|
+
# them after the subcommand.
|
52
|
+
GLOBAL_OPTIONS = []
|
53
|
+
# {:name => :verbose, :desc => "Verbose output", :options => {:short => "-v"}}
|
54
|
+
|
55
|
+
class << self
|
56
|
+
|
57
|
+
attr_reader :current_namespaces
|
58
|
+
|
59
|
+
##
|
60
|
+
# Returns all of the commands registered in the system.
|
61
|
+
#
|
62
|
+
# @return [Hash<Symbol => Amp::Command>] the commands, keyed by command name as a string
|
63
|
+
attr_reader :all_commands
|
64
|
+
|
65
|
+
##
|
66
|
+
# Returns all the synonyms registered in the system.
|
67
|
+
#
|
68
|
+
# @return [Hash<Symbol => Amp::Command>] the synonyms, keyed by the synonym as a string
|
69
|
+
attr_reader :all_synonyms
|
70
|
+
attr_reader :workflows
|
71
|
+
|
72
|
+
##
|
73
|
+
# Appends the given namespace to the active namespace for new commands.
|
74
|
+
#
|
75
|
+
# @param [String, #to_s] namespace the new namespace to add
|
76
|
+
def use_namespace(namespace)
|
77
|
+
current_namespaces.push namespace
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Removes one namespace from the active namespaces for new commands
|
82
|
+
def pop_namespace
|
83
|
+
current_namespaces.pop
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# Returns all commands and synonyms registered in the system.
|
88
|
+
# The commands are merged into the synonyms so that any synonym with
|
89
|
+
# the same name as a command will be overwritten in the hash.
|
90
|
+
#
|
91
|
+
# @return [Hash<Symbol => Amp::Command>] the commands and synonyms,
|
92
|
+
# keyed by command name as a string
|
93
|
+
def all
|
94
|
+
all_synonyms.merge all_commands
|
95
|
+
end
|
96
|
+
|
97
|
+
##
|
98
|
+
# Returns all commands and synonyms registered in the system for a
|
99
|
+
# given workflow. The ":all" workflow is automatically merged in, as well.
|
100
|
+
#
|
101
|
+
# @param [Symbol] workflow the workflow whose commands we need
|
102
|
+
# @return [Hash<Symbol => Amp::Command>] the commands and synonyms for the
|
103
|
+
# workflow (and all global commands), keyed by command name as a string
|
104
|
+
def all_for_workflow(flow, synonyms=true)
|
105
|
+
flow = flow.to_sym
|
106
|
+
|
107
|
+
cmds = workflows[flow].merge workflows[:all]
|
108
|
+
|
109
|
+
if synonyms
|
110
|
+
# because there is no way to view all synonyms with workflow +flow+,
|
111
|
+
# we have to work bottom up (hence the doubly linked aspect for commands,
|
112
|
+
# which is reduced to singly linked)
|
113
|
+
syns = all_synonyms.select {|k, v| v.workflows.include? flow }
|
114
|
+
syns = syns.to_hash
|
115
|
+
else
|
116
|
+
syns = {}
|
117
|
+
end
|
118
|
+
|
119
|
+
syns.merge cmds
|
120
|
+
end
|
121
|
+
|
122
|
+
##
|
123
|
+
# Gets a specific command, for a given workflow. This is necessary because it
|
124
|
+
# will be expected that 2 different workflows have a command with the same name
|
125
|
+
# (such as "move").
|
126
|
+
#
|
127
|
+
# @param [String, Symbol] cmd the command to look up
|
128
|
+
# @param [Symbol] the workflow to use for the lookup
|
129
|
+
# @return [Amp::Command] the command for the given name and workflow
|
130
|
+
def command_for_workflow(cmd, flow)
|
131
|
+
all_for_workflow(flow)[cmd.to_sym]
|
132
|
+
end
|
133
|
+
|
134
|
+
##
|
135
|
+
# Returns all of the commands registered in the system.
|
136
|
+
#
|
137
|
+
# @return [Hash<Symbol => Amp::Command>, NilClass] the commands, keyed by
|
138
|
+
# command name as a symbol. returns nil if nothing is found
|
139
|
+
def [](arg)
|
140
|
+
all[arg.to_sym]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Command-specific command-line options
|
145
|
+
attr_accessor :options
|
146
|
+
# The name of the command (eg 'add', 'init')
|
147
|
+
attr_accessor :name
|
148
|
+
# Short, 1-line description of the command
|
149
|
+
attr_accessor :description
|
150
|
+
# The Trollop parser
|
151
|
+
attr_accessor :parser
|
152
|
+
|
153
|
+
##
|
154
|
+
# Creates a command in the Amp system. Simply instantiating a new
|
155
|
+
# command will make it available to the Amp executable. You configure the
|
156
|
+
# command by filling out a block in the command's initializer.
|
157
|
+
#
|
158
|
+
# @example
|
159
|
+
# Command.new("add") do |c|
|
160
|
+
# c.opt :include, "Paths to include",
|
161
|
+
# :options => {:short => "-I", :multi => true}
|
162
|
+
# c.opt :print_names, :desc => "Print the filenames",
|
163
|
+
# :options => {:short => "-p", :default => false,
|
164
|
+
# :type => :boolean}
|
165
|
+
# c.on_run do |options, arguments|
|
166
|
+
# puts "silly!"
|
167
|
+
# end
|
168
|
+
# end
|
169
|
+
# @param name the name of the command that the user will use to call
|
170
|
+
# the command
|
171
|
+
# @param &block a block of code where you can configure the command
|
172
|
+
# @yield This block configures the command. Set up options, add an on_run
|
173
|
+
# handler, and so on.
|
174
|
+
# @yieldparam The command itself - it is yielded so you can modify it.
|
175
|
+
def initialize(name, require_new = false)
|
176
|
+
# so that you can do additions to commands, just like ammending rake tasks
|
177
|
+
full_name = (self.class.current_namespaces + [name]).join(":")
|
178
|
+
name = full_name.to_sym
|
179
|
+
if self.class.all_commands[name]
|
180
|
+
yield self.class.all_commands[name] if block_given?
|
181
|
+
return self.class.all_commands[name]
|
182
|
+
end
|
183
|
+
|
184
|
+
@name = name
|
185
|
+
@help = ""
|
186
|
+
@options = []
|
187
|
+
self.class.all_commands[name] = self
|
188
|
+
@before = []
|
189
|
+
@after = []
|
190
|
+
|
191
|
+
@workflows = []
|
192
|
+
@synonyms = []
|
193
|
+
yield(self) if block_given?
|
194
|
+
workflow :all if @workflows.empty?
|
195
|
+
@options += GLOBAL_OPTIONS
|
196
|
+
end
|
197
|
+
|
198
|
+
##
|
199
|
+
# Adds an command-line option to the command.
|
200
|
+
#
|
201
|
+
# @param name the name of the command the user will type to run it
|
202
|
+
# @param desc the short, one-line description of the command
|
203
|
+
# @param options the options that configure the command-line option
|
204
|
+
# (too meta? sorry!)
|
205
|
+
# @option [String] options :short (nil) the short version of the option
|
206
|
+
# (e.g. "-I")
|
207
|
+
# @option [String] options :default (nil) the default value of the option.
|
208
|
+
# @option [Symbol] options :type (:string) the type of the option. Allows
|
209
|
+
# you to force Integer or URL matches.
|
210
|
+
# @option [Boolean] options :multi (false) can this option take multiple
|
211
|
+
# values?
|
212
|
+
def opt(name, desc='', options={})
|
213
|
+
@options << {:name => name, :desc => desc, :options => options}
|
214
|
+
end
|
215
|
+
alias_method :add_opt, :opt
|
216
|
+
|
217
|
+
##
|
218
|
+
# Override a default value for a command option. Useful for user-provided
|
219
|
+
# ampfiles.
|
220
|
+
#
|
221
|
+
# @example This example will make `amp status` default to mercurial-style
|
222
|
+
# output, instead of amp's colorful, easy-to-read output.
|
223
|
+
# command :status do |c|
|
224
|
+
# default :hg, true
|
225
|
+
# default :"no-color", true
|
226
|
+
# end
|
227
|
+
# @param [Symbol, #to_sym] opt the option to modify. Can be symbol or string.
|
228
|
+
# @param value the new default value for the option
|
229
|
+
def default(opt, value)
|
230
|
+
opt = opt.to_sym
|
231
|
+
the_opt = @options.select {|o| o[:name] == opt}.first
|
232
|
+
if the_opt
|
233
|
+
the_opt[:options][:default] = value
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
##
|
238
|
+
# This method is how you set what the command does when it is run.
|
239
|
+
#
|
240
|
+
# @param &block the code to run when the command runs
|
241
|
+
# @yield The code to run when the command is executed, after options
|
242
|
+
# are prepared.
|
243
|
+
# @yieldparam options The options that the dispatcher has prepared for
|
244
|
+
# the command. Includes global and local.
|
245
|
+
# @yieldparam arguments All arguments passed to the command, after
|
246
|
+
# the options.
|
247
|
+
# @example
|
248
|
+
# Command.new("email_news") do |c|
|
249
|
+
# c.on_run do |options, arguments|
|
250
|
+
# arguments.each do |email_address|
|
251
|
+
# send_some_email(options[:email_subject],email_address)
|
252
|
+
# end
|
253
|
+
# end
|
254
|
+
# end
|
255
|
+
def on_run(&block)
|
256
|
+
@code = proc(&block) # this way we have the ability to do `return`
|
257
|
+
end
|
258
|
+
|
259
|
+
##
|
260
|
+
# This method lets you set a synonym (or synonyms) for this command.
|
261
|
+
# For example, the "remove" command has the synonym "rm". Example:
|
262
|
+
# command :remove do |c|
|
263
|
+
# c.synonym :rm, :destroy, :nuke
|
264
|
+
# end
|
265
|
+
# then you can do
|
266
|
+
# amp nuke badfile.rb
|
267
|
+
def synonym(*args)
|
268
|
+
args.each do |arg|
|
269
|
+
@synonyms << arg
|
270
|
+
self.class.all_synonyms[arg.to_sym] = self
|
271
|
+
end
|
272
|
+
end
|
273
|
+
alias_method :synonyms, :synonym
|
274
|
+
|
275
|
+
##
|
276
|
+
# Specifies a workflow that may access this command. Workflows are
|
277
|
+
# groups of commands, pure and simple. If the user has no specified
|
278
|
+
# workflow, the mercurial workflow is used by default.
|
279
|
+
def workflow(*args)
|
280
|
+
if args.any? # unless args.empty?
|
281
|
+
args.each do |arg|
|
282
|
+
self.class.workflows[arg][self.name.to_sym] = self # register globally
|
283
|
+
@workflows << arg # register locally
|
284
|
+
end
|
285
|
+
else
|
286
|
+
@workflows
|
287
|
+
end
|
288
|
+
end
|
289
|
+
alias_method :workflows, :workflow
|
290
|
+
|
291
|
+
##
|
292
|
+
# This returns the list of actions to run before the command, in order (first
|
293
|
+
# ones are run first). You can modify this array in any way you choose, and
|
294
|
+
# it is run _before_ the command is run.
|
295
|
+
#
|
296
|
+
# @yield Extra code to run before the command is executed, after options
|
297
|
+
# are prepared.
|
298
|
+
# @yieldparam options The options that the dispatcher has prepared
|
299
|
+
# for the command. Includes global and local.
|
300
|
+
# @yieldparam arguments All arguments passed to the command, after the options.
|
301
|
+
# @return [Hash] an array of strings and blocks. Strings are assumed to
|
302
|
+
# be command names and blocks are pieces of code to be run.
|
303
|
+
def before(*args, &block)
|
304
|
+
args.each do |arg|
|
305
|
+
@before << proc {|opts, args| Amp::Command[arg.to_sym].run(opts, args) }
|
306
|
+
end
|
307
|
+
|
308
|
+
@before << block if block
|
309
|
+
@before
|
310
|
+
end
|
311
|
+
##
|
312
|
+
# This returns the list of actions to run after the command, in order (first
|
313
|
+
# ones are run first). You can modify this array in any way you choose, and
|
314
|
+
# it is run _after_ the command is run.
|
315
|
+
#
|
316
|
+
# @yield Extra code to run after the command is executed, after options are prepared.
|
317
|
+
# @yieldparam options The options that the dispatcher has prepared for the command.
|
318
|
+
# Includes global and local.
|
319
|
+
# @yieldparam arguments All arguments passed to the command, after the options.
|
320
|
+
# @return [Hash] an array of strings and blocks. Strings are assumed to be command
|
321
|
+
# names and blocks are pieces of code to be run.
|
322
|
+
def after(*args, &block)
|
323
|
+
args.each do |arg|
|
324
|
+
@after << proc {|opts, args| Amp::Command[arg.to_sym].run(opts, args) }
|
325
|
+
end
|
326
|
+
|
327
|
+
@after << block if block
|
328
|
+
@after
|
329
|
+
end
|
330
|
+
|
331
|
+
##
|
332
|
+
# The one-line description of the command. This is the first line
|
333
|
+
# of the help text. If no argument is passed, then the desription
|
334
|
+
# is returned. If an argument is passed, it will be set to be the
|
335
|
+
# first line of the help text.
|
336
|
+
#
|
337
|
+
# @example cmd.desc # => "This command is useless."
|
338
|
+
# @param [String, nil] str the help text to set
|
339
|
+
def desc(str=nil)
|
340
|
+
str ? @help = "#{str}\n\n#{@help}" : @help.split("\n").first
|
341
|
+
end
|
342
|
+
|
343
|
+
##
|
344
|
+
# Trollop's help info for the command
|
345
|
+
def educate
|
346
|
+
@parser ? @parser.educate : ''
|
347
|
+
end
|
348
|
+
alias_method :education, :educate
|
349
|
+
|
350
|
+
##
|
351
|
+
# Sets the command to not laod a repository when run. Useful for purely
|
352
|
+
# informational commands (such as version) or initializing a new
|
353
|
+
# repository.
|
354
|
+
def no_repo
|
355
|
+
NO_REPO_ALLOWED[@name] = true
|
356
|
+
end
|
357
|
+
|
358
|
+
# @see no_repo
|
359
|
+
def no_repo=(value)
|
360
|
+
NO_REPO_ALLOWED[@name] = value
|
361
|
+
end
|
362
|
+
|
363
|
+
##
|
364
|
+
# Sets the command to not require a repository to run, but try to load one.
|
365
|
+
# Used, for example, for the templates command, which sometimes stores
|
366
|
+
# information in the local repository.
|
367
|
+
def maybe_repo
|
368
|
+
MAYBE_REPO_ALLOWED[@name] = true
|
369
|
+
end
|
370
|
+
|
371
|
+
# @see no_repo
|
372
|
+
def maybe_repo=(value)
|
373
|
+
MAYBE_REPO_ALLOWED[@name] = value
|
374
|
+
end
|
375
|
+
|
376
|
+
##
|
377
|
+
# Sets the help text for the command. This can be a very long string,
|
378
|
+
# as it is what the user sees when they type `amp help +name+`
|
379
|
+
#
|
380
|
+
# @param str the help text to set
|
381
|
+
# @example cmd.help %Q{
|
382
|
+
# Big help text!
|
383
|
+
# }
|
384
|
+
def help(str=nil)
|
385
|
+
str ? @help << str : @help
|
386
|
+
end
|
387
|
+
|
388
|
+
##
|
389
|
+
# Sets the help text for the command. This can be a very long string,
|
390
|
+
# as it is what the user sees when they type `amp help +name+`
|
391
|
+
#
|
392
|
+
# @param str the help text to set
|
393
|
+
alias :help= :help
|
394
|
+
|
395
|
+
##
|
396
|
+
# Parses the commands from the command line using Trollop. You probably
|
397
|
+
# shouldn't override this method, but if you have good reason, go for it.
|
398
|
+
#
|
399
|
+
# @return [Hash<Symbol => Object>] The parsed command-line options
|
400
|
+
def collect_options
|
401
|
+
options = @options # hack to get around the fact that
|
402
|
+
help = @help # Trollop uses instance eval
|
403
|
+
|
404
|
+
ret = Trollop::options do
|
405
|
+
banner help
|
406
|
+
|
407
|
+
# we can't use @options here because Trollop::options uses instance_eval
|
408
|
+
# therefore we have to use a local to cheat death^H^H^H^H^Hinstance_eval
|
409
|
+
options.each do |option|
|
410
|
+
opt option[:name], option[:desc], option[:options]
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
@parser = ret.pop
|
415
|
+
ret.first
|
416
|
+
end
|
417
|
+
|
418
|
+
def inspect
|
419
|
+
"#<Amp::Command #{name}>"
|
420
|
+
end
|
421
|
+
|
422
|
+
##
|
423
|
+
# Adds a namespace to the name of the command. This extra method is
|
424
|
+
# needed because many class variables expect this command based on its name -
|
425
|
+
# if we don't update these, then our entire program will expect a
|
426
|
+
# command with the old name. Not cool.
|
427
|
+
#
|
428
|
+
# @param [String] ns the namespace to put in front of the command's name
|
429
|
+
def add_namespace(ns)
|
430
|
+
to = "#{ns}:#{name}".to_sym
|
431
|
+
if self.class.all_commands[name] == self
|
432
|
+
self.class.all_commands[to] = self.class.all_commands.delete name
|
433
|
+
end
|
434
|
+
@workflows.each do |flow|
|
435
|
+
if self.class.workflows[flow][name] == self
|
436
|
+
self.class.workflows[flow][to] = self.class.workflows[flow].delete name
|
437
|
+
end
|
438
|
+
end
|
439
|
+
@synonyms.each do |syn|
|
440
|
+
if self.class.all_synonyms[syn] == self
|
441
|
+
self.class.all_synonyms["#{ns}:#{syn}"] = self.class.all_synonyms.delete syn
|
442
|
+
end
|
443
|
+
end
|
444
|
+
@name = to
|
445
|
+
end
|
446
|
+
|
447
|
+
##
|
448
|
+
# Called by the dispatcher to execute the command. You really don't need to
|
449
|
+
# override this. The `$break` global can be set by anything, which
|
450
|
+
# will halt the chain.
|
451
|
+
#
|
452
|
+
# @param [Hash<Symbol => Object>] options The global options, merged with the command-specific
|
453
|
+
# options, as decided by the dispatcher.
|
454
|
+
# @param [Array<String>] arguments The list of arguments, passed after the options. Could
|
455
|
+
# be a filename, for example.
|
456
|
+
# @return [Amp::Command] the command being run
|
457
|
+
def run(options={}, args=[])
|
458
|
+
# run the before commands
|
459
|
+
@before.each {|cmd| result = cmd.run options, args; return if !result || $break }
|
460
|
+
|
461
|
+
@code[options, args] # and of course the actual command...
|
462
|
+
|
463
|
+
# top it off with the after commands
|
464
|
+
@after.each {|cmd| result = cmd.run options, args; return if !result || $break }
|
465
|
+
|
466
|
+
self
|
467
|
+
end
|
468
|
+
|
469
|
+
NO_REPO_ALLOWED = {}
|
470
|
+
%w(clone init help version debugcomplete debugdata debugindex
|
471
|
+
debugindexdot debugdate debuginstall debugfsinfo).each do |k|
|
472
|
+
NO_REPO_ALLOWED[k.to_sym] = true
|
473
|
+
end
|
474
|
+
|
475
|
+
MAYBE_REPO_ALLOWED = {}
|
476
|
+
%w().each do |k|
|
477
|
+
MAYBE_REPO_ALLOWED[k.to_sym] = true
|
478
|
+
end
|
479
|
+
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
483
|
+
module Amp
|
484
|
+
module KernelMethods
|
485
|
+
# shortcut
|
486
|
+
def command(name, &block)
|
487
|
+
Amp::Command.new name, &block
|
488
|
+
end
|
489
|
+
|
490
|
+
##
|
491
|
+
# Stops the command from running any further - uses the global options.
|
492
|
+
def cut!; $break = true; end
|
493
|
+
|
494
|
+
# Rake style namespacing
|
495
|
+
# After new commands are made, alter their names
|
496
|
+
# so that they're "#{namespace}:#{command}"
|
497
|
+
# NOTE: THIS IS NOT RAKE-FRIENDLY
|
498
|
+
# If you load this into a script with Rake, they will
|
499
|
+
# fight to the death and only one will have a proper namespace method!
|
500
|
+
def namespace(name)
|
501
|
+
# current commands
|
502
|
+
Amp::Command.use_namespace name.to_s
|
503
|
+
yield
|
504
|
+
Amp::Command.pop_namespace
|
505
|
+
end
|
506
|
+
end
|
507
|
+
end
|