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,201 @@
1
+ # Stolen from http://github.com/integrity/sinatra-authorization/blob/0761b5cc58597227364a9c8f3e91fcfc43154555/lib/sinatra/authorization.rb
2
+ # thank you!
3
+
4
+ require "sinatra/base"
5
+
6
+ module Sinatra
7
+ # Code adapted from {Ryan Tomayko}[http://tomayko.com/about] and
8
+ # {Christopher Schneid}[http://gittr.com], shared under an MIT License
9
+ # Code significantly refactored for Amp
10
+ module AbstractAuthorization
11
+ def unauthorized!(www_authenticate = challenge)
12
+ response["WWW-Authenticate"] = challenge
13
+ throw :halt, [ 401, 'Authorization Required' ]
14
+ end
15
+
16
+ def bad_request!
17
+ throw :halt, [ 400, 'Bad Request' ]
18
+ end
19
+
20
+ # Convenience method to determine if a user is logged in
21
+ def authorized?
22
+ !!request.env['REMOTE_USER']
23
+ end
24
+ alias :logged_in? :authorized?
25
+
26
+ # Name provided by the current user to log in
27
+ def current_user
28
+ request.env['REMOTE_USER']
29
+ end
30
+ end
31
+
32
+ ##
33
+ # HTTP Authorization helpers for Sinatra.
34
+ #
35
+ # In your helpers module, include Sinatra::Authorization and then define
36
+ # an #authorize(user, password) method to handle user provided
37
+ # credentials.
38
+ #
39
+ # Inside your events, call #login_required to trigger the HTTP
40
+ # Authorization window to pop up in the browser.
41
+ #
42
+ # Code adapted from {Ryan Tomayko}[http://tomayko.com/about] and
43
+ # {Christopher Schneid}[http://gittr.com], shared under an MIT License
44
+ # Code significantly refactored for Amp
45
+ module BasicAuthorization
46
+ include AbstractAuthorization
47
+ #
48
+ # # From you app, call set :authorization_realm, "my app" to set this
49
+ # # or define a #authorization_realm method in your helpers block.
50
+ def challenge
51
+ %(Basic realm="#{options.authorization_realm}")
52
+ end
53
+
54
+ # Call in any event that requires authentication
55
+ def login_required
56
+ return if authorized?
57
+ unauthorized! unless auth.provided?
58
+ bad_request! unless auth.basic?
59
+ unauthorized! unless authorize(*auth.credentials)
60
+ request.env['REMOTE_USER'] = auth.username
61
+ end
62
+
63
+
64
+ ##
65
+ # Whether or not the supplied username and password (and path) combination
66
+ # are, as Taco Bell says, "Good To Go".
67
+ #
68
+ # @param [String] username the plaintext that is passed in from the browser
69
+ # @param [String] password the plaintext (!!!!!!) password from the browser
70
+ # @return [Boolean] is the user/pass/path combo authorized?
71
+ def authorize(username, password)
72
+ repo = self.class.amp_repositories[request.path_info]
73
+ return true unless repo && repos[repo]
74
+
75
+ user = get_user_and_permissions repo, username # user = {:user => ..., :read => ..., :write => ...}
76
+ return false if command_reads?(params["cmd"]) && !user[:read]
77
+ return false if !command_reads?(params["cmd"]) &&
78
+ !user[:write] && repo_is_private?(repo)
79
+
80
+ user[:user].password == password
81
+ end
82
+
83
+ private
84
+
85
+ def auth
86
+ @auth ||= Rack::Auth::Basic::Request.new(request.env)
87
+ end
88
+ end
89
+
90
+ # liberally lifted and modified from Rack's source
91
+ # Code slightly refactored for Amp
92
+ module DigestAuthorization
93
+ include AbstractAuthorization
94
+
95
+ def opaque; "DEADBEEF"; end
96
+
97
+ QOP = 'auth'.freeze
98
+
99
+ def login_required
100
+ auth = Rack::Auth::Digest::Request.new(request.env)
101
+ unauthorized! unless auth.provided?
102
+ bad_request! if !auth.digest?
103
+ if valid?(auth)
104
+ if auth.nonce.stale?
105
+ return unauthorized!(challenge(:stale => true))
106
+ else
107
+ request.env["REMOTE_USER"] = auth.username
108
+ return true
109
+ end
110
+ end
111
+ unauthorized!
112
+ end
113
+
114
+ ##
115
+ # This method verifies that the digest provided is accurate. This is the only
116
+ # method involved in the authentication process that requires knowledge of the login
117
+ # system, so it is exposed here, rather than {Sinatra::DigestAuthorization}.
118
+ #
119
+ # @param [Rack::Request] auth The request being used for authorization
120
+ # @return [Boolean] is the user allowed to view the given material?
121
+ def valid_digest?(auth)
122
+ repo = self.class.amp_repositories[request.path_info]
123
+ # no repo OR no users added to repo --> Access to anyone
124
+ return true unless repo && repos[repo]
125
+
126
+ user = get_user_and_permissions repo, auth.username
127
+ # User not in the system at all? Denied!
128
+ return false unless user
129
+
130
+ # if we're private
131
+ if repo_is_private?(repo)
132
+ # and the command is read-only, but user cannot read, they get Ben Wallace'd
133
+ return false if command_reads?(params["cmd"]) && !user[:read]
134
+ end
135
+
136
+ # Command is write-only, but user cannot write --> Denied. Private/non-private doesn't matter.
137
+ return false if command_writes?(params["cmd"]) && !user[:write]
138
+
139
+ # Can't short-circuit this one. Just run the digest.
140
+ digest(auth, user[:user].password) == auth.response
141
+ end
142
+
143
+ def auth_params(hash = {})
144
+ param = Rack::Auth::Digest::Params.new do |param|
145
+ param['realm'] = options.authorization_realm
146
+ param['nonce'] = Rack::Auth::Digest::Nonce.new.to_s
147
+ param['opaque'] = H(opaque)
148
+ param['qop'] = QOP
149
+ hash.each { |k, v| param[k] = v }
150
+ end
151
+ end
152
+
153
+ def challenge(hash = {})
154
+ "Digest #{auth_params(hash)}"
155
+ end
156
+
157
+ def valid?(auth)
158
+ valid_opaque?(auth) && valid_nonce?(auth) && valid_digest?(auth)
159
+ end
160
+
161
+ def valid_qop?(auth)
162
+ QOP == auth.qop
163
+ end
164
+
165
+ def valid_opaque?(auth)
166
+ H(opaque) == auth.opaque
167
+ end
168
+
169
+ def valid_nonce?(auth)
170
+ auth.nonce.valid?
171
+ end
172
+
173
+ def md5(data)
174
+ ::Digest::MD5.hexdigest(data)
175
+ end
176
+
177
+ alias :H :md5
178
+
179
+ def KD(secret, data)
180
+ H([secret, data] * ':')
181
+ end
182
+
183
+ def A1(auth, password)
184
+ [ auth.username, auth.realm, password ] * ':'
185
+ end
186
+
187
+ def A2(auth)
188
+ [ auth.method, auth.uri ] * ':'
189
+ end
190
+
191
+ def digest(auth, password)
192
+ # change false to match if we ever store hashed passes
193
+ password_hash = false ? password : H(A1(auth, password))
194
+
195
+ KD(password_hash, [ auth.nonce, auth.nc, auth.cnonce, QOP, H(A2(auth)) ] * ':')
196
+ end
197
+ end
198
+ # add them in
199
+ helpers BasicAuthorization
200
+ helpers DigestAuthorization
201
+ end
@@ -0,0 +1,252 @@
1
+ require 'rubygems'
2
+ require 'haml'
3
+ require 'sass'
4
+
5
+ class Hash
6
+ alias_method :get, :[]
7
+ ##
8
+ # Same as #[], but will take regexps and try to match those.
9
+ # This will bug out if you are using regexps as keys
10
+ #
11
+ # @return [Hash, Value] will return either a hash (if supplied with a regexp)
12
+ # or whatever it would normally return.
13
+ def [](key)
14
+ case key
15
+ when Regexp
16
+ select {|k, _| k =~ key }.to_hash
17
+ else
18
+ get key
19
+ end
20
+ end
21
+ end
22
+
23
+ module Amp
24
+ module Servers
25
+
26
+ class FancyHTTPServer < HTTPAuthorizedServer
27
+
28
+ set :views, File.expand_path(File.join(File.dirname(__FILE__), "fancy_views"))
29
+ enable :static
30
+ set :public, File.expand_path(File.join(File.dirname(__FILE__), "fancy_views"))
31
+
32
+ def self.amp_repository(http_path, repo, opts={})
33
+ super(http_path, repo)
34
+
35
+ http_path.chomp!('/')
36
+ path_slashed = http_path + "/"
37
+
38
+ get "#{http_path}/changeset/:changeset/?" do |cs|
39
+ @changeset = repo[cs]
40
+ haml :changeset, :locals => {:root => http_path, :repo => repo}
41
+ end
42
+
43
+
44
+ [http_path+"/", "#{http_path}/commits/?", "#{http_path}/commits/:page/?"].each do |path|
45
+ get path do
46
+ haml :commits, :locals => {:root => http_path, :opts => opts, :repo => repo, :page => params[:page].to_i}
47
+ end
48
+ end
49
+
50
+
51
+ get "#{http_path}/users/:user" do
52
+ if users[params[:user]]
53
+ "You are browsing user #{params[:user]} in a repository located at #{repo.inspect}"
54
+ else
55
+ "User #{params[:user].inspect} not found :-("
56
+ end
57
+ end
58
+
59
+ ["#{http_path}/code/:changeset/?*", "#{http_path}/code/?*"].each do |p|
60
+ get p do
61
+ path = params[:splat].join
62
+ path = path.shift('/').chomp('/') # clean it of slashes
63
+ changeset_node = params[:changeset] || "tip"
64
+ changeset = repo[changeset_node]
65
+
66
+ info = load_browser_info changeset, path
67
+ file_list, path, vf_cur, orig_path = info[:file_list], info[:path], info[:vf_cur], info[:orig_path]
68
+
69
+ haml :file, :locals => {:root => http_path, :repo => repo, :file_list => file_list,
70
+ :path => path, :vf_cur => vf_cur, :orig_path => orig_path,
71
+ :changeset => changeset}
72
+ end
73
+ end
74
+
75
+ get "#{http_path}/diff/:changeset/*" do
76
+ path = params[:splat].join
77
+ path = path.shift('/').chomp('/') # clean it of slashes
78
+ changeset_node = params[:changeset] || "tip"
79
+ changeset = repo[changeset_node]
80
+
81
+ info = load_browser_info changeset, path
82
+ file_list, path, vf_cur, orig_path = info[:file_list], info[:path], info[:vf_cur], info[:orig_path]
83
+
84
+ haml :file_diff, :locals => {:root => http_path, :repo => repo, :file_list => file_list,
85
+ :path => path, :vf_cur => vf_cur, :orig_path => orig_path,
86
+ :changeset => changeset}
87
+ end
88
+
89
+ get "#{http_path}/raw/:changeset/*" do
90
+ changeset_node = params[:changeset]
91
+ path = params[:splat].join.shift("/").chomp("/")
92
+
93
+ changeset = repo[changeset_node]
94
+ vf_cur = changeset.get_file path
95
+
96
+ content_type "text/plain"
97
+ vf_cur.data
98
+ end
99
+
100
+ get '/stylesheet.css' do
101
+ content_type 'text/css', :charset => 'utf-8'
102
+ sass :stylesheet
103
+ end
104
+
105
+ end
106
+
107
+ helpers do
108
+
109
+ def load_browser_info(changeset, path)
110
+
111
+ mapping = changeset.manifest
112
+ orig_path = nil
113
+ # if the path is a file (because we only keep track of files)
114
+ if mapping[path]
115
+ # give it the appropriate information (the versioned file)
116
+ vf_cur = changeset.get_file(path)
117
+ file_list = [] # and return an empty file_list
118
+ orig_path = path
119
+ path = Dir.dirname path
120
+ end
121
+
122
+ files = mapping.files.select {|f| Dir.dirname(f) == path }.map {|f| f[path.size..-1].shift '/' }
123
+ dirs = mapping.files.select {|f| File.amp_directories_to(f, true).index(path) && Dir.dirname(f) != path } # only go one deep
124
+ dirs.map! do |d|
125
+ idx = File.amp_directories_to(d, true).index path
126
+ File.amp_directories_to(d, true)[idx - 1][path.size..-1].shift '/'
127
+ end.uniq!
128
+
129
+ path = path.empty? ? '' : path + '/'
130
+
131
+ file_list = files.map do |name|
132
+ {:link => path + name ,
133
+ :type => :file,
134
+ :name => name }
135
+ end
136
+
137
+ file_list += dirs.map do |name|
138
+ {:link => path + name,
139
+ :type => :directory ,
140
+ :name => name }
141
+ end
142
+
143
+ file_list.sort! {|h1, h2| h1[:name] <=> h2[:name] } # alphabetically sorted
144
+ vf_cur ||= if mapping[/#{path}readme/i].any? # map[//] returns a hash
145
+ change_id = params[:changeset] || "tip"
146
+ readme = mapping[/#{path}readme/i].keys.first
147
+ orig_path = readme
148
+ changeset.get_file readme
149
+ else
150
+ nil
151
+ end
152
+
153
+ path = path.chomp '/' # path will not have any trailing slashes
154
+
155
+ {:path => path, :vf_cur => vf_cur, :file_list => file_list, :orig_path => orig_path}
156
+ end
157
+
158
+ def link(root, action, changeset_node, after_path, opts={})
159
+ after_path = "/#{after_path}" if after_path
160
+ changeset_node = changeset_node[0..11]
161
+ text = opts.delete(:text) || changeset_node
162
+ additional_opts = opts.map {|key, value| %{#{key}="#{value}"}}.join(" ")
163
+ %{<a href="#{root}/#{action}/#{changeset_node}#{after_path}" #{additional_opts}>
164
+ #{text}
165
+ </a>}
166
+ end
167
+
168
+ def link_to_changeset(root, changeset_node, opts={})
169
+ link(root, :changeset, changeset_node, nil, opts)
170
+ end
171
+
172
+ def link_to_file(root, changeset_node, file=nil, opts={})
173
+ opts[:text] ||= file
174
+ link(root, :code, changeset_node, file, opts)
175
+ end
176
+
177
+ def link_to_file_raw(root, changeset_node, file=nil, opts={})
178
+ opts[:text] ||= file
179
+ link(root, :raw, changeset_node, file, opts)
180
+ end
181
+
182
+ def link_to_file_diff(root, changeset_node, file=nil, opts={})
183
+ opts[:text] ||= file
184
+ link(root, :diff, changeset_node, file, opts)
185
+ end
186
+
187
+ def highlight_text(text, opts = {:format => "ruby", :theme => "twilight", :lines => false})
188
+ require 'uv'
189
+ ::Haml::Helpers.preserve(Uv.parse( text.rstrip, "xhtml", opts[:format].to_s, opts[:lines], opts[:theme]))
190
+ end
191
+
192
+ def rel_date(o_date)
193
+ a = (Time.now-o_date).to_i
194
+ case a
195
+ when 0 then return 'just now'
196
+ when 1 then return 'a second ago'
197
+ when 2..59 then return a.to_s+' seconds ago'
198
+ when 60..119 then return 'a minute ago' #120 = 2 minutes
199
+ when 120..3540 then return (a/60).to_i.to_s+' minutes ago'
200
+ when 3541..7100 then return 'an hour ago' # 3600 = 1 hour
201
+ when 7101..82800 then return ((a+99)/3600).to_i.to_s+' hours ago'
202
+ when 82801..172000 then return 'a day ago' # 86400 = 1 day
203
+ when 172001..518400 then return ((a+800)/(60*60*24)).to_i.to_s+' days ago'
204
+ end
205
+ return o_date.strftime("%B %d, %Y")
206
+ end
207
+
208
+ def format_for_filename(ext)
209
+ ext = File.extname(ext)
210
+ return :text if ext.nil? || ext.empty?
211
+
212
+ case ext.downcase
213
+ when ".rb"
214
+ :ruby
215
+ when ".py"
216
+ :python
217
+ when ".cpp"
218
+ :"c++"
219
+ when ".txt"
220
+ :text
221
+ else
222
+ ext[1..-1].to_sym
223
+ end
224
+ end
225
+
226
+ def parse_diff(input_diff)
227
+ line_counter_a, line_counter_b = 0, 0
228
+ input_diff.split_lines_better.map do |line|
229
+ if line[0,1] == ' '
230
+ res = %{<li class='diff-unmod'><pre>#{line_counter_a} #{line_counter_b}&nbsp;#{line.rstrip}</pre></li>\n}
231
+ line_counter_a += 1
232
+ line_counter_b += 1
233
+ elsif line[0,3] == '+++'
234
+ elsif line[0,3] == '---'
235
+ elsif line[0,1] == '+'
236
+ res = %{<li class='diff-add'><pre>#{" " * line_counter_b.to_s.size} #{line_counter_b} &nbsp;#{line.rstrip}</pre></li>\n}
237
+ line_counter_b += 1
238
+ elsif line[0,1] == '-'
239
+ res = %{<li class='diff-del'><pre>#{line_counter_a} #{" " * line_counter_a.to_s.size} &nbsp;#{line.rstrip}</pre></li>\n}
240
+ line_counter_a += 1
241
+ elsif line[0,2] == '@@'
242
+ line_counter_a, line_counter_b = line.scan(/\-(\d+),\d+ \+(\d+),\d+/).shift.map {|x| x.to_i}
243
+ res = %{<li class='diff-ctx'><pre>&nbsp;#{line.rstrip}</pre></li>\n}
244
+ end
245
+ res
246
+ end
247
+ end
248
+ end
249
+
250
+ end
251
+ end
252
+ end