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,500 @@
1
+ module Amp
2
+ module Mercurial
3
+ module RevlogSupport
4
+ include Node
5
+
6
+ ##
7
+ # This class represents one revision entry in the index.
8
+ #
9
+ # Format on disk (in BitStruct notation):
10
+ #
11
+ # default_options :endian => :network
12
+ #
13
+ # signed :offset_flags, 64
14
+ # signed :compressed_len, 32
15
+ # signed :uncompressed_len, 32
16
+ # signed :base_rev, 32
17
+ # signed :link_rev, 32
18
+ # signed :parent_one_rev, 32
19
+ # signed :parent_two_rev, 32
20
+ # char :node_id, 160
21
+ # pad :padding, 96
22
+ #
23
+ # [offset_flags] - this is a double-word (8 bytes) - that combines the offset into the data file
24
+ # and any flags about the entry
25
+ # [compressed_len] - this is the length of the data when compressed
26
+ # [uncompresed_len] - length of the data uncompresed
27
+ # [base_rev] - the revision of the filelog
28
+ # [link_rev] - the revision of the whole repo where this was attached
29
+ # [parent_one_rev] - the parent revision the revision. Even if it's not a merge,
30
+ # it will have at least this parent entry
31
+ # [parent_two_rev] - if the revision is a merge, then it will have a second parent.
32
+ class IndexEntry < Struct.new(:offset_flags, :compressed_len, :uncompressed_len, :base_rev,
33
+ :link_rev, :parent_one_rev, :parent_two_rev, :node_id)
34
+ include Comparable
35
+
36
+ INDEX_FORMAT_NG = "Q NNNNNN a20 x12"
37
+ BLOCK_SIZE = 64
38
+
39
+ def initialize(*args)
40
+ if args.size == 1 && args[0].respond_to?(:read)
41
+ super(*(args[0].read(BLOCK_SIZE).unpack(INDEX_FORMAT_NG)))
42
+ else
43
+ super(*args)
44
+ end
45
+ end
46
+
47
+ def to_s
48
+ fix_signs
49
+ ret = self.to_a.pack(INDEX_FORMAT_NG)
50
+ fix_signs
51
+ ret
52
+ end
53
+
54
+ # Fixes the values to force them to be signed (possible to be negative)
55
+ def fix_signs
56
+ self.offset_flags = self.offset_flags.byte_swap_64
57
+ self.parent_one_rev = self.parent_one_rev.to_signed_32
58
+ self.parent_two_rev = self.parent_two_rev.to_signed_32
59
+
60
+ self
61
+ end
62
+
63
+ # Compares this entry to another
64
+ def <=> other_entry
65
+ this.base_rev <=> other_entry.base_rev
66
+ end
67
+
68
+ # Gives a hash value so we can stick these entries into a hash
69
+ def hash
70
+ node_id.hash
71
+ end
72
+ end
73
+
74
+ ##
75
+ # = Index
76
+ # The Index is a file that keeps track of the revision data. All revisions
77
+ # go through an index. This class, {Index}, is the most basic class. It
78
+ # provides an Index.parse method so that you can read a file in, and
79
+ # the class will figure out which version it is, and all that jazz.
80
+ #
81
+ class Index
82
+ include Mercurial::RevlogSupport::Support
83
+ include Enumerable
84
+
85
+ # This is the packed format of the version number of the index.
86
+ VERSION_FORMAT = "N"
87
+ # The version (either {REVLOG_VERSION_0} or {REVLOG_VERSION_NG})
88
+ attr_reader :version
89
+ # The actual lookup array. Each revision has an index in this list, and
90
+ # that list also happens to be relatively chronological.
91
+ attr_reader :index
92
+ # This node_map lets you look up node_id's (NOT INDEX-NUMBERS),
93
+ # which are strings, and get the index into @index of the
94
+ # node you're looking up.
95
+ attr_reader :node_map
96
+ # This allows a couple neat caching tricks to speed up acces and cut
97
+ # down on IO.
98
+ attr_reader :chunk_cache
99
+ # This is the path to the index file. Can be a URL. I don't care and
100
+ # neither should you.
101
+ attr_reader :indexfile
102
+ # This is the raw cache data. Another helpful bit.
103
+ attr_accessor :cache
104
+
105
+ ##
106
+ # This method will parse the file at the provided path and return
107
+ # an appropriate Index object. The object will be of the class that
108
+ # fits the file provided, based on version and whether
109
+ # it is inline.
110
+ #
111
+ # @param [String] inputfile the filepath to load and parse
112
+ # @return [Index] Some subclassed version of Index that's parsed the file
113
+ def self.parse(opener, inputfile)
114
+ versioninfo = REVLOG_DEFAULT_VERSION
115
+ i = ""
116
+ begin
117
+ opener.open(inputfile) do |f|
118
+ i = f.read(4)
119
+ end
120
+ versioninfo = i.unpack(VERSION_FORMAT).first if i.size > 0
121
+ # Check if the data is with the index info.
122
+ inline = (versioninfo & REVLOG_NG_INLINE_DATA > 0)
123
+ # Get the version number of the index file.
124
+ version = Support.get_version versioninfo
125
+ rescue
126
+ inline = true
127
+ version = REVLOG_VERSION_NG
128
+ end
129
+
130
+ # Pick a subclass for the version and in-line-icity we found.
131
+ case [version, inline]
132
+ when [REVLOG_VERSION_0, false]
133
+ IndexVersion0.new opener, inputfile
134
+ when [REVLOG_VERSION_NG, false]
135
+ IndexVersionNG.new opener, inputfile
136
+ when [REVLOG_VERSION_NG, true]
137
+ IndexInlineNG.new opener, inputfile
138
+ else
139
+ raise RevlogError.new("Invalid format: #{version} flags: #{get_flags(versioninfo)}")
140
+ end
141
+ end
142
+
143
+ ##
144
+ # Returns whether a given node ID exists, without throwing a lookup error.
145
+ #
146
+ # @param [String] node the node_id to lookup. 20 bytes, binary.
147
+ # @return [Boolean] is the node in the index?
148
+ def has_node?(node)
149
+ @node_map[node]
150
+ end
151
+
152
+ ##
153
+ # This provides quick lookup into the index, based on revision
154
+ # number. NOT ID's, index numbers.
155
+ #
156
+ # @param [Fixnum] index the index to look up
157
+ # @return [IndexEntry] the revision requested
158
+ def [](index)
159
+ @index[index]
160
+ end
161
+
162
+ ##
163
+ # This method writes the index to file. Pretty 1337h4><.
164
+ #
165
+ # @param [String] index_file the path to the index file.
166
+ def write_entry(index_file, journal)
167
+ raise abort("Use a concrete class. Yeah, I called it a concrete class. I hate" +
168
+ " Java too, but you tried to use an abstract class.")
169
+ end
170
+
171
+ ##
172
+ # Adds an item to the index safely. DO NOT USE some_index.index <<. It's
173
+ # some_index << entry.
174
+ #
175
+ # @param [[Integer, Integer, Integer, Integer, Integer, Integer,
176
+ # Integer, Integer]] item the data to enter as an entry. See the spec fo
177
+ # {IndexEntry}.
178
+ def <<(item)
179
+ @index.insert(-2, IndexEntry.new(*item)) if item.is_a? Array
180
+ @index.insert(-2, item) if item.is_a? IndexEntry
181
+ # leave the terminating entry intact
182
+ end
183
+
184
+ # Returns the number of entries in the index, including the null revision
185
+ def size
186
+ @index.size
187
+ end
188
+
189
+ # Iterates over each entry in the index, including the null revision
190
+ def each(&b)
191
+ @index.each(&b)
192
+ end
193
+ end
194
+
195
+ ##
196
+ # = IndexVersion0
197
+ # This handles old versions of the index file format.
198
+ # These are apparently so old they were version 0.
199
+ class IndexVersion0 < Index
200
+ # Binary data format for each revision entry
201
+ INDEX_FORMAT_V0 = "N4 a20 a20 a20"
202
+ # The size of each revision entry
203
+ BLOCK_SIZE = (4 * 4) + (3 * 20)
204
+ # The offset into the entry where the SHA1 is stored for validation
205
+ SHA1_OFFSET = 56
206
+
207
+ # Return the size of 1 entry
208
+ def entry_size; BLOCK_SIZE; end
209
+ # Return what version this index is
210
+ def version; REVLOG_VERSION_0; end
211
+ # Does the index store the data with the revision index entries?
212
+ def inline?; false; end
213
+
214
+ # Initializes the index by reading from the provided filename. Users probably
215
+ # don't need this because {Index}#{parse} will do this for you.
216
+ #
217
+ # @param [String] inputfile the path to the index file
218
+ def initialize(opener, inputfile)
219
+ @opener = opener
220
+ @indexfile = inputfile
221
+ @node_map = {Node::NULL_ID => Node::NULL_REV}
222
+ @index = []
223
+ n = offset = 0
224
+ if File.exists?(opener.join(inputfile))
225
+ opener.open(inputfile) do |f|
226
+
227
+ while !f.eof?
228
+ current = f.read(BLOCK_SIZE)
229
+ entry = current.unpack(INDEX_FORMAT_V0)
230
+ new_entry = IndexEntry.new(offset_version(entry[0],0), entry[1], -1, entry[2], entry[3],
231
+ (@node_map[entry[4]] || nullrev), (@node_map[entry[5]] || nullrev),
232
+ entry[6])
233
+ @index << new_entry.fix_signs
234
+ @node_map[entry[6]] = n
235
+ n += 1
236
+ end
237
+ end
238
+ end
239
+ @cache = nil
240
+ self
241
+ end
242
+
243
+ ##
244
+ # This method writes the index to file. Pretty 1337h4><.
245
+ #
246
+ # @param [String] index_file the path to the index file.
247
+ def write_entry(index_file, entry, journal, data)
248
+ curr = self.size - 1
249
+
250
+ node_map[entry.last] = curr
251
+
252
+ link = entry[4]
253
+ data_file = index_file[0..-3] + ".d"
254
+
255
+ entry = pack_entry entry, link
256
+
257
+ data_file_handle = open(data_file, "a")
258
+ index_file_handle = open(index_file, "a+")
259
+
260
+ journal << {:file => data_file, :offset => offset}
261
+ journal << {:file => index_file, :offset => curr * entry.size}
262
+
263
+ data_file_handle.write data[:compression] if data[:compression].any?
264
+ data_file_handle.write data[:text]
265
+
266
+ data_file_handle.flush
267
+ index_file_handle.write entry
268
+ end
269
+ ##
270
+ # This takes an entry and packs it into binary data for writing to
271
+ # the file.
272
+ #
273
+ # @param [IndexEntry] entry the revision entry to pack up for writing
274
+ # @param rev unused by version 0. Kept to make the interface uniform
275
+ # @return [String] the Binary data packed up for writing.
276
+ def pack_entry(entry, rev)
277
+ entry = IndexEntry.new(*entry) if entry.kind_of? Array
278
+ entry.fix_signs
279
+ e2 = [RevlogSupport::Support.offset_type(entry.offset_flags),
280
+ entry.compressed_len, entry.base_rev, entry.link_rev,
281
+ @index[entry.parent_one_rev].node_id,
282
+ @index[entry.parent_two_rev].node_id, entry.node_id]
283
+ e2.pack(INDEX_FORMAT_V0)
284
+ end
285
+ end
286
+
287
+ ##
288
+ # = IndexVersionNG
289
+ # This is the current version of the index. I'm not sure why they call
290
+ # it Version 'NG' but they do. An index of this type is *not* inline.
291
+ class IndexVersionNG < Index
292
+ VERSION_FORMAT = "N"
293
+ # The binary format used for pack/unpack
294
+ INDEX_FORMAT_NG = "Q NNNNNN a20 x12"
295
+ # The distance into the entry to go to find the SHA1 hash
296
+ SHA1_OFFSET = 32
297
+ # The size of a single block in the index
298
+ BLOCK_SIZE = 8 + (6 * 4) + 20 + 12
299
+
300
+ ##
301
+ # Initializes the index by parsing the given file.
302
+ #
303
+ # @param [String] inputfile the path to the index file.
304
+ def initialize(opener, inputfile)
305
+ @opener = opener
306
+ @indexfile = inputfile
307
+ @cache = nil
308
+ @index = []
309
+ @node_map = {Node::NULL_ID => Node::NULL_REV}
310
+
311
+ opened = parse_file
312
+
313
+ if opened
314
+ first_entry = @index[0]
315
+ type = get_version(first_entry.offset_flags)
316
+ first_entry.offset_flags = offset_version(0, type) #turn off inline
317
+ @index[0] = first_entry
318
+ end
319
+
320
+ @index << IndexEntry.new(0,0,0,-1,-1,-1,-1,Node::NULL_ID)
321
+ end
322
+
323
+ ##
324
+ # returns the size of 1 block in this type of index
325
+ def entry_size; BLOCK_SIZE; end
326
+
327
+ # returns the version number of the index
328
+ def version; REVLOG_VERSION_NG; end
329
+ # returns whether or not the index stores data with revision info
330
+ def inline?; false; end
331
+
332
+ ##
333
+ # Parses each index entry. Internal use only.
334
+ #
335
+ # @return [Boolean] whether the file was opened
336
+ def parse_file
337
+ n = 0
338
+ begin
339
+ @opener.open(@indexfile,"r") do |f|
340
+ until f.eof?
341
+ # read the entry
342
+ entry = IndexEntry.new(f).fix_signs
343
+ # store it in the map
344
+ @node_map[entry.node_id] = n
345
+ # add it to the index
346
+ @index << entry
347
+ n += 1
348
+ end
349
+ end
350
+ return true
351
+ rescue Errno::ENOENT
352
+ return false
353
+ end
354
+ end
355
+
356
+ ##
357
+ # Packs up the revision entry for writing to the binary file.
358
+ #
359
+ # @param [IndexEntry] entry this is the entry that has to be formatted
360
+ # into binary.
361
+ # @param [Fixnum] rev this is the index number of the entry - if it's
362
+ # the first revision (rev == 0) then we treat it slightly differently.
363
+ # @return [String] the entry converted into binary suitable for writing.
364
+ def pack_entry(entry, rev)
365
+ entry = IndexEntry.new(*entry) if entry.kind_of? Array
366
+ p = entry.to_s
367
+ if rev == 0 || rev == 1
368
+ p = [version].pack(VERSION_FORMAT) + p[4..-1] # initial entry
369
+ end
370
+ p
371
+ end
372
+
373
+ ##
374
+ # This method writes the index to file. Pretty 1337h4><.
375
+ #
376
+ # @param [String] index_file the path to the index file.
377
+ def write_entry(index_file, entry, journal, data, index_file_handle = nil)
378
+ curr = self.size - 1
379
+
380
+ link = (entry.is_a? Array) ? entry[4] : entry.link_rev
381
+ data_file = index_file[0..-3] + ".d"
382
+
383
+ entry = pack_entry entry, link
384
+
385
+ @opener.open(data_file, "a+") do |data_file_handle|
386
+ data_offset = data_file_handle.tell
387
+
388
+ data_file_handle.write data[:compression] if data[:compression].any?
389
+ data_file_handle.write data[:text]
390
+ data_file_handle.flush
391
+
392
+ journal << {:file => data_file, :offset => data_offset, :data => curr}
393
+ end
394
+
395
+ index_file_handle ||= (opened = true && @opener.open(index_file, "a+"))
396
+
397
+ offset = index_file_handle.tell
398
+ index_file_handle.write entry
399
+ index_file_handle.close if opened
400
+
401
+ journal << {:file => index_file, :offset => offset, :data => curr}
402
+ end
403
+
404
+ end
405
+
406
+ ##
407
+ # = LazyIndex
408
+ # When this gets filled in, this class will let us access an index without loading
409
+ # every entry first. This is handy because index files can get pretty fuckin big.
410
+ class LazyIndex < Index
411
+
412
+ end
413
+
414
+ ##
415
+ # = IndexInlineNG
416
+ # This is a variant of the current version of the index format, in which the data
417
+ # is stored in the actual index file itself, right after the little revision
418
+ # entry block (see {IndexEntry}). This means less IO, which is good.
419
+ #
420
+ class IndexInlineNG < IndexVersionNG
421
+ VERSION_FORMAT = "N"
422
+ # We're inline!
423
+ INDEX_FORMAT_NG = "Q NNNNNN a20 x12"
424
+ # The distance into the entry to go to find the SHA1 hash
425
+ SHA1_OFFSET = 32
426
+ # The size of a single block in the index
427
+ BLOCK_SIZE = 8 + (6 * 4) + 20 + 12
428
+
429
+ def inline?; true; end
430
+ def version; REVLOG_VERSION_NG | REVLOG_NG_INLINE_DATA; end
431
+ def pack_entry(entry, rev)
432
+ entry = IndexEntry.new(*entry) if entry.kind_of? Array
433
+ p = entry.to_s
434
+ if rev == 0 || rev == 1
435
+ p = [version].pack(VERSION_FORMAT) + p[4..-1] # initial entry
436
+ end
437
+ p
438
+ end
439
+
440
+
441
+ ##
442
+ # @todo "not sure what the 0 is for yet or i'd make this a hash" (see code)
443
+ # This method overrides the parent class' method that reads entries sequentially
444
+ # from the index file. Each entry is followed by the data for that revision
445
+ # so we have to skip over that data for our purposes.
446
+ def parse_file
447
+ n = offset = 0
448
+ begin
449
+ @opener.open(@indexfile,"r") do |f|
450
+ return false if f.eof?
451
+ while !f.eof?
452
+ # read 1 entry
453
+ entry = IndexEntry.new(f).fix_signs
454
+ # store it in the map
455
+ @node_map[entry.node_id] = n
456
+ # add it to the index
457
+ @index << entry
458
+ n += 1
459
+ break if entry.compressed_len < 0
460
+
461
+ # skip past the data, too!
462
+ f.seek(entry.compressed_len, IO::SEEK_CUR)
463
+ end
464
+ end
465
+ return true
466
+ rescue Errno::ENOENT
467
+ return false
468
+ end
469
+ end
470
+
471
+ ##
472
+ # This method writes the index entry to file. Pretty 1337h4><.
473
+ #
474
+ # @param [String] index_file the path to the index file.
475
+ def write_entry(index_file, entry, journal, data, index_file_handle = nil)
476
+ curr = self.size - 1
477
+ prev = curr - 1
478
+
479
+ link = (entry.is_a? Array) ? entry[4] : entry.link_rev
480
+
481
+ entry = pack_entry entry, curr
482
+
483
+ index_file_handle ||= (opened = true && @opener.open(index_file, "a+"))
484
+
485
+ offset = index_file_handle.tell
486
+
487
+ index_file_handle.write entry
488
+ index_file_handle.write data[:compression] if data[:compression].any?
489
+ index_file_handle.write data[:text]
490
+
491
+ index_file_handle.close if opened
492
+
493
+ journal << {:file => index_file, :offset => offset, :data => curr}
494
+
495
+ end
496
+
497
+ end
498
+ end
499
+ end
500
+ end