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,192 @@
1
+ module Amp
2
+ module Repositories
3
+ module Git
4
+ class StagingArea < Amp::Repositories::AbstractStagingArea
5
+
6
+ attr_accessor :repo
7
+ attr_accessor :vcs_dir
8
+
9
+ def initialize(repo)
10
+ @repo = repo
11
+ @vcs_dir = '.git'
12
+ end
13
+
14
+ ##
15
+ # Marks a file to be added to the repository upon the next commit.
16
+ #
17
+ # @param [[String]] filenames a list of files to add in the next commit
18
+ # @return [Boolean] true for success, false for failure
19
+ def add(*filenames)
20
+ `git add #{filenames.join ' '} 2> /dev/null`
21
+ true
22
+ end
23
+
24
+ ##
25
+ # Marks a file to be removed from the repository upon the next commit. Last argument
26
+ # can be a hash, which can take an :unlink key, specifying whether the files should actually
27
+ # be removed or not.
28
+ #
29
+ # @param [String, Array<String>] filenames a list of files to remove in the next commit
30
+ # @return [Boolean] true for success, false for failure
31
+ def remove(*filenames)
32
+ `git rm #{filenames.join ' '} 2> /dev/null`
33
+ true
34
+ end
35
+
36
+ ##
37
+ # Set +file+ as normal and clean. Un-removes any files marked as removed, and
38
+ # un-adds any files marked as added.
39
+ #
40
+ # @param [String, Array<String>] files the name of the files to mark as normal
41
+ # @return [Boolean] success marker
42
+ def normal(*files)
43
+ # Do nothing...
44
+ true
45
+ end
46
+
47
+ ##
48
+ # Mark the files as untracked.
49
+ #
50
+ # @param [Array<String>] files the name of the files to mark as untracked
51
+ # @return [Boolean] success marker
52
+ def forget(*files)
53
+ `git rm --cached #{files.join ' '} 2> /dev/null`
54
+ true
55
+ end
56
+
57
+ ##
58
+ # Marks a file to be copied from the +from+ location to the +to+ location
59
+ # in the next commit, while retaining history.
60
+ #
61
+ # @param [String] from the source of the file copy
62
+ # @param [String] to the destination of the file copy
63
+ # @return [Boolean] true for success, false for failure
64
+ def copy(from, to)
65
+ `git cp #{from} #{to} 2> /dev/null`
66
+ true
67
+ end
68
+
69
+ ##
70
+ # Marks a file to be moved from the +from+ location to the +to+ location
71
+ # in the next commit, while retaining history.
72
+ #
73
+ # @param [String] from the source of the file move
74
+ # @param [String] to the destination of the file move
75
+ # @return [Boolean] true for success, false for failure
76
+ def move(from, to)
77
+ `git mv #{from} #{to} 2> /dev/null`
78
+ true
79
+ end
80
+
81
+ ##
82
+ # Marks a modified file to be included in the next commit.
83
+ # If your VCS does this implicitly, this should be defined as a no-op.
84
+ #
85
+ # @param [String, Array<String>] filenames a list of files to include for committing
86
+ # @return [Boolean] true for success, false for failure
87
+ def include(*filenames)
88
+ add filenames
89
+ end
90
+ alias_method :stage, :include
91
+
92
+ ##
93
+ # Mark a modified file to not be included in the next commit.
94
+ # If your VCS does not include this idea because staging a file is implicit, this should
95
+ # be defined as a no-op.
96
+ #
97
+ # @param [[String]] filenames a list of files to remove from the staging area for committing
98
+ # @return [Boolean] true for success, false for failure
99
+ def exclude(*filenames)
100
+ `git rm --cached #{filenames.join ' '} 2> /dev/null`
101
+ true
102
+ end
103
+ alias_method :unstage, :exclude
104
+
105
+ ##
106
+ # Returns a Symbol.
107
+ #
108
+ # If you call localrepo#status from this method... well...
109
+ # I DARE YOU!
110
+ def file_status(filename)
111
+ parse!
112
+ inverted = @status.inject({}) do |h, (k, v)|
113
+ v.each {|v_| h[v_] = k }
114
+ h
115
+ end
116
+
117
+ # lame hack, i know
118
+ case val = inverted[filename]
119
+ when :modified
120
+ :normal
121
+ else
122
+ val
123
+ end
124
+ end
125
+
126
+ # modified, lookup, or clean
127
+ # in this case, since we're shelling out,
128
+ # only modified or clean
129
+ def file_precise_status(filename, st)
130
+ parse!
131
+ inverted = @status.inject({}) do |h, (k, v)|
132
+ v.each {|v_| h[v_] = k }
133
+ h
134
+ end
135
+
136
+ # bleh this code sucks
137
+ if inverted[filename] == :modified
138
+ :modified
139
+ else
140
+ :clean
141
+ end
142
+ end
143
+
144
+ ##
145
+ # Calculates the difference (in bytes) between a file and its last tracked state.
146
+ #
147
+ # Supplements the built-in #status method so that its output will include deltas.
148
+ #
149
+ # @apioptional
150
+ # @param [String] file the filename to look up
151
+ # @param [File::Stats] st the current results of File.lstat(file)
152
+ # @return [Fixnum] the number of bytes difference between the file and
153
+ # its last tracked state.
154
+ def calculate_delta(file, st)
155
+ 0
156
+ end
157
+
158
+ def parse!
159
+ return if @parsed
160
+
161
+ @status = {}
162
+ data = `git status 2> /dev/null`.split("\n")
163
+ data.inject @status do |h, line|
164
+ case line
165
+ when /^#\s+(\w+):\s(.+)$/
166
+ h[$1.to_sym] = $2.strip
167
+ when /^#\s+new file:\s(.+)$/
168
+ h[:added] = $1.strip
169
+ when /^#\s+([^ ]+)$/
170
+ h[:untracked] = $1.strip
171
+ else
172
+ h
173
+ end
174
+ end
175
+
176
+ @parsed = true
177
+ end
178
+
179
+ ##
180
+ # Returns all files tracked by the repository *for the working directory* - not
181
+ # to be confused with the most recent changeset.
182
+ #
183
+ # @api
184
+ # @return [Array<String>] all files tracked by the repository at this moment in
185
+ # time, including just-added files (for example) that haven't been committed yet.
186
+ def all_files
187
+ Amp::Git::WorkingDirectoryChangeset.new(@repo).all_files
188
+ end
189
+ end
190
+ end
191
+ end
192
+ end
@@ -0,0 +1,119 @@
1
+ module Amp
2
+ module Git
3
+
4
+ ##
5
+ # This class allows you to access a file at a given revision in the repo's
6
+ # history. You can compare them, sort them, access the changeset, and
7
+ # all sorts of stuff.
8
+ class VersionedFile < Amp::Repositories::AbstractVersionedFile
9
+
10
+ attr_accessor :revision
11
+ attr_accessor :path
12
+ attr_accessor :repo
13
+
14
+ def initialize(repo, path, opts={})
15
+ @repo = repo
16
+ @path = path
17
+ @revision = opts[:revision]
18
+ end
19
+
20
+ ##
21
+ # The changeset to which this versioned file belongs.
22
+ #
23
+ # @return [AbstractChangeset]
24
+ def changeset
25
+ @changeset ||= Changeset.new @repo, @revision
26
+ end
27
+
28
+ ##
29
+ # The size of this file
30
+ #
31
+ # @return [Integer]
32
+ def size
33
+ @size ||= data.size
34
+ end
35
+
36
+ ##
37
+ # The contents of a file at the given revision
38
+ #
39
+ # @return [String] the data at the current revision
40
+ def data
41
+ @data ||= `git show #{revision}:#{path} 2> /dev/null`
42
+ end
43
+
44
+ ##
45
+ # The hash value for sticking this fucker in a hash.
46
+ #
47
+ # @return [Integer]
48
+ def hash
49
+ "#{size}--#{path}--#{repo.root}--#{revision} 2> /dev/null".hash
50
+ end
51
+
52
+ ##
53
+ # Has this file been renamed? If so, return some useful info
54
+ def renamed?
55
+ nil
56
+ end
57
+
58
+ ##
59
+ # Compares to either a bit of text or another versioned file.
60
+ # Returns true if different, false for the same.
61
+ # (much like <=> == 0 for the same)
62
+ #
63
+ # @param [AbstractVersionedFile, String] item what we're being compared to
64
+ # @return [Boolean] true if different, false if same.
65
+ def cmp(item)
66
+ return data == item if item.is_a? String
67
+
68
+ not (data == item.data &&
69
+ size == item.size &&
70
+ revision == item.revision &&
71
+ repo.root == item.repo.root )
72
+ end
73
+
74
+ ##
75
+ # Are two versioned files the same? This means same path and revision indexes.
76
+ #
77
+ # @param [AbstractVersionedFile] vfile what we're being compared to
78
+ # @return [Boolean]
79
+ def ==(vfile)
80
+ !cmp(vfile)
81
+ end
82
+
83
+ ##
84
+ # Gets the flags for this file ('x', 'l', or '')
85
+ #
86
+ # @return [String] 'x', 'l', or ''
87
+ def flags
88
+ '' # because git doesn't track them
89
+ end
90
+
91
+ end
92
+
93
+ ##
94
+ # This is a VersionedFile, except it's in the working directory, so its data
95
+ # is stored on disk in the actual file. Other than that, it's basically the
96
+ # same in its interface!
97
+ class VersionedWorkingFile < VersionedFile
98
+
99
+ ##
100
+ # Initializes a new working dir file - slightly different semantics here
101
+ def initialize(repo, path, opts={})
102
+ super(repo, path, opts)
103
+ end
104
+
105
+ def size
106
+ File.stat(repo.join(path)).size
107
+ end
108
+
109
+ def data
110
+ File.read repo.working_join(path)
111
+ end
112
+
113
+ def changeset
114
+ WorkingDirectoryChangeset.new repo
115
+ end
116
+
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,164 @@
1
+ module Amp
2
+ module Repositories
3
+ module Git
4
+
5
+ class LocalRepository < Amp::Repositories::AbstractLocalRepository
6
+
7
+ attr_accessor :root
8
+ attr_accessor :config
9
+ attr_accessor :file_opener
10
+ attr_accessor :git_opener
11
+ attr_accessor :staging_area
12
+
13
+ def initialize(path="", create=false, config=nil)
14
+ super(path, create, config)
15
+
16
+ @config = config
17
+
18
+ @file_opener = Amp::Opener.new @root # This will open relative to the repo root
19
+ @file_opener.default = :open_file # these two are the same, pretty much
20
+ @git_opener = Amp::Opener.new @root # this will open relative to root/.git
21
+ @git_opener.default = :open_git # just with different defaults
22
+
23
+ @staging_area = Amp::Repositories::Git::StagingArea.new self
24
+
25
+ if create
26
+ init
27
+ end
28
+ end
29
+
30
+ def init(config=@config)
31
+ super(config)
32
+
33
+ `cd #{@root} && git init 2> /dev/null`
34
+ true
35
+ end
36
+
37
+ def commit(opts={})
38
+ add_all_files
39
+ string = "git commit #{opts[:user] ? "--author #{opts[:user].inspect}" : "" }" +
40
+ " #{opts[:empty_ok] ? "--allow-empty" : "" }" +
41
+ " #{opts[:message] ? "-m #{opts[:message].inspect}" : "" } 2> /dev/null"
42
+ string.strip!
43
+
44
+ system string
45
+ end
46
+
47
+ def add_all_files
48
+ staging_area.add status[:modified]
49
+ end
50
+
51
+ def forget(*files)
52
+ staging_area.forget *files
53
+ end
54
+
55
+ def [](rev)
56
+ case rev
57
+ when String
58
+ Amp::Git::Changeset.new self, rev
59
+ when nil
60
+ Amp::Git::WorkingDirectoryChangeset.new self
61
+ when 'tip', :tip
62
+ Amp::Git::Changeset.new self, parents[0]
63
+ when Integer
64
+ revs = `git log --pretty=oneline 2> /dev/null`.split("\n")
65
+ short_name = revs[revs.size - 1 - rev].split(' ').first
66
+ Amp::Git::Changeset.new self, short_name
67
+ end
68
+ end
69
+
70
+ def size
71
+ `git log --pretty=oneline 2> /dev/null`.split("\n").size
72
+ end
73
+
74
+ ##
75
+ # Write +text+ to +filename+, where +filename+
76
+ # is local to the root.
77
+ #
78
+ # @param [String] filename The file as relative to the root
79
+ # @param [String] text The text to write to said file
80
+ def working_write(filename, text)
81
+ file_opener.open filename, 'w' do |f|
82
+ f.write text
83
+ end
84
+ end
85
+
86
+ ##
87
+ # Determines if a file has been modified from :node1 to :node2.
88
+ #
89
+ # @return [Boolean] has it been modified
90
+ def file_modified?(file, opts={})
91
+ file_status(file, opts) == :included
92
+ end
93
+
94
+ ##
95
+ # Returns a Symbol.
96
+ # Possible results:
97
+ # :added (subset of :included)
98
+ # :removed
99
+ # :untracked
100
+ # :included (aka :modified)
101
+ # :normal
102
+ #
103
+ # If you call localrepo#status from this method... well...
104
+ # I DARE YOU!
105
+ def file_status(filename, opts={})
106
+ parse_status! opts
107
+ inverted = @status.inject({}) do |h, (k, v)|
108
+ v.each {|v_| h[v_] = k }
109
+ h
110
+ end
111
+
112
+ # Now convert it so it uses the same jargon
113
+ # we REALLY need to get the dirstate and localrepo on
114
+ # the same page here.
115
+ case inverted[filename]
116
+ when :modified
117
+ :included
118
+ when :added
119
+ :added
120
+ when :removed
121
+ :removed
122
+ when :unknown
123
+ :untracked
124
+ else
125
+ :normal
126
+ end
127
+
128
+ end
129
+
130
+ def parse_status!(opts={})
131
+ return if @parsed
132
+
133
+ data = `git status #{opts[:node1]}..#{opts[:node2]} 2> /dev/null`.split("\n")
134
+ @status = data.inject({}) do |h, line| # yeah i know stfu
135
+ case line
136
+ when /^#\s+(\w+):\s(.+)$/
137
+ h[$1.to_sym] = $2; h
138
+ when /^#\s+([^ ]+)$/
139
+ h[:unknown] = $1; h
140
+ else
141
+ h
142
+ end
143
+ end
144
+ @parsed = true
145
+ end
146
+
147
+ def parents
148
+ first = `git log -1 HEAD 2> /dev/null`
149
+ dad = first[/^commit (.+)$/, 1]
150
+ dad = dad ? dad[0..6] : nil
151
+ mom = nil
152
+
153
+ if first =~ /Merge: (.+)\.\.\. (.+)\.\.\.$/ # Merge: 1c002dd... 35cfb2b...
154
+ dad = $1 # just have them both use the short name, nbd
155
+ mom = $2
156
+ end
157
+
158
+ [dad, mom]
159
+ end
160
+
161
+ end
162
+ end
163
+ end
164
+ end