amp 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (232) hide show
  1. data/.gitignore +12 -0
  2. data/.hgignore +3 -0
  3. data/AUTHORS +1 -1
  4. data/Manifest.txt +99 -38
  5. data/README.md +3 -3
  6. data/Rakefile +53 -18
  7. data/SCHEDULE.markdown +5 -1
  8. data/TODO.markdown +120 -149
  9. data/ampfile.rb +3 -1
  10. data/bin/amp +4 -1
  11. data/ext/amp/bz2/extconf.rb +1 -1
  12. data/ext/amp/mercurial_patch/extconf.rb +1 -1
  13. data/ext/amp/mercurial_patch/mpatch.c +4 -3
  14. data/ext/amp/priority_queue/extconf.rb +1 -1
  15. data/ext/amp/support/extconf.rb +1 -1
  16. data/ext/amp/support/support.c +1 -1
  17. data/lib/amp.rb +125 -67
  18. data/lib/amp/commands/command.rb +12 -10
  19. data/lib/amp/commands/command_support.rb +8 -1
  20. data/lib/amp/commands/commands/help.rb +2 -20
  21. data/lib/amp/commands/commands/init.rb +14 -2
  22. data/lib/amp/commands/commands/templates.rb +6 -4
  23. data/lib/amp/commands/commands/version.rb +15 -1
  24. data/lib/amp/commands/commands/workflow.rb +3 -3
  25. data/lib/amp/commands/commands/workflows/git/add.rb +3 -3
  26. data/lib/amp/commands/commands/workflows/git/copy.rb +1 -1
  27. data/lib/amp/commands/commands/workflows/git/rm.rb +4 -2
  28. data/lib/amp/commands/commands/workflows/hg/add.rb +1 -1
  29. data/lib/amp/commands/commands/workflows/hg/addremove.rb +2 -2
  30. data/lib/amp/commands/commands/workflows/hg/annotate.rb +8 -2
  31. data/lib/amp/commands/commands/workflows/hg/bisect.rb +253 -0
  32. data/lib/amp/commands/commands/workflows/hg/branch.rb +1 -1
  33. data/lib/amp/commands/commands/workflows/hg/branches.rb +3 -3
  34. data/lib/amp/commands/commands/workflows/hg/bundle.rb +3 -3
  35. data/lib/amp/commands/commands/workflows/hg/clone.rb +4 -5
  36. data/lib/amp/commands/commands/workflows/hg/commit.rb +37 -1
  37. data/lib/amp/commands/commands/workflows/hg/copy.rb +2 -1
  38. data/lib/amp/commands/commands/workflows/hg/debug/index.rb +1 -1
  39. data/lib/amp/commands/commands/workflows/hg/diff.rb +3 -8
  40. data/lib/amp/commands/commands/workflows/hg/forget.rb +5 -4
  41. data/lib/amp/commands/commands/workflows/hg/identify.rb +6 -6
  42. data/lib/amp/commands/commands/workflows/hg/import.rb +1 -1
  43. data/lib/amp/commands/commands/workflows/hg/incoming.rb +2 -2
  44. data/lib/amp/commands/commands/workflows/hg/log.rb +5 -4
  45. data/lib/amp/commands/commands/workflows/hg/merge.rb +1 -1
  46. data/lib/amp/commands/commands/workflows/hg/move.rb +5 -3
  47. data/lib/amp/commands/commands/workflows/hg/outgoing.rb +1 -1
  48. data/lib/amp/commands/commands/workflows/hg/push.rb +6 -7
  49. data/lib/amp/commands/commands/workflows/hg/remove.rb +2 -2
  50. data/lib/amp/commands/commands/workflows/hg/resolve.rb +6 -23
  51. data/lib/amp/commands/commands/workflows/hg/root.rb +1 -2
  52. data/lib/amp/commands/commands/workflows/hg/status.rb +21 -12
  53. data/lib/amp/commands/commands/workflows/hg/tag.rb +2 -2
  54. data/lib/amp/commands/commands/workflows/hg/untrack.rb +12 -0
  55. data/lib/amp/commands/commands/workflows/hg/verify.rb +13 -3
  56. data/lib/amp/commands/commands/workflows/hg/what_changed.rb +18 -0
  57. data/lib/amp/commands/dispatch.rb +12 -13
  58. data/lib/amp/dependencies/amp_support.rb +1 -1
  59. data/lib/amp/dependencies/amp_support/ruby_amp_support.rb +1 -0
  60. data/lib/amp/dependencies/maruku.rb +136 -0
  61. data/lib/amp/dependencies/maruku/attributes.rb +227 -0
  62. data/lib/amp/dependencies/maruku/defaults.rb +71 -0
  63. data/lib/amp/dependencies/maruku/errors_management.rb +92 -0
  64. data/lib/amp/dependencies/maruku/helpers.rb +260 -0
  65. data/lib/amp/dependencies/maruku/input/charsource.rb +326 -0
  66. data/lib/amp/dependencies/maruku/input/extensions.rb +69 -0
  67. data/lib/amp/dependencies/maruku/input/html_helper.rb +189 -0
  68. data/lib/amp/dependencies/maruku/input/linesource.rb +111 -0
  69. data/lib/amp/dependencies/maruku/input/parse_block.rb +615 -0
  70. data/lib/amp/dependencies/maruku/input/parse_doc.rb +234 -0
  71. data/lib/amp/dependencies/maruku/input/parse_span_better.rb +746 -0
  72. data/lib/amp/dependencies/maruku/input/rubypants.rb +225 -0
  73. data/lib/amp/dependencies/maruku/input/type_detection.rb +147 -0
  74. data/lib/amp/dependencies/maruku/input_textile2/t2_parser.rb +163 -0
  75. data/lib/amp/dependencies/maruku/maruku.rb +33 -0
  76. data/lib/amp/dependencies/maruku/output/to_ansi.rb +223 -0
  77. data/lib/amp/dependencies/maruku/output/to_html.rb +991 -0
  78. data/lib/amp/dependencies/maruku/output/to_markdown.rb +164 -0
  79. data/lib/amp/dependencies/maruku/output/to_s.rb +56 -0
  80. data/lib/amp/dependencies/maruku/string_utils.rb +191 -0
  81. data/lib/amp/dependencies/maruku/structures.rb +167 -0
  82. data/lib/amp/dependencies/maruku/structures_inspect.rb +87 -0
  83. data/lib/amp/dependencies/maruku/structures_iterators.rb +61 -0
  84. data/lib/amp/dependencies/maruku/textile2.rb +1 -0
  85. data/lib/amp/dependencies/maruku/toc.rb +199 -0
  86. data/lib/amp/dependencies/maruku/usage/example1.rb +33 -0
  87. data/lib/amp/dependencies/maruku/version.rb +40 -0
  88. data/lib/amp/dependencies/priority_queue.rb +2 -1
  89. data/lib/amp/dependencies/python_config.rb +2 -1
  90. data/lib/amp/graphs/ancestor.rb +2 -1
  91. data/lib/amp/graphs/copies.rb +236 -233
  92. data/lib/amp/help/entries/__default__.erb +31 -0
  93. data/lib/amp/help/entries/commands.erb +6 -0
  94. data/lib/amp/help/entries/mdtest.md +35 -0
  95. data/lib/amp/help/entries/silly +3 -0
  96. data/lib/amp/help/help.rb +288 -0
  97. data/lib/amp/profiling_hacks.rb +5 -3
  98. data/lib/amp/repository/abstract/abstract_changeset.rb +97 -0
  99. data/lib/amp/repository/abstract/abstract_local_repo.rb +181 -0
  100. data/lib/amp/repository/abstract/abstract_staging_area.rb +180 -0
  101. data/lib/amp/repository/abstract/abstract_versioned_file.rb +100 -0
  102. data/lib/amp/repository/abstract/common_methods/changeset.rb +75 -0
  103. data/lib/amp/repository/abstract/common_methods/local_repo.rb +277 -0
  104. data/lib/amp/repository/abstract/common_methods/staging_area.rb +233 -0
  105. data/lib/amp/repository/abstract/common_methods/versioned_file.rb +71 -0
  106. data/lib/amp/repository/generic_repo_picker.rb +78 -0
  107. data/lib/amp/repository/git/repo_format/changeset.rb +336 -0
  108. data/lib/amp/repository/git/repo_format/staging_area.rb +192 -0
  109. data/lib/amp/repository/git/repo_format/versioned_file.rb +119 -0
  110. data/lib/amp/repository/git/repositories/local_repository.rb +164 -0
  111. data/lib/amp/repository/git/repository.rb +41 -0
  112. data/lib/amp/repository/mercurial/encoding/mercurial_diff.rb +382 -0
  113. data/lib/amp/repository/mercurial/encoding/mercurial_patch.rb +1 -0
  114. data/lib/amp/repository/mercurial/encoding/patch.rb +294 -0
  115. data/lib/amp/repository/mercurial/encoding/pure_ruby/ruby_mercurial_patch.rb +124 -0
  116. data/lib/amp/repository/mercurial/merging/merge_ui.rb +327 -0
  117. data/lib/amp/repository/mercurial/merging/simple_merge.rb +452 -0
  118. data/lib/amp/repository/mercurial/repo_format/branch_manager.rb +266 -0
  119. data/lib/amp/repository/mercurial/repo_format/changeset.rb +768 -0
  120. data/lib/amp/repository/mercurial/repo_format/dir_state.rb +716 -0
  121. data/lib/amp/repository/mercurial/repo_format/journal.rb +218 -0
  122. data/lib/amp/repository/mercurial/repo_format/lock.rb +210 -0
  123. data/lib/amp/repository/mercurial/repo_format/merge_state.rb +228 -0
  124. data/lib/amp/repository/mercurial/repo_format/staging_area.rb +367 -0
  125. data/lib/amp/repository/mercurial/repo_format/store.rb +487 -0
  126. data/lib/amp/repository/mercurial/repo_format/tag_manager.rb +322 -0
  127. data/lib/amp/repository/mercurial/repo_format/updatable.rb +543 -0
  128. data/lib/amp/repository/mercurial/repo_format/updater.rb +848 -0
  129. data/lib/amp/repository/mercurial/repo_format/verification.rb +433 -0
  130. data/lib/amp/repository/mercurial/repositories/bundle_repository.rb +216 -0
  131. data/lib/amp/repository/mercurial/repositories/http_repository.rb +386 -0
  132. data/lib/amp/repository/mercurial/repositories/local_repository.rb +2034 -0
  133. data/lib/amp/repository/mercurial/repository.rb +119 -0
  134. data/lib/amp/repository/mercurial/revlogs/bundle_revlogs.rb +249 -0
  135. data/lib/amp/repository/mercurial/revlogs/changegroup.rb +217 -0
  136. data/lib/amp/repository/mercurial/revlogs/changelog.rb +339 -0
  137. data/lib/amp/repository/mercurial/revlogs/file_log.rb +152 -0
  138. data/lib/amp/repository/mercurial/revlogs/index.rb +500 -0
  139. data/lib/amp/repository/mercurial/revlogs/manifest.rb +201 -0
  140. data/lib/amp/repository/mercurial/revlogs/node.rb +20 -0
  141. data/lib/amp/repository/mercurial/revlogs/revlog.rb +1026 -0
  142. data/lib/amp/repository/mercurial/revlogs/revlog_support.rb +129 -0
  143. data/lib/amp/repository/mercurial/revlogs/versioned_file.rb +597 -0
  144. data/lib/amp/repository/repository.rb +11 -88
  145. data/lib/amp/server/extension/amp_extension.rb +3 -3
  146. data/lib/amp/server/fancy_http_server.rb +1 -1
  147. data/lib/amp/server/fancy_views/_browser.haml +1 -1
  148. data/lib/amp/server/fancy_views/_diff_file.haml +1 -8
  149. data/lib/amp/server/fancy_views/changeset.haml +2 -2
  150. data/lib/amp/server/fancy_views/file.haml +1 -1
  151. data/lib/amp/server/fancy_views/file_diff.haml +1 -1
  152. data/lib/amp/support/amp_ui.rb +13 -29
  153. data/lib/amp/support/generator.rb +1 -1
  154. data/lib/amp/support/loaders.rb +1 -2
  155. data/lib/amp/support/logger.rb +10 -16
  156. data/lib/amp/support/match.rb +18 -4
  157. data/lib/amp/support/mercurial/ignore.rb +151 -0
  158. data/lib/amp/support/openers.rb +8 -3
  159. data/lib/amp/support/support.rb +91 -46
  160. data/lib/amp/templates/{blank.commit.erb → mercurial/blank.commit.erb} +0 -0
  161. data/lib/amp/templates/{blank.log.erb → mercurial/blank.log.erb} +0 -0
  162. data/lib/amp/templates/{default.commit.erb → mercurial/default.commit.erb} +0 -0
  163. data/lib/amp/templates/{default.log.erb → mercurial/default.log.erb} +0 -0
  164. data/lib/amp/templates/template.rb +18 -18
  165. data/man/amp.1 +51 -0
  166. data/site/src/about/commands.haml +1 -1
  167. data/site/src/css/amp.css +1 -1
  168. data/site/src/index.haml +3 -3
  169. data/tasks/man.rake +39 -0
  170. data/tasks/stats.rake +1 -10
  171. data/tasks/yard.rake +1 -50
  172. data/test/dirstate_tests/test_dir_state.rb +10 -8
  173. data/test/functional_tests/annotate.out +31 -0
  174. data/test/functional_tests/test_functional.rb +155 -63
  175. data/test/localrepo_tests/ampfile.rb +12 -0
  176. data/test/localrepo_tests/test_local_repo.rb +56 -57
  177. data/test/manifest_tests/test_manifest.rb +3 -5
  178. data/test/merge_tests/test_merge.rb +3 -3
  179. data/test/revlog_tests/test_revlog.rb +14 -6
  180. data/test/store_tests/test_fncache_store.rb +19 -19
  181. data/test/test_19_compatibility.rb +46 -0
  182. data/test/test_base85.rb +2 -2
  183. data/test/test_bdiff.rb +2 -2
  184. data/test/test_changegroup.rb +59 -0
  185. data/test/test_commands.rb +2 -2
  186. data/test/test_difflib.rb +2 -2
  187. data/test/test_generator.rb +34 -0
  188. data/test/test_ignore.rb +203 -0
  189. data/test/test_journal.rb +18 -13
  190. data/test/test_match.rb +2 -2
  191. data/test/test_mdiff.rb +3 -3
  192. data/test/test_mpatch.rb +3 -3
  193. data/test/test_multi_io.rb +40 -0
  194. data/test/test_support.rb +18 -2
  195. data/test/test_templates.rb +38 -0
  196. data/test/test_ui.rb +79 -0
  197. data/test/testutilities.rb +56 -0
  198. metadata +168 -49
  199. data/ext/amp/bz2/mkmf.log +0 -38
  200. data/lib/amp/encoding/mercurial_diff.rb +0 -378
  201. data/lib/amp/encoding/mercurial_patch.rb +0 -1
  202. data/lib/amp/encoding/patch.rb +0 -292
  203. data/lib/amp/encoding/pure_ruby/ruby_mercurial_patch.rb +0 -123
  204. data/lib/amp/merges/merge_state.rb +0 -164
  205. data/lib/amp/merges/merge_ui.rb +0 -322
  206. data/lib/amp/merges/simple_merge.rb +0 -450
  207. data/lib/amp/repository/branch_manager.rb +0 -234
  208. data/lib/amp/repository/dir_state.rb +0 -950
  209. data/lib/amp/repository/journal.rb +0 -203
  210. data/lib/amp/repository/lock.rb +0 -207
  211. data/lib/amp/repository/repositories/bundle_repository.rb +0 -214
  212. data/lib/amp/repository/repositories/http_repository.rb +0 -377
  213. data/lib/amp/repository/repositories/local_repository.rb +0 -2661
  214. data/lib/amp/repository/store.rb +0 -485
  215. data/lib/amp/repository/tag_manager.rb +0 -319
  216. data/lib/amp/repository/updatable.rb +0 -532
  217. data/lib/amp/repository/verification.rb +0 -431
  218. data/lib/amp/repository/versioned_file.rb +0 -475
  219. data/lib/amp/revlogs/bundle_revlogs.rb +0 -246
  220. data/lib/amp/revlogs/changegroup.rb +0 -217
  221. data/lib/amp/revlogs/changelog.rb +0 -338
  222. data/lib/amp/revlogs/changeset.rb +0 -521
  223. data/lib/amp/revlogs/file_log.rb +0 -165
  224. data/lib/amp/revlogs/index.rb +0 -493
  225. data/lib/amp/revlogs/manifest.rb +0 -195
  226. data/lib/amp/revlogs/node.rb +0 -18
  227. data/lib/amp/revlogs/revlog.rb +0 -1045
  228. data/lib/amp/revlogs/revlog_support.rb +0 -126
  229. data/lib/amp/support/ignore.rb +0 -144
  230. data/site/Rakefile +0 -38
  231. data/test/test_amp.rb +0 -9
  232. data/test/test_helper.rb +0 -15
@@ -0,0 +1,71 @@
1
+ module Amp
2
+ module Repositories
3
+
4
+ ##
5
+ # = CommonVersionedFileMethods
6
+ #
7
+ # These methods are common to all repositories, and this module is mixed into
8
+ # the AbstractLocalRepository class. This guarantees that all repositories will
9
+ # have these methods.
10
+ #
11
+ # No methods should be placed into this module unless it relies on methods in the
12
+ # general API for repositories.
13
+ module CommonVersionedFileMethods
14
+
15
+ def unified_diff_with(other_vf, opts = {})
16
+ Diffs::Mercurial::MercurialDiff.unified_diff(self.data, self.changeset.easy_date,
17
+ other_vf.data, other_vf.changeset.easy_date,
18
+ self.path, other_vf.path || "/dev/null",
19
+ false, opts)
20
+ end
21
+
22
+ ##
23
+ # Compares two versioned files - namely, their data.
24
+ #
25
+ # @param [VersionedFile] other what to compare to
26
+ # @return [Boolean] true if the two are the same
27
+ def ===(other)
28
+ self.path == other.path &&
29
+ self.data == other.data
30
+ end
31
+
32
+ # Returns if the file has been changed since its parent. Slow.
33
+ # If your implementation has a fast way of doing this, we recommend
34
+ # you override this method.
35
+ #
36
+ # @return [Boolean] has the file been changed since its parent?
37
+ def clean?
38
+ self === parents.first
39
+ end
40
+ opposite_method :dirty?, :clean?
41
+
42
+ ##
43
+ # User who committed this revision to this file
44
+ #
45
+ # @return [String] the user
46
+ def user; changeset.user; end
47
+
48
+ ##
49
+ # Date this revision to this file was committed
50
+ #
51
+ # @return [DateTime]
52
+ def date; changeset.date; end
53
+
54
+ ##
55
+ # The description of the commit that contained this file revision
56
+ #
57
+ # @return [String]
58
+ def description; changeset.description; end
59
+
60
+ ##
61
+ # The branch this tracked file belongs to
62
+ #
63
+ # @return [String]
64
+ def branch; changeset.branch; end
65
+
66
+ ##
67
+ # Working directory has no children!
68
+ def children; []; end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,78 @@
1
+ module Amp
2
+ module Repositories
3
+
4
+ ##
5
+ # This class is a generic "repo picker". It will return a Repository object
6
+ # for the given path (if there is one), and is capable of telling you if there
7
+ # is a repository of its type in the given directory.
8
+ #
9
+ # Amp started off with a MercurialPicker - it knows how to find Mercurial repos.
10
+ #
11
+ # When amp runs, it iterates over all subclasses of AbstractRepoPicker, in no
12
+ # guaranteed order (so don't stomp on existing pickers!), calling #repo_in_dir? .
13
+ # If only one picker returns +true+, then that picker is used for opening the
14
+ # repository. If more than one returns +true+, the user's configuration is consulted.
15
+ # If nothing is found then, then the user is prompted. When the final picker has been
16
+ # chosen, its #pick method is called to get the repository for the directory/URL.
17
+ #
18
+ # This is an "abstract" class, in that all the methods will raise a NotImplementedError
19
+ # if you try to call them.
20
+ #
21
+ # You must subclass this class, or your custom repo code will be ignored by Amp's
22
+ # dispatch system.
23
+ class GenericRepoPicker
24
+ @all_pickers = []
25
+ class << self
26
+ include Enumerable
27
+ attr_accessor :all_pickers
28
+
29
+ ##
30
+ # Returns whether or not there is a repository in the given directory. This
31
+ # picker should only be responsible for one type of repository - git, svn, hg,
32
+ # etc. The given path could be deep inside a repository, and must look in parent
33
+ # directories for the root of the VCS repository.
34
+ #
35
+ # @param [String] path the path in which to search for a repository
36
+ # @return [Boolean] is there a repository in this directory (or parent directories)?
37
+ def repo_in_dir?(path)
38
+ raise NotImplementedError.new("repo_in_dir? must be implemented in a concrete subclass.")
39
+ end
40
+ alias_method :repo_in_url?, :repo_in_dir?
41
+
42
+ ##
43
+ # Returns a repository object for the given path. Should respond to the standard repository
44
+ # API to the best of its ability, and raise a CapabilityError if asked to do something it
45
+ # cannot do from the API.
46
+ #
47
+ # @param [AmpConfig] config the configuration of the current environment, loaded from
48
+ # appropriate configuration files
49
+ # @param [String] path the path/URL in which to open the repository.
50
+ # @param [Boolean] create should a repository be created in the given directory/URL?
51
+ # @return [AbstractLocalRepository] the repository for the given URL
52
+ def pick(config, path = '', create = false)
53
+ raise NotImplementedError.new("repo_in_dir? must be implemented in a concrete subclass.")
54
+ end
55
+
56
+ ##
57
+ # Iterate over every RepoPicker in the system.
58
+ def each(*args, &block)
59
+ @all_pickers.each(*args, &block)
60
+ end
61
+
62
+ private
63
+
64
+ ##
65
+ # Assuming you're a Ruby Newbie reading this: The interpreter calls
66
+ # {{inherited}} on the superclass when a class is subclassed.
67
+ #
68
+ # For the non-newbies, we're just keeping track of all subclasses so
69
+ # we know what classes we can pick from.
70
+ #
71
+ # @param [Class] subclass the class that just inherited from this class
72
+ def inherited(subclass)
73
+ all_pickers << subclass
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,336 @@
1
+ require 'time'
2
+
3
+ module Amp
4
+ module Git
5
+
6
+ ##
7
+ # A Changeset is a simple way of accessing the repository within a certain
8
+ # revision. For example, if the user specifies revision # 36, or revision
9
+ # 3adf21, then we can look those up, and work within the repository at the
10
+ # moment of that revision.
11
+ class Changeset < Amp::Repositories::AbstractChangeset
12
+
13
+ attr_accessor :short_name
14
+ attr_accessor :repo
15
+ alias_method :repository, :repo
16
+
17
+ def initialize(repo, short_name)
18
+ @repo = repo
19
+ @short_name = short_name
20
+ end
21
+
22
+ def revision; short_name; end
23
+
24
+ ##
25
+ # Compares 2 changesets so we can sort them and whatnot
26
+ #
27
+ # @param [Changeset] other a changeset we will compare against
28
+ # @return [Integer] -1, 0, or 1. Typical comparison.
29
+ def <=>(other)
30
+ date <=> other.date
31
+ end
32
+
33
+ ##
34
+ # Iterates over every tracked file at this point in time.
35
+ #
36
+ # @return [Changeset] self, because that's how #each works
37
+ def each(&b)
38
+ all_files.each( &b)
39
+ self
40
+ end
41
+
42
+ ##
43
+ # the nodes that this node inherits from
44
+ #
45
+ # @return [Array<Abstract Changeset>]
46
+ def parents
47
+ parse!
48
+ @parents
49
+ end
50
+
51
+ ##
52
+ # Retrieve +filename+
53
+ #
54
+ # @return [AbstractVersionedFile]
55
+ def get_file(filename)
56
+ VersionedFile.new @repo, file, :revision => short_name
57
+ end
58
+ alias_method :[], :get_file
59
+
60
+ ##
61
+ # When was the changeset made?
62
+ #
63
+ # @return [Time]
64
+ def date
65
+ parse!
66
+ @date
67
+ end
68
+
69
+ ##
70
+ # The user who made the changeset
71
+ #
72
+ # @return [String] the user who made the changeset
73
+ def user
74
+ parse!
75
+ @user
76
+ end
77
+
78
+ ##
79
+ # Which branch this changeset belongs to
80
+ #
81
+ # @return [String] the user who made the changeset
82
+ def branch
83
+ parse!
84
+ raise NotImplementedError.new("branch() must be implemented by subclasses of AbstractChangeset.")
85
+ end
86
+
87
+ ##
88
+ # @return [String]
89
+ def description
90
+ parse!
91
+ @description
92
+ end
93
+
94
+ ##
95
+ # What files have been altered in this changeset?
96
+ #
97
+ # @return [Array<String>]
98
+ def altered_files
99
+ parse!
100
+ @altered_files
101
+ end
102
+
103
+ ##
104
+ # Returns a list of all files that are tracked at this current revision.
105
+ #
106
+ # @return [Array<String>] the files tracked at the given revision
107
+ def all_files
108
+ parse!
109
+ @all_files
110
+ end
111
+
112
+ # Is this changeset a working changeset?
113
+ #
114
+ # @return [Boolean] is the changeset representing the working directory?
115
+ def working?
116
+ false
117
+ end
118
+
119
+ ##
120
+ #
121
+ def to_templated_s(opts={})
122
+ username = user
123
+ files = altered_files
124
+ type = opts[:template_type] || 'log'
125
+
126
+ added = opts[:added] || []
127
+ removed = opts[:removed] || []
128
+ updated = opts[:updated] || []
129
+ config = opts
130
+
131
+ return "" if opts[:no_output]
132
+
133
+ config = opts
134
+
135
+ template = opts[:template]
136
+ template = "default-#{type}" if template.nil? || template.to_s == "default"
137
+
138
+ template = Support::Template['git', template]
139
+ template.render({}, binding)
140
+ end
141
+
142
+ private
143
+
144
+ # yeah, i know, you could combine these all into one for a clean sweep.
145
+ # but it's clearer this way
146
+ def parse!
147
+ return if @parsed
148
+
149
+ # the parents
150
+ log_data = `git log -1 #{short_name}^ 2> /dev/null`
151
+
152
+ # DETERMINING PARENTS
153
+ dad = log_data[/^commit (.+)$/, 1]
154
+ dad = dad ? dad[0..6] : nil
155
+ mom = nil
156
+
157
+ if log_data =~ /^Merge: (.+)\.\.\. (.+)\.\.\.$/ # Merge: 1c002dd... 35cfb2b...
158
+ dad = $1 # just have them both use the short name, nbd
159
+ mom = $2
160
+ end
161
+
162
+ @parents = [dad, mom].compact.map {|r| Changeset.new repo, r }
163
+
164
+ # the actual changeset
165
+ log_data = `git log -1 #{short_name} 2> /dev/null`
166
+
167
+ # DETERMINING DATE
168
+ @date = Time.parse log_data[/^Date:\s+(.+)$/, 1]
169
+
170
+ # DETERMINING USER
171
+ @user = log_data[/^Author:\s+(.+)$/, 1]
172
+
173
+ # DETERMINING DESCRIPTION
174
+ @description = log_data.split("\n")[4..-1].map {|l| l.strip }.join "\n"
175
+
176
+ # ALTERED FILES
177
+ @altered_files = `git log -1 #{short_name} --pretty=oneline --name-only 2> /dev/null`.split("\n")[1..-1]
178
+
179
+ # ALL FILES
180
+ # @all_files is also sorted. Hooray!
181
+ @all_files = `git ls-tree -r #{short_name}`.split("\n").map do |line|
182
+ # 100644 blob cdbeb2a42b714a4db49293c87fec4e180d07d44f .autotest
183
+ line[/^\d+ \w+ \w+\s+(.+)$/, 1]
184
+ end
185
+
186
+ @parsed = true
187
+ end
188
+
189
+ end
190
+
191
+ class WorkingDirectoryChangeset < Amp::Repositories::AbstractChangeset
192
+
193
+ attr_accessor :repo
194
+ alias_method :repository, :repo
195
+
196
+ def initialize(repo, opts={:text => ''})
197
+ @repo = repo
198
+ @text = opts[:text]
199
+ @date = Time.parse opts[:date].to_s
200
+ @user = opts[:user]
201
+ @parents = opts[:parents].map {|p| Changeset.new(@repo, p) } if opts[:parents]
202
+ @status = opts[:changes]
203
+ end
204
+
205
+ ##
206
+ # the nodes that this node inherits from
207
+ #
208
+ # @return [Array<Abstract Changeset>]
209
+ def parents
210
+ @parents || (parse! && @parents)
211
+ end
212
+
213
+ def revision; nil; end
214
+
215
+ ##
216
+ # Retrieve +filename+
217
+ #
218
+ # @return [AbstractVersionedFile]
219
+ def get_file(filename)
220
+ VersionedWorkingFile.new @repo, filename
221
+ end
222
+ alias_method :[], :get_file
223
+
224
+ ##
225
+ # When was the changeset made?
226
+ #
227
+ # @return [Time]
228
+ def date
229
+ Time.now
230
+ end
231
+
232
+ ##
233
+ # The user who made the changeset
234
+ #
235
+ # @return [String] the user who made the changeset
236
+ def user
237
+ @user ||= @repo.config.username
238
+ end
239
+
240
+ ##
241
+ # Which branch this changeset belongs to
242
+ #
243
+ # @return [String] the user who made the changeset
244
+ def branch
245
+ @branch ||= `git branch 2> /dev/null`[/\*\s(.+)$/, 1]
246
+ end
247
+
248
+ ##
249
+ # @return [String]
250
+ def description
251
+ @text || ''
252
+ end
253
+
254
+ def status
255
+ @status ||= @repo.status :unknown => true
256
+ end
257
+
258
+ ##
259
+ # Iterates over every tracked file at this point in time.
260
+ #
261
+ # @return [Changeset] self, because that's how #each works
262
+ def each(&b)
263
+ all_files.each( &b)
264
+ self
265
+ end
266
+
267
+ ##
268
+ # Returns a list of all files that are tracked at this current revision.
269
+ #
270
+ # @return [Array<String>] the files tracked at the given revision
271
+ def all_files
272
+ @all_files ||= `git ls-files 2> /dev/null`.split("\n")
273
+ end
274
+
275
+ # Is this changeset a working changeset?
276
+ #
277
+ # @return [Boolean] is the changeset representing the working directory?
278
+ def working?
279
+ true
280
+ end
281
+
282
+ ##
283
+ # Recursively walk the directory tree, getting all files that +match+ says
284
+ # are good.
285
+ #
286
+ # @param [Amp::Match] match how to select the files in the tree
287
+ # @param [Boolean] check_ignored (false) should we check for ignored files?
288
+ # @return [Array<String>] an array of filenames in the tree that match +match+
289
+ def walk(match, check_ignored = false)
290
+ tree = @repo.staging_area.walk true, check_ignored, match
291
+ tree.keys.sort
292
+ end
293
+
294
+ # What files have been altered in this changeset?
295
+ def altered_files; `git show --name-only #{short_name} 2> /dev/null`.split("\n"); end
296
+ # What files have changed?
297
+ def modified; status[:modified]; end
298
+ # What files have we added?
299
+ def added; status[:added]; end
300
+ # What files have been removed?
301
+ def removed; status[:removed]; end
302
+ # What files have been deleted (but not officially)?
303
+ def deleted; status[:deleted]; end
304
+ # What files are hanging out, but untracked?
305
+ def unknown; status[:unknown]; end
306
+ # What files are pristine since the last revision?
307
+ def clean; status[:normal]; end
308
+
309
+ # yeah, i know, you could combine these all into one for a clean sweep.
310
+ # but it's clearer this way
311
+ def parse!
312
+ return if @parsed
313
+
314
+ log_data = `git log -1 HEAD 2> /dev/null`
315
+
316
+ unless log_data.empty?
317
+ # DETERMINING PARENTS
318
+ commit = log_data[/^commit (.+)$/, 1]
319
+ dad = commit ? commit[0..6] : nil
320
+ mom = nil
321
+
322
+ if log_data =~ /^Merge: (.+)\.\.\. (.+)\.\.\.$/ # Merge: 1c002dd... 35cfb2b...
323
+ dad = $1 # just have them both use the short name, nbd
324
+ mom = $2
325
+ end
326
+
327
+ @parents = [dad, mom].compact.map {|p| Changeset.new @repo, p }
328
+ else
329
+ @parents = []
330
+ end
331
+ @parsed = true
332
+ end
333
+
334
+ end
335
+ end
336
+ end