amp 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. data/.gitignore +1 -0
  2. data/.hgignore +26 -0
  3. data/AUTHORS +2 -0
  4. data/History.txt +6 -0
  5. data/LICENSE +37 -0
  6. data/MANIFESTO +7 -0
  7. data/Manifest.txt +294 -0
  8. data/README.md +129 -0
  9. data/Rakefile +102 -0
  10. data/SCHEDULE.markdown +12 -0
  11. data/STYLE +27 -0
  12. data/TODO.markdown +149 -0
  13. data/ampfile.rb +47 -0
  14. data/bin/amp +30 -0
  15. data/bin/amp1.9 +30 -0
  16. data/ext/amp/bz2/README.txt +39 -0
  17. data/ext/amp/bz2/bz2.c +1582 -0
  18. data/ext/amp/bz2/extconf.rb +77 -0
  19. data/ext/amp/bz2/mkmf.log +29 -0
  20. data/ext/amp/mercurial_patch/extconf.rb +5 -0
  21. data/ext/amp/mercurial_patch/mpatch.c +405 -0
  22. data/ext/amp/priority_queue/extconf.rb +5 -0
  23. data/ext/amp/priority_queue/priority_queue.c +947 -0
  24. data/ext/amp/support/extconf.rb +5 -0
  25. data/ext/amp/support/support.c +250 -0
  26. data/lib/amp.rb +200 -0
  27. data/lib/amp/commands/command.rb +507 -0
  28. data/lib/amp/commands/command_support.rb +137 -0
  29. data/lib/amp/commands/commands/config.rb +143 -0
  30. data/lib/amp/commands/commands/help.rb +29 -0
  31. data/lib/amp/commands/commands/init.rb +10 -0
  32. data/lib/amp/commands/commands/templates.rb +137 -0
  33. data/lib/amp/commands/commands/version.rb +7 -0
  34. data/lib/amp/commands/commands/workflow.rb +28 -0
  35. data/lib/amp/commands/commands/workflows/git/add.rb +65 -0
  36. data/lib/amp/commands/commands/workflows/git/copy.rb +27 -0
  37. data/lib/amp/commands/commands/workflows/git/mv.rb +23 -0
  38. data/lib/amp/commands/commands/workflows/git/rm.rb +60 -0
  39. data/lib/amp/commands/commands/workflows/hg/add.rb +53 -0
  40. data/lib/amp/commands/commands/workflows/hg/addremove.rb +86 -0
  41. data/lib/amp/commands/commands/workflows/hg/annotate.rb +46 -0
  42. data/lib/amp/commands/commands/workflows/hg/archive.rb +126 -0
  43. data/lib/amp/commands/commands/workflows/hg/branch.rb +28 -0
  44. data/lib/amp/commands/commands/workflows/hg/branches.rb +30 -0
  45. data/lib/amp/commands/commands/workflows/hg/bundle.rb +115 -0
  46. data/lib/amp/commands/commands/workflows/hg/clone.rb +95 -0
  47. data/lib/amp/commands/commands/workflows/hg/commit.rb +42 -0
  48. data/lib/amp/commands/commands/workflows/hg/copy.rb +31 -0
  49. data/lib/amp/commands/commands/workflows/hg/debug/dirstate.rb +32 -0
  50. data/lib/amp/commands/commands/workflows/hg/debug/index.rb +36 -0
  51. data/lib/amp/commands/commands/workflows/hg/default.rb +9 -0
  52. data/lib/amp/commands/commands/workflows/hg/diff.rb +30 -0
  53. data/lib/amp/commands/commands/workflows/hg/forget.rb +11 -0
  54. data/lib/amp/commands/commands/workflows/hg/heads.rb +25 -0
  55. data/lib/amp/commands/commands/workflows/hg/identify.rb +23 -0
  56. data/lib/amp/commands/commands/workflows/hg/import.rb +135 -0
  57. data/lib/amp/commands/commands/workflows/hg/incoming.rb +85 -0
  58. data/lib/amp/commands/commands/workflows/hg/info.rb +18 -0
  59. data/lib/amp/commands/commands/workflows/hg/log.rb +21 -0
  60. data/lib/amp/commands/commands/workflows/hg/manifest.rb +13 -0
  61. data/lib/amp/commands/commands/workflows/hg/merge.rb +53 -0
  62. data/lib/amp/commands/commands/workflows/hg/move.rb +28 -0
  63. data/lib/amp/commands/commands/workflows/hg/outgoing.rb +61 -0
  64. data/lib/amp/commands/commands/workflows/hg/pull.rb +74 -0
  65. data/lib/amp/commands/commands/workflows/hg/push.rb +20 -0
  66. data/lib/amp/commands/commands/workflows/hg/remove.rb +45 -0
  67. data/lib/amp/commands/commands/workflows/hg/resolve.rb +83 -0
  68. data/lib/amp/commands/commands/workflows/hg/revert.rb +53 -0
  69. data/lib/amp/commands/commands/workflows/hg/root.rb +13 -0
  70. data/lib/amp/commands/commands/workflows/hg/serve.rb +38 -0
  71. data/lib/amp/commands/commands/workflows/hg/status.rb +116 -0
  72. data/lib/amp/commands/commands/workflows/hg/tag.rb +69 -0
  73. data/lib/amp/commands/commands/workflows/hg/tags.rb +27 -0
  74. data/lib/amp/commands/commands/workflows/hg/tip.rb +13 -0
  75. data/lib/amp/commands/commands/workflows/hg/update.rb +27 -0
  76. data/lib/amp/commands/commands/workflows/hg/verify.rb +9 -0
  77. data/lib/amp/commands/commands/workflows/hg/view.rb +36 -0
  78. data/lib/amp/commands/dispatch.rb +181 -0
  79. data/lib/amp/commands/hooks.rb +81 -0
  80. data/lib/amp/dependencies/amp_support.rb +1 -0
  81. data/lib/amp/dependencies/amp_support/ruby_amp_support.rb +103 -0
  82. data/lib/amp/dependencies/minitar.rb +979 -0
  83. data/lib/amp/dependencies/priority_queue.rb +18 -0
  84. data/lib/amp/dependencies/priority_queue/c_priority_queue.rb +1 -0
  85. data/lib/amp/dependencies/priority_queue/poor_priority_queue.rb +46 -0
  86. data/lib/amp/dependencies/priority_queue/ruby_priority_queue.rb +525 -0
  87. data/lib/amp/dependencies/python_config.rb +211 -0
  88. data/lib/amp/dependencies/trollop.rb +713 -0
  89. data/lib/amp/dependencies/zip/ioextras.rb +155 -0
  90. data/lib/amp/dependencies/zip/stdrubyext.rb +111 -0
  91. data/lib/amp/dependencies/zip/tempfile_bugfixed.rb +186 -0
  92. data/lib/amp/dependencies/zip/zip.rb +1850 -0
  93. data/lib/amp/dependencies/zip/zipfilesystem.rb +609 -0
  94. data/lib/amp/dependencies/zip/ziprequire.rb +90 -0
  95. data/lib/amp/encoding/base85.rb +97 -0
  96. data/lib/amp/encoding/binary_diff.rb +82 -0
  97. data/lib/amp/encoding/difflib.rb +166 -0
  98. data/lib/amp/encoding/mercurial_diff.rb +378 -0
  99. data/lib/amp/encoding/mercurial_patch.rb +1 -0
  100. data/lib/amp/encoding/patch.rb +292 -0
  101. data/lib/amp/encoding/pure_ruby/ruby_mercurial_patch.rb +123 -0
  102. data/lib/amp/extensions/ditz.rb +41 -0
  103. data/lib/amp/extensions/lighthouse.rb +167 -0
  104. data/lib/amp/graphs/ancestor.rb +147 -0
  105. data/lib/amp/graphs/copies.rb +261 -0
  106. data/lib/amp/merges/merge_state.rb +164 -0
  107. data/lib/amp/merges/merge_ui.rb +322 -0
  108. data/lib/amp/merges/simple_merge.rb +450 -0
  109. data/lib/amp/profiling_hacks.rb +36 -0
  110. data/lib/amp/repository/branch_manager.rb +234 -0
  111. data/lib/amp/repository/dir_state.rb +950 -0
  112. data/lib/amp/repository/journal.rb +203 -0
  113. data/lib/amp/repository/lock.rb +207 -0
  114. data/lib/amp/repository/repositories/bundle_repository.rb +214 -0
  115. data/lib/amp/repository/repositories/http_repository.rb +377 -0
  116. data/lib/amp/repository/repositories/local_repository.rb +2661 -0
  117. data/lib/amp/repository/repository.rb +94 -0
  118. data/lib/amp/repository/store.rb +485 -0
  119. data/lib/amp/repository/tag_manager.rb +319 -0
  120. data/lib/amp/repository/updatable.rb +532 -0
  121. data/lib/amp/repository/verification.rb +431 -0
  122. data/lib/amp/repository/versioned_file.rb +475 -0
  123. data/lib/amp/revlogs/bundle_revlogs.rb +246 -0
  124. data/lib/amp/revlogs/changegroup.rb +217 -0
  125. data/lib/amp/revlogs/changelog.rb +338 -0
  126. data/lib/amp/revlogs/changeset.rb +521 -0
  127. data/lib/amp/revlogs/file_log.rb +165 -0
  128. data/lib/amp/revlogs/index.rb +493 -0
  129. data/lib/amp/revlogs/manifest.rb +195 -0
  130. data/lib/amp/revlogs/node.rb +18 -0
  131. data/lib/amp/revlogs/revlog.rb +1032 -0
  132. data/lib/amp/revlogs/revlog_support.rb +126 -0
  133. data/lib/amp/server/amp_user.rb +44 -0
  134. data/lib/amp/server/extension/amp_extension.rb +396 -0
  135. data/lib/amp/server/extension/authorization.rb +201 -0
  136. data/lib/amp/server/fancy_http_server.rb +252 -0
  137. data/lib/amp/server/fancy_views/_browser.haml +28 -0
  138. data/lib/amp/server/fancy_views/_diff_file.haml +13 -0
  139. data/lib/amp/server/fancy_views/_navbar.haml +17 -0
  140. data/lib/amp/server/fancy_views/changeset.haml +31 -0
  141. data/lib/amp/server/fancy_views/commits.haml +32 -0
  142. data/lib/amp/server/fancy_views/file.haml +35 -0
  143. data/lib/amp/server/fancy_views/file_diff.haml +23 -0
  144. data/lib/amp/server/fancy_views/harshcss/all_hallows_eve.css +72 -0
  145. data/lib/amp/server/fancy_views/harshcss/amy.css +147 -0
  146. data/lib/amp/server/fancy_views/harshcss/twilight.css +138 -0
  147. data/lib/amp/server/fancy_views/stylesheet.sass +175 -0
  148. data/lib/amp/server/http_server.rb +140 -0
  149. data/lib/amp/server/repo_user_management.rb +287 -0
  150. data/lib/amp/support/amp_config.rb +164 -0
  151. data/lib/amp/support/amp_ui.rb +287 -0
  152. data/lib/amp/support/docs.rb +54 -0
  153. data/lib/amp/support/generator.rb +78 -0
  154. data/lib/amp/support/ignore.rb +144 -0
  155. data/lib/amp/support/loaders.rb +93 -0
  156. data/lib/amp/support/logger.rb +103 -0
  157. data/lib/amp/support/match.rb +151 -0
  158. data/lib/amp/support/multi_io.rb +87 -0
  159. data/lib/amp/support/openers.rb +121 -0
  160. data/lib/amp/support/ruby_19_compatibility.rb +66 -0
  161. data/lib/amp/support/support.rb +1095 -0
  162. data/lib/amp/templates/blank.commit.erb +23 -0
  163. data/lib/amp/templates/blank.log.erb +18 -0
  164. data/lib/amp/templates/default.commit.erb +23 -0
  165. data/lib/amp/templates/default.log.erb +26 -0
  166. data/lib/amp/templates/template.rb +165 -0
  167. data/site/Rakefile +24 -0
  168. data/site/src/about/ampfile.haml +57 -0
  169. data/site/src/about/commands.haml +106 -0
  170. data/site/src/about/index.haml +33 -0
  171. data/site/src/about/performance.haml +31 -0
  172. data/site/src/about/workflows.haml +34 -0
  173. data/site/src/contribute/index.haml +65 -0
  174. data/site/src/contribute/style.haml +297 -0
  175. data/site/src/css/active4d.css +114 -0
  176. data/site/src/css/all_hallows_eve.css +72 -0
  177. data/site/src/css/all_themes.css +3299 -0
  178. data/site/src/css/amp.css +260 -0
  179. data/site/src/css/amy.css +147 -0
  180. data/site/src/css/blackboard.css +88 -0
  181. data/site/src/css/brilliance_black.css +605 -0
  182. data/site/src/css/brilliance_dull.css +599 -0
  183. data/site/src/css/cobalt.css +149 -0
  184. data/site/src/css/cur_amp.css +185 -0
  185. data/site/src/css/dawn.css +121 -0
  186. data/site/src/css/eiffel.css +121 -0
  187. data/site/src/css/espresso_libre.css +109 -0
  188. data/site/src/css/idle.css +62 -0
  189. data/site/src/css/iplastic.css +80 -0
  190. data/site/src/css/lazy.css +73 -0
  191. data/site/src/css/mac_classic.css +123 -0
  192. data/site/src/css/magicwb_amiga.css +104 -0
  193. data/site/src/css/pastels_on_dark.css +188 -0
  194. data/site/src/css/reset.css +55 -0
  195. data/site/src/css/slush_poppies.css +85 -0
  196. data/site/src/css/spacecadet.css +51 -0
  197. data/site/src/css/sunburst.css +180 -0
  198. data/site/src/css/twilight.css +137 -0
  199. data/site/src/css/zenburnesque.css +91 -0
  200. data/site/src/get/index.haml +32 -0
  201. data/site/src/helpers.rb +121 -0
  202. data/site/src/images/amp_logo.png +0 -0
  203. data/site/src/images/carbonica.png +0 -0
  204. data/site/src/images/revolution.png +0 -0
  205. data/site/src/images/tab-bg.png +0 -0
  206. data/site/src/images/tab-sliding-left.png +0 -0
  207. data/site/src/images/tab-sliding-right.png +0 -0
  208. data/site/src/include/_footer.haml +22 -0
  209. data/site/src/include/_header.haml +17 -0
  210. data/site/src/index.haml +104 -0
  211. data/site/src/learn/index.haml +46 -0
  212. data/site/src/scripts/jquery-1.3.2.min.js +19 -0
  213. data/site/src/scripts/jquery.cookie.js +96 -0
  214. data/tasks/stats.rake +155 -0
  215. data/tasks/yard.rake +171 -0
  216. data/test/dirstate_tests/dirstate +0 -0
  217. data/test/dirstate_tests/hgrc +5 -0
  218. data/test/dirstate_tests/test_dir_state.rb +192 -0
  219. data/test/functional_tests/resources/.hgignore +2 -0
  220. data/test/functional_tests/resources/STYLE.txt +25 -0
  221. data/test/functional_tests/resources/command.rb +372 -0
  222. data/test/functional_tests/resources/commands/annotate.rb +57 -0
  223. data/test/functional_tests/resources/commands/experimental/lolcats.rb +17 -0
  224. data/test/functional_tests/resources/commands/heads.rb +22 -0
  225. data/test/functional_tests/resources/commands/manifest.rb +12 -0
  226. data/test/functional_tests/resources/commands/status.rb +90 -0
  227. data/test/functional_tests/resources/version2/.hgignore +5 -0
  228. data/test/functional_tests/resources/version2/STYLE.txt +25 -0
  229. data/test/functional_tests/resources/version2/command.rb +372 -0
  230. data/test/functional_tests/resources/version2/commands/annotate.rb +45 -0
  231. data/test/functional_tests/resources/version2/commands/experimental/lolcats.rb +17 -0
  232. data/test/functional_tests/resources/version2/commands/heads.rb +22 -0
  233. data/test/functional_tests/resources/version2/commands/manifest.rb +12 -0
  234. data/test/functional_tests/resources/version2/commands/status.rb +90 -0
  235. data/test/functional_tests/resources/version3/.hgignore +5 -0
  236. data/test/functional_tests/resources/version3/STYLE.txt +31 -0
  237. data/test/functional_tests/resources/version3/command.rb +376 -0
  238. data/test/functional_tests/resources/version3/commands/annotate.rb +45 -0
  239. data/test/functional_tests/resources/version3/commands/experimental/lolcats.rb +17 -0
  240. data/test/functional_tests/resources/version3/commands/heads.rb +22 -0
  241. data/test/functional_tests/resources/version3/commands/manifest.rb +12 -0
  242. data/test/functional_tests/resources/version3/commands/status.rb +90 -0
  243. data/test/functional_tests/resources/version4/.hgignore +5 -0
  244. data/test/functional_tests/resources/version4/STYLE.txt +31 -0
  245. data/test/functional_tests/resources/version4/command.rb +376 -0
  246. data/test/functional_tests/resources/version4/commands/experimental/lolcats.rb +17 -0
  247. data/test/functional_tests/resources/version4/commands/heads.rb +22 -0
  248. data/test/functional_tests/resources/version4/commands/manifest.rb +12 -0
  249. data/test/functional_tests/resources/version4/commands/stats.rb +25 -0
  250. data/test/functional_tests/resources/version4/commands/status.rb +90 -0
  251. data/test/functional_tests/resources/version5_1/.hgignore +5 -0
  252. data/test/functional_tests/resources/version5_1/STYLE.txt +2 -0
  253. data/test/functional_tests/resources/version5_1/command.rb +374 -0
  254. data/test/functional_tests/resources/version5_1/commands/experimental/lolcats.rb +17 -0
  255. data/test/functional_tests/resources/version5_1/commands/heads.rb +22 -0
  256. data/test/functional_tests/resources/version5_1/commands/manifest.rb +12 -0
  257. data/test/functional_tests/resources/version5_1/commands/stats.rb +25 -0
  258. data/test/functional_tests/resources/version5_1/commands/status.rb +90 -0
  259. data/test/functional_tests/resources/version5_2/.hgignore +5 -0
  260. data/test/functional_tests/resources/version5_2/STYLE.txt +14 -0
  261. data/test/functional_tests/resources/version5_2/command.rb +376 -0
  262. data/test/functional_tests/resources/version5_2/commands/experimental/lolcats.rb +17 -0
  263. data/test/functional_tests/resources/version5_2/commands/manifest.rb +12 -0
  264. data/test/functional_tests/resources/version5_2/commands/newz.rb +12 -0
  265. data/test/functional_tests/resources/version5_2/commands/stats.rb +25 -0
  266. data/test/functional_tests/resources/version5_2/commands/status.rb +90 -0
  267. data/test/functional_tests/test_functional.rb +604 -0
  268. data/test/localrepo_tests/test_local_repo.rb +121 -0
  269. data/test/localrepo_tests/testrepo.tar.gz +0 -0
  270. data/test/manifest_tests/00manifest.i +0 -0
  271. data/test/manifest_tests/test_manifest.rb +72 -0
  272. data/test/merge_tests/base.txt +10 -0
  273. data/test/merge_tests/expected.local.txt +16 -0
  274. data/test/merge_tests/local.txt +11 -0
  275. data/test/merge_tests/remote.txt +11 -0
  276. data/test/merge_tests/test_merge.rb +26 -0
  277. data/test/revlog_tests/00changelog.i +0 -0
  278. data/test/revlog_tests/revision_added_changelog.i +0 -0
  279. data/test/revlog_tests/test_adding_index.i +0 -0
  280. data/test/revlog_tests/test_revlog.rb +333 -0
  281. data/test/revlog_tests/testindex.i +0 -0
  282. data/test/store_tests/store.tar.gz +0 -0
  283. data/test/store_tests/test_fncache_store.rb +122 -0
  284. data/test/test_amp.rb +9 -0
  285. data/test/test_base85.rb +14 -0
  286. data/test/test_bdiff.rb +42 -0
  287. data/test/test_commands.rb +122 -0
  288. data/test/test_difflib.rb +50 -0
  289. data/test/test_helper.rb +15 -0
  290. data/test/test_journal.rb +29 -0
  291. data/test/test_match.rb +134 -0
  292. data/test/test_mdiff.rb +74 -0
  293. data/test/test_mpatch.rb +14 -0
  294. data/test/test_support.rb +24 -0
  295. metadata +385 -0
@@ -0,0 +1,164 @@
1
+ require 'amp/dependencies/python_config.rb'
2
+
3
+ module Amp
4
+
5
+ ##
6
+ # AmpConfig is the class that handles all configuration for the
7
+ # Amp program. It is different from PythonConfig because there is
8
+ # a sense of hierarchy in the configuration files in Mercurial, and
9
+ # as such, in Amp. Namely, the hgrc in /etc/mercurial/ is of lesser
10
+ # importance as the one in your_repo/.hg/. So, we use "parent configs"
11
+ # to handle this hierarchy - create an AmpConfig with a parent, and it'll
12
+ # copy over all the old configurations. Then, tell it to read the
13
+ # repo-specific hgrc file, and the new settings will override the old ones.
14
+ class AmpConfig
15
+ include PythonConfig
16
+
17
+ ##
18
+ # The PythonConfig that actually stores all the information
19
+ attr_accessor :config
20
+ attr_reader :parent_config
21
+ ##
22
+ # Initializes the AmpConfig. Takes options to do that.
23
+ #
24
+ # @param [Hash] opts the options for initialization.
25
+ # @option [AmpConfig] opts :parent_config (nil) The parent configuration
26
+ # to base this configuration off of. The parent will be duplicated and
27
+ # then some options in it may be overridden.
28
+ # @option [[String], String] opts :read (nil) A list of files to read for
29
+ # configuring this AmpConfig, for example repo/.hg/hgrc. Note: if
30
+ # :parent_config is not provided, this option will default to
31
+ # /etc/mercurial/hgrc and ~/.hgrc.
32
+ # All other options are saved in an instance variable for later reference.
33
+ def initialize(opts={})
34
+ @config = nil
35
+ @options = opts
36
+
37
+ if opts[:parent_config]
38
+ @parent_config = opts.delete :parent_config
39
+ @config = @parent_config.config.dup
40
+ else
41
+ opts[:read] = Support::rc_path
42
+ end
43
+
44
+ if opts[:read]
45
+ @config = ConfigParser.new
46
+
47
+ [*opts.delete(:read)].each do |file|
48
+ read_file file
49
+ end
50
+ end
51
+
52
+ if opts[:parent]
53
+ @config = opts.delete(:parent).dup
54
+ end
55
+ @write_to_file ||= File.expand_path("~/.hgrc")
56
+ end
57
+
58
+ ##
59
+ # Reads the file provided, and overwrites any settings we've already
60
+ # assigned. Does NOT raise an error if the file isn't found.
61
+ def read_file(file)
62
+ begin
63
+ File.open(file, "r") do |fp|
64
+ newconfig = ConfigParser.new fp
65
+ @config.merge! newconfig
66
+ end
67
+
68
+ @config.merge! @options[:overlay] if @options[:overlay]
69
+ @write_to_file = file
70
+ rescue Errno::ENOENT
71
+ end
72
+ end
73
+
74
+ ##
75
+ # Saves to the most recently read-in file
76
+ def save!
77
+ @config.write @write_to_file
78
+ end
79
+
80
+ ##
81
+ # Updates our options with any settings we provide.
82
+ def update_options(opts = {})
83
+ if opts[:config]
84
+ config = opts.delete config
85
+ config.each do |section, settings|
86
+ settings.each do |k,v|
87
+ self[section,k] = v
88
+ end
89
+ end
90
+ end
91
+ @options.merge! opts
92
+ end
93
+
94
+ ##
95
+ # Gets the current username. First it checks some environment variables,
96
+ # then it looks into config files, then it gives up and makes one up.
97
+ #
98
+ # @return [String] the username for commits and shizz
99
+ def username
100
+ user = nil
101
+ # check the env-var
102
+ user ||= ENV["HGUSER"]
103
+ return user if user
104
+ # check for an email
105
+ user ||= ENV["EMAIL"]
106
+ return user if user
107
+ # check for stored username
108
+ user ||= self["ui","username"]
109
+ return user if user
110
+ #check for a setting
111
+ if self["ui", "askusername", Boolean]
112
+ user = UI.ask("enter a commit username:")
113
+ end
114
+ return user if user
115
+ # figure it out based on the system
116
+ user = "#{Support.get_username}@#{Support.get_fully_qualified_domain_name}"
117
+ return user
118
+ end
119
+
120
+ ##
121
+ # Access configurations. Params:
122
+ # Section, [Config Key], [Type to convert to], [Default value if not found]
123
+ #
124
+ # @example myconfig["ui", "askusername", Boolean, false]
125
+ # this means look in the "ui" section for a key named "askusername". If
126
+ # we find it, convert it to a Boolean and return it. If not, then just
127
+ # return false.
128
+ def [](*args)
129
+ section = args[0]
130
+
131
+ case args.size
132
+ when 1
133
+ @config[section]
134
+ when 2
135
+ key = args[1]
136
+ @config[section][key]
137
+ when 3
138
+ key = args[1]
139
+ force = args[2]
140
+ @config[section][key, force]
141
+ when 4
142
+ key = args[1]
143
+ force = args[2]
144
+ default = args[3]
145
+ @config[section][key, force, default]
146
+ end
147
+ end
148
+
149
+ ##
150
+ # Assigning section-key values.
151
+ #
152
+ # @param args the [Section, Key] pair
153
+ # @param value what you assigned it to.
154
+ # @example config["ui", "askusername"] = false
155
+ def []=(*args) # def []=(*args, value)
156
+ value = args.pop
157
+ section = args[0]
158
+ key = args[1]
159
+ @config[section][key] = value
160
+ end
161
+
162
+ def to_s; @config.to_s; end
163
+ end
164
+ end
@@ -0,0 +1,287 @@
1
+ require 'singleton'
2
+ require 'tempfile'
3
+
4
+ module Amp
5
+ ##
6
+ # Represents an extremely simple menu that the UI can use to ask for input.
7
+ # Replacement for Highline's "choose" method - and is extremely, extremely basic.
8
+ # In fact, I might strip out some flexibility for now. I just did. It only does
9
+ # numbered lists with no intelligently figuring things out.
10
+ class UIMenu
11
+ # The prompt to ask at the top of the menu
12
+ attr_accessor :prompt
13
+ # How to index results - left in for compatibility and possibly future flexibility
14
+ attr_accessor :index
15
+
16
+ ##
17
+ # Creates a new UIMenu. Initializes ivars. Does nothing else of use.
18
+ #
19
+ # @return [UIMenu] the new menu
20
+ def initialize
21
+ @choices = []
22
+ @prompt = "Pick an option, please."
23
+ @index = :number
24
+ end
25
+
26
+ ##
27
+ # Adds a choice to the list of choices to be presented to the user.
28
+ # Choices are ordered in the order in which this method is called.
29
+ # The block is stored and executed if the choice is selected.
30
+ #
31
+ # @param [String] prompt the prompt to display to the user for this
32
+ # choice
33
+ # @param [Hash] opts options for this choice (unused for now)
34
+ # @param [Proc] &block a block that will be executed later if the choice
35
+ # is selected
36
+ def choice(prompt, opts={}, &block)
37
+ @choices << {:text => prompt, :action => block}
38
+ end
39
+
40
+ ##
41
+ # Runs the UIMenu. Will loop until an acceptable choice is selected
42
+ # by the user. Prints the choices in the order in which they were added,
43
+ # in a numbered list. The user must select the number of their desired
44
+ # option. After an acceptable choice is selected, its associated block
45
+ # is executed.
46
+ def run
47
+ input = -1
48
+ while input <= 0 || input > @choices.size do
49
+ UI.say @prompt
50
+ @choices.each_with_index {|item, idx| UI::say "#{idx+1} #{item[:text]}"}
51
+ UI::say
52
+ UI::tell "Your choice: "
53
+ UI::say "[1-#{@choices.size}]"
54
+ input = UI::ask('', Integer)
55
+ end
56
+ choice = @choices[input - 1]
57
+ choice[:action].call
58
+ end
59
+ end
60
+
61
+ module UI
62
+ extend self
63
+ extend Amp::Merges::MergeUI
64
+
65
+ class << self
66
+ attr_accessor :config
67
+ end
68
+ ##
69
+ # Prints a warning. Can be disabled using configuration files. These are
70
+ # informational in nature but imply the user did something wrong, or
71
+ # that something is impossible.
72
+ #
73
+ # @param [#to_s] warning the warning to print to standard output
74
+ def warn(warning)
75
+ if !@config || @config["ui","amp-show-warnings",Boolean,true]
76
+ err "warning: #{warning}"
77
+ end
78
+ end
79
+
80
+ ##
81
+ # Produces a menu for the user. Home-rolled to avoid rubygems dependencies!
82
+ #
83
+ # @yield yields the menu object, which is configured inside the block, and then
84
+ # the menu is run
85
+ # @yieldparam menu the menu object. Should be configured inside the given block.
86
+ def choose
87
+ menu = UIMenu.new
88
+ yield menu
89
+ menu.run
90
+ end
91
+
92
+ ##
93
+ # Gets the user's password, while hiding it from prying eyes.
94
+ #
95
+ # REQUIRES `stty`
96
+ #
97
+ # @return [String] the user's password.
98
+ def get_pass
99
+ system "stty -echo"
100
+ pass = gets.chomp
101
+ tell "\n"
102
+ system "stty echo"
103
+ pass
104
+ end
105
+
106
+ ##
107
+ # Prints a status update. Can be disabled using configuration files.
108
+ # These are casual updates to let the user know the progress in an
109
+ # operation.
110
+ #
111
+ # @param [#to_s] update the message to print to standard output
112
+ # @return [NilClass]
113
+ def status(update='')
114
+ return unless $display
115
+ if !@config || @config["ui", "amp-show-status", Boolean, true]
116
+ say "status: #{update}"
117
+ end
118
+ end
119
+
120
+ ##
121
+ # Notes the message - ignored unless in debug mode
122
+ #
123
+ # @param [#to_s] note the note to print to standard output
124
+ # @return [NilClass]
125
+ def note(note='')
126
+ return unless $display
127
+ if !@config || @config["ui", "amp-show-notes", Boolean, false]
128
+ say "note: #{note}"
129
+ end
130
+ end
131
+
132
+ ##
133
+ # Prints +message+ to standard out with a trailing newline
134
+ #
135
+ # @param [#to_s] message the message to be printed.
136
+ # @return [NilClass]
137
+ def say(message='')
138
+ tell "#{message.to_s}\n"
139
+ end
140
+
141
+ ##
142
+ # Prints +message+ to standard out without a trailing newline.
143
+ #
144
+ # @param [#to_s] message the message to be printed.
145
+ # @return [NilClass]
146
+ def tell(message='')
147
+ $stdout.print message.to_s
148
+ end
149
+
150
+ ##
151
+ # Prints +message+ to standard error.
152
+ #
153
+ # @param [#to_s] message the message to be errored.
154
+ # @return [NilClass]
155
+ def err(message='')
156
+ $stderr.puts message.to_s
157
+ end
158
+
159
+ ##
160
+ # Ask +question+ and return the answer, chomped
161
+ #
162
+ # @param [#to_s] question question to ask
163
+ # @param [Class, #to_s, Symbol] type the type to cast the answer to
164
+ # @return [String] their response without trailing newline
165
+ def ask(question='', type=String)
166
+ type = type.to_s.downcase.to_sym
167
+
168
+ print question.to_s
169
+ result = gets.chomp unless type == :password
170
+
171
+ # type conversion
172
+ case type
173
+ when :string
174
+ result
175
+ when :integer, :fixnum, :bignum, :numeric
176
+ result.to_i
177
+ when :array
178
+ result.split(',').map {|e| e.strip }
179
+ when :password
180
+ get_pass
181
+ else
182
+ raise abort("Don't know how to convert to type #{type}")
183
+ end
184
+ end
185
+
186
+ ##
187
+ # Ask a yes or no question (accepts a variety of inputs)
188
+ #
189
+ # @param [#to_s] question question to ask
190
+ # @return [Boolean] their agreement
191
+ def yes_or_no(question='')
192
+ result = ask(question.to_s + ' [y/n/r/h] ')
193
+ case result.downcase[0, 1]
194
+ when 'r'
195
+ yes_or_no question # recurse
196
+ when 'h'
197
+ tell <<-EOS
198
+ [y/n/r/h] means you can type anything starting with a 'y', 'n', 'r', or an 'h' to select those options.
199
+
200
+ 'y'\tyes
201
+ 'n'\tno
202
+ 'r'\trepeat
203
+ 'h'\thelp
204
+ EOS
205
+ yes_or_no question
206
+ else
207
+ result.downcase.start_with? 'y'
208
+ end
209
+ end
210
+ alias_method :agree, :yes_or_no
211
+
212
+ ##
213
+ # Opens the user's editor for the file at the given path, with no extra
214
+ # processing afterward.
215
+ #
216
+ # @param [String, #inspect] path The path to locate the file to open.
217
+ # @return [Boolean] whether or not the editor successfully launched
218
+ def edit_file(path)
219
+ editor = get_editor
220
+ system "#{editor} #{path.inspect}"
221
+ end
222
+
223
+ ##
224
+ # Prints this message, only if the debug flag is set.
225
+ #
226
+ # @param [String, #to_s] message The debug message to be printed
227
+ def debug(message='')
228
+ if @config && @config["debug","messages", Boolean, false]
229
+ say message
230
+ end
231
+ end
232
+
233
+ ##
234
+ # Opens the editor for editing. Uses a temporary file to capture the
235
+ # user's input. The user must have either HGEDITOR, AMPEDITOR, VISUAL,
236
+ # EDITOR, or the configuration "ui"->"editor" set. Or, it'll just use
237
+ # vi.
238
+ #
239
+ # @param [String] text the text with which to fill the file
240
+ # @param [String] username the username to set the ENV var as
241
+ # @return [String] the file after being edited
242
+ def edit(text="", username="")
243
+ tempfile = Tempfile.new("amp-editor-")
244
+ path = tempfile.path
245
+ tempfile.write text
246
+ tempfile.close
247
+
248
+ ENV["AMPUSER"] = username
249
+ edit_file path
250
+
251
+ text = File.open(path) {|tf| tf.read } || ''
252
+
253
+ FileUtils.safe_unlink path
254
+
255
+ text.gsub!(/^AMP:.*\n/,"")
256
+ text
257
+ end
258
+
259
+ ##
260
+ # Asks the user something.
261
+ #
262
+ # @deprecated
263
+ # @param [#to_s] message the message to send
264
+ # @param [Class, lambda] type anything to force a type. If you supply
265
+ # a class, then the answer will be parsed into that class. If you
266
+ # supply a lambda, the string will be provided, and you do the conversion
267
+ # @param [] default Whatever the default answer is, if they fail to provide
268
+ # a valid answer.
269
+ # @return [String] their response with whitespace removed, or the default value
270
+ def prompt(message='', type=String, default=nil)
271
+ say message.to_s
272
+ response = STDIN.gets.strip
273
+ response = default if response == ""
274
+ return response
275
+ end
276
+
277
+ ##
278
+ # Gets the editor for the current system using environment variables or
279
+ # the configuration files.
280
+ #
281
+ # @return [String] the name of the editor command to execute
282
+ def get_editor
283
+ return ENV["AMPEDITOR"] || ENV["HGEDITOR"] || (@config && @config["ui","editor"]) ||
284
+ ENV["VISUAL"] || ENV["EDITOR"] || "vi"
285
+ end
286
+ end
287
+ end