amp 0.5.2 → 0.5.3

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 (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