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