amp 0.5.0
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.
- data/.gitignore +1 -0
- data/.hgignore +26 -0
- data/AUTHORS +2 -0
- data/History.txt +6 -0
- data/LICENSE +37 -0
- data/MANIFESTO +7 -0
- data/Manifest.txt +294 -0
- data/README.md +129 -0
- data/Rakefile +102 -0
- data/SCHEDULE.markdown +12 -0
- data/STYLE +27 -0
- data/TODO.markdown +149 -0
- data/ampfile.rb +47 -0
- data/bin/amp +30 -0
- data/bin/amp1.9 +30 -0
- data/ext/amp/bz2/README.txt +39 -0
- data/ext/amp/bz2/bz2.c +1582 -0
- data/ext/amp/bz2/extconf.rb +77 -0
- data/ext/amp/bz2/mkmf.log +29 -0
- data/ext/amp/mercurial_patch/extconf.rb +5 -0
- data/ext/amp/mercurial_patch/mpatch.c +405 -0
- data/ext/amp/priority_queue/extconf.rb +5 -0
- data/ext/amp/priority_queue/priority_queue.c +947 -0
- data/ext/amp/support/extconf.rb +5 -0
- data/ext/amp/support/support.c +250 -0
- data/lib/amp.rb +200 -0
- data/lib/amp/commands/command.rb +507 -0
- data/lib/amp/commands/command_support.rb +137 -0
- data/lib/amp/commands/commands/config.rb +143 -0
- data/lib/amp/commands/commands/help.rb +29 -0
- data/lib/amp/commands/commands/init.rb +10 -0
- data/lib/amp/commands/commands/templates.rb +137 -0
- data/lib/amp/commands/commands/version.rb +7 -0
- data/lib/amp/commands/commands/workflow.rb +28 -0
- data/lib/amp/commands/commands/workflows/git/add.rb +65 -0
- data/lib/amp/commands/commands/workflows/git/copy.rb +27 -0
- data/lib/amp/commands/commands/workflows/git/mv.rb +23 -0
- data/lib/amp/commands/commands/workflows/git/rm.rb +60 -0
- data/lib/amp/commands/commands/workflows/hg/add.rb +53 -0
- data/lib/amp/commands/commands/workflows/hg/addremove.rb +86 -0
- data/lib/amp/commands/commands/workflows/hg/annotate.rb +46 -0
- data/lib/amp/commands/commands/workflows/hg/archive.rb +126 -0
- data/lib/amp/commands/commands/workflows/hg/branch.rb +28 -0
- data/lib/amp/commands/commands/workflows/hg/branches.rb +30 -0
- data/lib/amp/commands/commands/workflows/hg/bundle.rb +115 -0
- data/lib/amp/commands/commands/workflows/hg/clone.rb +95 -0
- data/lib/amp/commands/commands/workflows/hg/commit.rb +42 -0
- data/lib/amp/commands/commands/workflows/hg/copy.rb +31 -0
- data/lib/amp/commands/commands/workflows/hg/debug/dirstate.rb +32 -0
- data/lib/amp/commands/commands/workflows/hg/debug/index.rb +36 -0
- data/lib/amp/commands/commands/workflows/hg/default.rb +9 -0
- data/lib/amp/commands/commands/workflows/hg/diff.rb +30 -0
- data/lib/amp/commands/commands/workflows/hg/forget.rb +11 -0
- data/lib/amp/commands/commands/workflows/hg/heads.rb +25 -0
- data/lib/amp/commands/commands/workflows/hg/identify.rb +23 -0
- data/lib/amp/commands/commands/workflows/hg/import.rb +135 -0
- data/lib/amp/commands/commands/workflows/hg/incoming.rb +85 -0
- data/lib/amp/commands/commands/workflows/hg/info.rb +18 -0
- data/lib/amp/commands/commands/workflows/hg/log.rb +21 -0
- data/lib/amp/commands/commands/workflows/hg/manifest.rb +13 -0
- data/lib/amp/commands/commands/workflows/hg/merge.rb +53 -0
- data/lib/amp/commands/commands/workflows/hg/move.rb +28 -0
- data/lib/amp/commands/commands/workflows/hg/outgoing.rb +61 -0
- data/lib/amp/commands/commands/workflows/hg/pull.rb +74 -0
- data/lib/amp/commands/commands/workflows/hg/push.rb +20 -0
- data/lib/amp/commands/commands/workflows/hg/remove.rb +45 -0
- data/lib/amp/commands/commands/workflows/hg/resolve.rb +83 -0
- data/lib/amp/commands/commands/workflows/hg/revert.rb +53 -0
- data/lib/amp/commands/commands/workflows/hg/root.rb +13 -0
- data/lib/amp/commands/commands/workflows/hg/serve.rb +38 -0
- data/lib/amp/commands/commands/workflows/hg/status.rb +116 -0
- data/lib/amp/commands/commands/workflows/hg/tag.rb +69 -0
- data/lib/amp/commands/commands/workflows/hg/tags.rb +27 -0
- data/lib/amp/commands/commands/workflows/hg/tip.rb +13 -0
- data/lib/amp/commands/commands/workflows/hg/update.rb +27 -0
- data/lib/amp/commands/commands/workflows/hg/verify.rb +9 -0
- data/lib/amp/commands/commands/workflows/hg/view.rb +36 -0
- data/lib/amp/commands/dispatch.rb +181 -0
- data/lib/amp/commands/hooks.rb +81 -0
- data/lib/amp/dependencies/amp_support.rb +1 -0
- data/lib/amp/dependencies/amp_support/ruby_amp_support.rb +103 -0
- data/lib/amp/dependencies/minitar.rb +979 -0
- data/lib/amp/dependencies/priority_queue.rb +18 -0
- data/lib/amp/dependencies/priority_queue/c_priority_queue.rb +1 -0
- data/lib/amp/dependencies/priority_queue/poor_priority_queue.rb +46 -0
- data/lib/amp/dependencies/priority_queue/ruby_priority_queue.rb +525 -0
- data/lib/amp/dependencies/python_config.rb +211 -0
- data/lib/amp/dependencies/trollop.rb +713 -0
- data/lib/amp/dependencies/zip/ioextras.rb +155 -0
- data/lib/amp/dependencies/zip/stdrubyext.rb +111 -0
- data/lib/amp/dependencies/zip/tempfile_bugfixed.rb +186 -0
- data/lib/amp/dependencies/zip/zip.rb +1850 -0
- data/lib/amp/dependencies/zip/zipfilesystem.rb +609 -0
- data/lib/amp/dependencies/zip/ziprequire.rb +90 -0
- data/lib/amp/encoding/base85.rb +97 -0
- data/lib/amp/encoding/binary_diff.rb +82 -0
- data/lib/amp/encoding/difflib.rb +166 -0
- data/lib/amp/encoding/mercurial_diff.rb +378 -0
- data/lib/amp/encoding/mercurial_patch.rb +1 -0
- data/lib/amp/encoding/patch.rb +292 -0
- data/lib/amp/encoding/pure_ruby/ruby_mercurial_patch.rb +123 -0
- data/lib/amp/extensions/ditz.rb +41 -0
- data/lib/amp/extensions/lighthouse.rb +167 -0
- data/lib/amp/graphs/ancestor.rb +147 -0
- data/lib/amp/graphs/copies.rb +261 -0
- data/lib/amp/merges/merge_state.rb +164 -0
- data/lib/amp/merges/merge_ui.rb +322 -0
- data/lib/amp/merges/simple_merge.rb +450 -0
- data/lib/amp/profiling_hacks.rb +36 -0
- data/lib/amp/repository/branch_manager.rb +234 -0
- data/lib/amp/repository/dir_state.rb +950 -0
- data/lib/amp/repository/journal.rb +203 -0
- data/lib/amp/repository/lock.rb +207 -0
- data/lib/amp/repository/repositories/bundle_repository.rb +214 -0
- data/lib/amp/repository/repositories/http_repository.rb +377 -0
- data/lib/amp/repository/repositories/local_repository.rb +2661 -0
- data/lib/amp/repository/repository.rb +94 -0
- data/lib/amp/repository/store.rb +485 -0
- data/lib/amp/repository/tag_manager.rb +319 -0
- data/lib/amp/repository/updatable.rb +532 -0
- data/lib/amp/repository/verification.rb +431 -0
- data/lib/amp/repository/versioned_file.rb +475 -0
- data/lib/amp/revlogs/bundle_revlogs.rb +246 -0
- data/lib/amp/revlogs/changegroup.rb +217 -0
- data/lib/amp/revlogs/changelog.rb +338 -0
- data/lib/amp/revlogs/changeset.rb +521 -0
- data/lib/amp/revlogs/file_log.rb +165 -0
- data/lib/amp/revlogs/index.rb +493 -0
- data/lib/amp/revlogs/manifest.rb +195 -0
- data/lib/amp/revlogs/node.rb +18 -0
- data/lib/amp/revlogs/revlog.rb +1032 -0
- data/lib/amp/revlogs/revlog_support.rb +126 -0
- data/lib/amp/server/amp_user.rb +44 -0
- data/lib/amp/server/extension/amp_extension.rb +396 -0
- data/lib/amp/server/extension/authorization.rb +201 -0
- data/lib/amp/server/fancy_http_server.rb +252 -0
- data/lib/amp/server/fancy_views/_browser.haml +28 -0
- data/lib/amp/server/fancy_views/_diff_file.haml +13 -0
- data/lib/amp/server/fancy_views/_navbar.haml +17 -0
- data/lib/amp/server/fancy_views/changeset.haml +31 -0
- data/lib/amp/server/fancy_views/commits.haml +32 -0
- data/lib/amp/server/fancy_views/file.haml +35 -0
- data/lib/amp/server/fancy_views/file_diff.haml +23 -0
- data/lib/amp/server/fancy_views/harshcss/all_hallows_eve.css +72 -0
- data/lib/amp/server/fancy_views/harshcss/amy.css +147 -0
- data/lib/amp/server/fancy_views/harshcss/twilight.css +138 -0
- data/lib/amp/server/fancy_views/stylesheet.sass +175 -0
- data/lib/amp/server/http_server.rb +140 -0
- data/lib/amp/server/repo_user_management.rb +287 -0
- data/lib/amp/support/amp_config.rb +164 -0
- data/lib/amp/support/amp_ui.rb +287 -0
- data/lib/amp/support/docs.rb +54 -0
- data/lib/amp/support/generator.rb +78 -0
- data/lib/amp/support/ignore.rb +144 -0
- data/lib/amp/support/loaders.rb +93 -0
- data/lib/amp/support/logger.rb +103 -0
- data/lib/amp/support/match.rb +151 -0
- data/lib/amp/support/multi_io.rb +87 -0
- data/lib/amp/support/openers.rb +121 -0
- data/lib/amp/support/ruby_19_compatibility.rb +66 -0
- data/lib/amp/support/support.rb +1095 -0
- data/lib/amp/templates/blank.commit.erb +23 -0
- data/lib/amp/templates/blank.log.erb +18 -0
- data/lib/amp/templates/default.commit.erb +23 -0
- data/lib/amp/templates/default.log.erb +26 -0
- data/lib/amp/templates/template.rb +165 -0
- data/site/Rakefile +24 -0
- data/site/src/about/ampfile.haml +57 -0
- data/site/src/about/commands.haml +106 -0
- data/site/src/about/index.haml +33 -0
- data/site/src/about/performance.haml +31 -0
- data/site/src/about/workflows.haml +34 -0
- data/site/src/contribute/index.haml +65 -0
- data/site/src/contribute/style.haml +297 -0
- data/site/src/css/active4d.css +114 -0
- data/site/src/css/all_hallows_eve.css +72 -0
- data/site/src/css/all_themes.css +3299 -0
- data/site/src/css/amp.css +260 -0
- data/site/src/css/amy.css +147 -0
- data/site/src/css/blackboard.css +88 -0
- data/site/src/css/brilliance_black.css +605 -0
- data/site/src/css/brilliance_dull.css +599 -0
- data/site/src/css/cobalt.css +149 -0
- data/site/src/css/cur_amp.css +185 -0
- data/site/src/css/dawn.css +121 -0
- data/site/src/css/eiffel.css +121 -0
- data/site/src/css/espresso_libre.css +109 -0
- data/site/src/css/idle.css +62 -0
- data/site/src/css/iplastic.css +80 -0
- data/site/src/css/lazy.css +73 -0
- data/site/src/css/mac_classic.css +123 -0
- data/site/src/css/magicwb_amiga.css +104 -0
- data/site/src/css/pastels_on_dark.css +188 -0
- data/site/src/css/reset.css +55 -0
- data/site/src/css/slush_poppies.css +85 -0
- data/site/src/css/spacecadet.css +51 -0
- data/site/src/css/sunburst.css +180 -0
- data/site/src/css/twilight.css +137 -0
- data/site/src/css/zenburnesque.css +91 -0
- data/site/src/get/index.haml +32 -0
- data/site/src/helpers.rb +121 -0
- data/site/src/images/amp_logo.png +0 -0
- data/site/src/images/carbonica.png +0 -0
- data/site/src/images/revolution.png +0 -0
- data/site/src/images/tab-bg.png +0 -0
- data/site/src/images/tab-sliding-left.png +0 -0
- data/site/src/images/tab-sliding-right.png +0 -0
- data/site/src/include/_footer.haml +22 -0
- data/site/src/include/_header.haml +17 -0
- data/site/src/index.haml +104 -0
- data/site/src/learn/index.haml +46 -0
- data/site/src/scripts/jquery-1.3.2.min.js +19 -0
- data/site/src/scripts/jquery.cookie.js +96 -0
- data/tasks/stats.rake +155 -0
- data/tasks/yard.rake +171 -0
- data/test/dirstate_tests/dirstate +0 -0
- data/test/dirstate_tests/hgrc +5 -0
- data/test/dirstate_tests/test_dir_state.rb +192 -0
- data/test/functional_tests/resources/.hgignore +2 -0
- data/test/functional_tests/resources/STYLE.txt +25 -0
- data/test/functional_tests/resources/command.rb +372 -0
- data/test/functional_tests/resources/commands/annotate.rb +57 -0
- data/test/functional_tests/resources/commands/experimental/lolcats.rb +17 -0
- data/test/functional_tests/resources/commands/heads.rb +22 -0
- data/test/functional_tests/resources/commands/manifest.rb +12 -0
- data/test/functional_tests/resources/commands/status.rb +90 -0
- data/test/functional_tests/resources/version2/.hgignore +5 -0
- data/test/functional_tests/resources/version2/STYLE.txt +25 -0
- data/test/functional_tests/resources/version2/command.rb +372 -0
- data/test/functional_tests/resources/version2/commands/annotate.rb +45 -0
- data/test/functional_tests/resources/version2/commands/experimental/lolcats.rb +17 -0
- data/test/functional_tests/resources/version2/commands/heads.rb +22 -0
- data/test/functional_tests/resources/version2/commands/manifest.rb +12 -0
- data/test/functional_tests/resources/version2/commands/status.rb +90 -0
- data/test/functional_tests/resources/version3/.hgignore +5 -0
- data/test/functional_tests/resources/version3/STYLE.txt +31 -0
- data/test/functional_tests/resources/version3/command.rb +376 -0
- data/test/functional_tests/resources/version3/commands/annotate.rb +45 -0
- data/test/functional_tests/resources/version3/commands/experimental/lolcats.rb +17 -0
- data/test/functional_tests/resources/version3/commands/heads.rb +22 -0
- data/test/functional_tests/resources/version3/commands/manifest.rb +12 -0
- data/test/functional_tests/resources/version3/commands/status.rb +90 -0
- data/test/functional_tests/resources/version4/.hgignore +5 -0
- data/test/functional_tests/resources/version4/STYLE.txt +31 -0
- data/test/functional_tests/resources/version4/command.rb +376 -0
- data/test/functional_tests/resources/version4/commands/experimental/lolcats.rb +17 -0
- data/test/functional_tests/resources/version4/commands/heads.rb +22 -0
- data/test/functional_tests/resources/version4/commands/manifest.rb +12 -0
- data/test/functional_tests/resources/version4/commands/stats.rb +25 -0
- data/test/functional_tests/resources/version4/commands/status.rb +90 -0
- data/test/functional_tests/resources/version5_1/.hgignore +5 -0
- data/test/functional_tests/resources/version5_1/STYLE.txt +2 -0
- data/test/functional_tests/resources/version5_1/command.rb +374 -0
- data/test/functional_tests/resources/version5_1/commands/experimental/lolcats.rb +17 -0
- data/test/functional_tests/resources/version5_1/commands/heads.rb +22 -0
- data/test/functional_tests/resources/version5_1/commands/manifest.rb +12 -0
- data/test/functional_tests/resources/version5_1/commands/stats.rb +25 -0
- data/test/functional_tests/resources/version5_1/commands/status.rb +90 -0
- data/test/functional_tests/resources/version5_2/.hgignore +5 -0
- data/test/functional_tests/resources/version5_2/STYLE.txt +14 -0
- data/test/functional_tests/resources/version5_2/command.rb +376 -0
- data/test/functional_tests/resources/version5_2/commands/experimental/lolcats.rb +17 -0
- data/test/functional_tests/resources/version5_2/commands/manifest.rb +12 -0
- data/test/functional_tests/resources/version5_2/commands/newz.rb +12 -0
- data/test/functional_tests/resources/version5_2/commands/stats.rb +25 -0
- data/test/functional_tests/resources/version5_2/commands/status.rb +90 -0
- data/test/functional_tests/test_functional.rb +604 -0
- data/test/localrepo_tests/test_local_repo.rb +121 -0
- data/test/localrepo_tests/testrepo.tar.gz +0 -0
- data/test/manifest_tests/00manifest.i +0 -0
- data/test/manifest_tests/test_manifest.rb +72 -0
- data/test/merge_tests/base.txt +10 -0
- data/test/merge_tests/expected.local.txt +16 -0
- data/test/merge_tests/local.txt +11 -0
- data/test/merge_tests/remote.txt +11 -0
- data/test/merge_tests/test_merge.rb +26 -0
- data/test/revlog_tests/00changelog.i +0 -0
- data/test/revlog_tests/revision_added_changelog.i +0 -0
- data/test/revlog_tests/test_adding_index.i +0 -0
- data/test/revlog_tests/test_revlog.rb +333 -0
- data/test/revlog_tests/testindex.i +0 -0
- data/test/store_tests/store.tar.gz +0 -0
- data/test/store_tests/test_fncache_store.rb +122 -0
- data/test/test_amp.rb +9 -0
- data/test/test_base85.rb +14 -0
- data/test/test_bdiff.rb +42 -0
- data/test/test_commands.rb +122 -0
- data/test/test_difflib.rb +50 -0
- data/test/test_helper.rb +15 -0
- data/test/test_journal.rb +29 -0
- data/test/test_match.rb +134 -0
- data/test/test_mdiff.rb +74 -0
- data/test/test_mpatch.rb +14 -0
- data/test/test_support.rb +24 -0
- metadata +385 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
module Amp
|
|
2
|
+
##
|
|
3
|
+
# = FileLog
|
|
4
|
+
# A FileLog is the revision log that stores revision history for
|
|
5
|
+
# each individual file tracked by the system. It stores special meta-data
|
|
6
|
+
# for handling files that have been copied over their history.
|
|
7
|
+
#
|
|
8
|
+
class FileLog < Revlog
|
|
9
|
+
##
|
|
10
|
+
# Initializes the revision log, being sure to encode directories
|
|
11
|
+
# to avoid naming conflicts
|
|
12
|
+
# @param [Opener] opener the opener to use for opening the file
|
|
13
|
+
# @param [String] path the path to the file, excluding "data".
|
|
14
|
+
#
|
|
15
|
+
def initialize(opener, path)
|
|
16
|
+
super(opener, ["data", encode_dir(path + ".i")].join("/"))
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
##
|
|
20
|
+
# Encodes the directory to avoid naming conflicts
|
|
21
|
+
# @param [String] path the path to encode for naming conflict issues
|
|
22
|
+
# @return [String] the encoded directory path
|
|
23
|
+
#
|
|
24
|
+
def encode_dir(path)
|
|
25
|
+
path.gsub(".hg/",".hg.hg/").gsub(".i/",".i.hg/").gsub(".d/",".d.hg/")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
# Decodes the directory to avoid naming conflicts
|
|
30
|
+
# @param [String] path the path to decode for naming conflict issues
|
|
31
|
+
# @return [String] the decoded directory path
|
|
32
|
+
#
|
|
33
|
+
def decode_dir(path)
|
|
34
|
+
path.gsub(".d.hg/",".d/").gsub(".i.hg/",".i/").gsub(".hg.hg/",".hg/")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
##
|
|
38
|
+
# Reads the data of the revision, ignoring the meta data for copied files
|
|
39
|
+
# @param [String] node the node_id to read
|
|
40
|
+
# @return [String] the data of the revision
|
|
41
|
+
#
|
|
42
|
+
def read(node)
|
|
43
|
+
t = decompress_revision(node)
|
|
44
|
+
return t unless t.start_with?("\1\n")
|
|
45
|
+
|
|
46
|
+
start = t.index("\1\n", 2)
|
|
47
|
+
t[(start+2)..-1]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
##
|
|
51
|
+
# Reads the meta data in the node
|
|
52
|
+
# @param [String] node the node_id to read the meta of
|
|
53
|
+
# @return [Hash] the meta data in this revision. Could be empty hash.
|
|
54
|
+
#
|
|
55
|
+
def read_meta(node)
|
|
56
|
+
t = decompress_revision(node)
|
|
57
|
+
return {} unless t.start_with?("\1\n")
|
|
58
|
+
|
|
59
|
+
start = t.index("\1\n", 2)
|
|
60
|
+
mt = t[2..(start-1)]
|
|
61
|
+
m = {}
|
|
62
|
+
mt.split("\n").each do |l|
|
|
63
|
+
k, v = l.split(": ", 2)
|
|
64
|
+
m[k] = v
|
|
65
|
+
end
|
|
66
|
+
m
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
##
|
|
70
|
+
# Adds a revision to the file's history. Overridden for special metadata
|
|
71
|
+
#
|
|
72
|
+
# @param [String] text the new text of the file
|
|
73
|
+
# @param [Hash] meta the meta data to use (if we copied)
|
|
74
|
+
# @param [Journal] journal for aborting transaction
|
|
75
|
+
# @param [Integer] link the revision number this is linked to
|
|
76
|
+
# @param [Integer] p1 (nil) the first parent of this new revision
|
|
77
|
+
# @param [Integer] p2 (nil) the second parent of this new revision
|
|
78
|
+
# @param [String] digest referring to the node this makes
|
|
79
|
+
def add(text, meta, journal, link, p1=nil, p2=nil)
|
|
80
|
+
if (meta && meta.any?) || text.start_with?("\1\n")
|
|
81
|
+
mt = ""
|
|
82
|
+
mt = meta.map {|k, v| "#{k}: #{v}\n"} if meta
|
|
83
|
+
text = "\1\n" + mt.join + "\1\n" + text
|
|
84
|
+
end
|
|
85
|
+
add_revision(text, journal, link, p1, p2)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
##
|
|
89
|
+
# Returns whether or not the file at _node_ has been renamed or
|
|
90
|
+
# copied.
|
|
91
|
+
#
|
|
92
|
+
# @param [String] node the node_id of the revision
|
|
93
|
+
# @return [Boolean] has the file been renamed or copied at this
|
|
94
|
+
# revision?
|
|
95
|
+
def renamed(node)
|
|
96
|
+
return false if parents_for_node(node).first != NULL_ID
|
|
97
|
+
|
|
98
|
+
m = read_meta node
|
|
99
|
+
|
|
100
|
+
if m.any? && m["copy"]
|
|
101
|
+
return [m["copy"], m["copyrev"].unhexlify]
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
false
|
|
105
|
+
end
|
|
106
|
+
alias_method :renamed?, :renamed
|
|
107
|
+
|
|
108
|
+
##
|
|
109
|
+
# Yields a block for every revision, while being sure to follow copies.
|
|
110
|
+
def each(&block)
|
|
111
|
+
if @index[0].parent_one_rev == NULL_REV
|
|
112
|
+
meta_info = renamed(@index[0].node_id)
|
|
113
|
+
if meta_info
|
|
114
|
+
copied_log = FileLog.new(@opener, meta_info.first)
|
|
115
|
+
copied_log.each(&block)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
super(&block)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
##
|
|
122
|
+
# Unified diffs 2 revisions, based on their indices. They are returned in a sexified
|
|
123
|
+
# unified diff format.
|
|
124
|
+
def unified_revision_diff(rev1, old_date, rev2, new_date, path1, path2, opts={})
|
|
125
|
+
opts = Diffs::MercurialDiff::DEFAULT_OPTIONS.merge(opts)
|
|
126
|
+
version_1 = rev1 ? read(self.node_id_for_index(rev1)) : nil
|
|
127
|
+
version_2 = rev2 ? read(self.node_id_for_index(rev2)) : nil
|
|
128
|
+
|
|
129
|
+
Diffs::MercurialDiff.unified_diff( version_1, old_date, version_2, new_date,
|
|
130
|
+
path1, path2, false, opts)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
##
|
|
134
|
+
# Gets the size of the file. Overridden because of the metadata for
|
|
135
|
+
# copied files.
|
|
136
|
+
#
|
|
137
|
+
# @param [Integer] rev the number of the revision to lookup
|
|
138
|
+
# @return [String] the file's data
|
|
139
|
+
def size(rev)
|
|
140
|
+
node = self.node rev
|
|
141
|
+
if renamed? node
|
|
142
|
+
read(node).size
|
|
143
|
+
else
|
|
144
|
+
self[rev].compressed_len
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
##
|
|
149
|
+
# Converts a given node in this revision with the text provided.
|
|
150
|
+
# overridden because it handles renamed files.
|
|
151
|
+
#
|
|
152
|
+
# @param [String] thenode the node ID to use
|
|
153
|
+
# @param [String] text the text to compare against
|
|
154
|
+
# @return [Boolean] true if they're different, false if not. silly, isn't
|
|
155
|
+
# it?
|
|
156
|
+
def cmp(thenode, text)
|
|
157
|
+
if renamed? thenode
|
|
158
|
+
t2 = read thenode
|
|
159
|
+
return t2 != text
|
|
160
|
+
end
|
|
161
|
+
super(thenode, text)
|
|
162
|
+
end
|
|
163
|
+
end # class FileLog
|
|
164
|
+
|
|
165
|
+
end # module Amp
|
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
module Amp
|
|
2
|
+
module RevlogSupport
|
|
3
|
+
include Node
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
# This class represents one revision entry in the index.
|
|
7
|
+
#
|
|
8
|
+
# Format on disk (in BitStruct notation):
|
|
9
|
+
#
|
|
10
|
+
# default_options :endian => :network
|
|
11
|
+
#
|
|
12
|
+
# signed :offset_flags, 64
|
|
13
|
+
# signed :compressed_len, 32
|
|
14
|
+
# signed :uncompressed_len, 32
|
|
15
|
+
# signed :base_rev, 32
|
|
16
|
+
# signed :link_rev, 32
|
|
17
|
+
# signed :parent_one_rev, 32
|
|
18
|
+
# signed :parent_two_rev, 32
|
|
19
|
+
# char :node_id, 160
|
|
20
|
+
# pad :padding, 96
|
|
21
|
+
#
|
|
22
|
+
# [offset_flags] - this is a double-word (8 bytes) - that combines the offset into the data file
|
|
23
|
+
# and any flags about the entry
|
|
24
|
+
# [compressed_len] - this is the length of the data when compressed
|
|
25
|
+
# [uncompresed_len] - length of the data uncompresed
|
|
26
|
+
# [base_rev] - the revision of the filelog
|
|
27
|
+
# [link_rev] - the revision of the whole repo where this was attached
|
|
28
|
+
# [parent_one_rev] - the parent revision the revision. Even if it's not a merge,
|
|
29
|
+
# it will have at least this parent entry
|
|
30
|
+
# [parent_two_rev] - if the revision is a merge, then it will have a second parent.
|
|
31
|
+
class IndexEntry < Struct.new(:offset_flags, :compressed_len, :uncompressed_len, :base_rev,
|
|
32
|
+
:link_rev, :parent_one_rev, :parent_two_rev, :node_id)
|
|
33
|
+
include Comparable
|
|
34
|
+
INDEX_FORMAT_NG = "Q NNNNNN a20 x12"
|
|
35
|
+
BLOCK_SIZE = 64
|
|
36
|
+
def initialize(*args)
|
|
37
|
+
if args.size == 1 && args[0].respond_to?(:read)
|
|
38
|
+
super(*(args[0].read(BLOCK_SIZE).unpack(INDEX_FORMAT_NG)))
|
|
39
|
+
else
|
|
40
|
+
super(*args)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def to_s
|
|
45
|
+
fix_signs
|
|
46
|
+
ret = self.to_a.pack(INDEX_FORMAT_NG)
|
|
47
|
+
fix_signs
|
|
48
|
+
ret
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Fixes the values to force them to be signed (possible to be negative)
|
|
52
|
+
def fix_signs
|
|
53
|
+
require 'amp/dependencies/amp_support/ruby_amp_support'
|
|
54
|
+
|
|
55
|
+
self.offset_flags = self.offset_flags.byte_swap_64
|
|
56
|
+
self.compressed_len = self.compressed_len.to_signed_32
|
|
57
|
+
self.uncompressed_len = self.uncompressed_len.to_signed_32
|
|
58
|
+
self.base_rev = self.base_rev.to_signed_32
|
|
59
|
+
self.link_rev = self.link_rev.to_signed_32
|
|
60
|
+
self.parent_one_rev = self.parent_one_rev.to_signed_32
|
|
61
|
+
self.parent_two_rev = self.parent_two_rev.to_signed_32
|
|
62
|
+
|
|
63
|
+
self
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Compares this entry to another
|
|
67
|
+
def <=> other_entry
|
|
68
|
+
this.base_rev <=> other_entry.base_rev
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Gives a hash value so we can stick these entries into a hash
|
|
72
|
+
def hash
|
|
73
|
+
node_id.hash
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
##
|
|
78
|
+
# = Index
|
|
79
|
+
# The Index is a file that keeps track of the revision data. All revisions
|
|
80
|
+
# go through an index. This class, {Index}, is the most basic class. It
|
|
81
|
+
# provides an Index.parse method so that you can read a file in, and
|
|
82
|
+
# the class will figure out which version it is, and all that jazz.
|
|
83
|
+
#
|
|
84
|
+
class Index
|
|
85
|
+
include Amp::RevlogSupport::Support
|
|
86
|
+
include Enumerable
|
|
87
|
+
|
|
88
|
+
# This is the packed format of the version number of the index.
|
|
89
|
+
VERSION_FORMAT = "N"
|
|
90
|
+
# The version (either {REVLOG_VERSION_0} or {REVLOG_VERSION_NG})
|
|
91
|
+
attr_reader :version
|
|
92
|
+
# The actual lookup array. Each revision has an index in this list, and
|
|
93
|
+
# that list also happens to be relatively chronological.
|
|
94
|
+
attr_reader :index
|
|
95
|
+
# This node_map lets you look up node_id's (NOT INDEX-NUMBERS),
|
|
96
|
+
# which are strings, and get the index into @index of the
|
|
97
|
+
# node you're looking up.
|
|
98
|
+
attr_reader :node_map
|
|
99
|
+
# This allows a couple neat caching tricks to speed up acces and cut
|
|
100
|
+
# down on IO.
|
|
101
|
+
attr_reader :chunk_cache
|
|
102
|
+
# This is the path to the index file. Can be a URL. I don't care and
|
|
103
|
+
# neither should you.
|
|
104
|
+
attr_reader :indexfile
|
|
105
|
+
# This is the raw cache data. Another helpful bit.
|
|
106
|
+
attr_accessor :cache
|
|
107
|
+
|
|
108
|
+
##
|
|
109
|
+
# This method will parse the file at the provided path and return
|
|
110
|
+
# an appropriate Index object. The object will be of the class that
|
|
111
|
+
# fits the file provided, based on version and whether
|
|
112
|
+
# it is inline.
|
|
113
|
+
#
|
|
114
|
+
# @param [String] inputfile the filepath to load and parse
|
|
115
|
+
# @return [Index] Some subclassed version of Index that's parsed the file
|
|
116
|
+
def self.parse(opener, inputfile)
|
|
117
|
+
versioninfo = REVLOG_DEFAULT_VERSION
|
|
118
|
+
i = ""
|
|
119
|
+
begin
|
|
120
|
+
opener.open(inputfile) do |f|
|
|
121
|
+
i = f.read(4)
|
|
122
|
+
end
|
|
123
|
+
versioninfo = i.unpack(VERSION_FORMAT).first if i.size > 0
|
|
124
|
+
# Check if the data is with the index info.
|
|
125
|
+
inline = (versioninfo & REVLOG_NG_INLINE_DATA > 0)
|
|
126
|
+
# Get the version number of the index file.
|
|
127
|
+
version = Support.get_version versioninfo
|
|
128
|
+
rescue
|
|
129
|
+
inline = true
|
|
130
|
+
version = REVLOG_VERSION_NG
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Pick a subclass for the version and in-line-icity we found.
|
|
134
|
+
case [version, inline]
|
|
135
|
+
when [REVLOG_VERSION_0, false]
|
|
136
|
+
IndexVersion0.new opener, inputfile
|
|
137
|
+
when [REVLOG_VERSION_NG, false]
|
|
138
|
+
IndexVersionNG.new opener, inputfile
|
|
139
|
+
when [REVLOG_VERSION_NG, true]
|
|
140
|
+
IndexInlineNG.new opener, inputfile
|
|
141
|
+
else
|
|
142
|
+
raise RevlogError.new("Invalid format: #{version} flags: #{get_flags(versioninfo)}")
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
##
|
|
147
|
+
# Returns whether a given node ID exists, without throwing a lookup error.
|
|
148
|
+
#
|
|
149
|
+
# @param [String] node the node_id to lookup. 20 bytes, binary.
|
|
150
|
+
# @return [Boolean] is the node in the index?
|
|
151
|
+
def has_node?(node)
|
|
152
|
+
@node_map[node]
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
##
|
|
156
|
+
# This provides quick lookup into the index, based on revision
|
|
157
|
+
# number. NOT ID's, index numbers.
|
|
158
|
+
#
|
|
159
|
+
# @param [Fixnum] index the index to look up
|
|
160
|
+
# @return [IndexEntry] the revision requested
|
|
161
|
+
def [](index)
|
|
162
|
+
@index[index]
|
|
163
|
+
end
|
|
164
|
+
##
|
|
165
|
+
# This method writes the index to file. Pretty 1337h4><.
|
|
166
|
+
#
|
|
167
|
+
# @param [String] index_file the path to the index file.
|
|
168
|
+
def write_entry(index_file, journal)
|
|
169
|
+
raise abort("Use a concrete class. Yeah, I called it a concrete class. I hate" +
|
|
170
|
+
" Java too, but you tried to use an abstract class.")
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
##
|
|
174
|
+
# Adds an item to the index safely. DO NOT USE some_index.index <<. It's
|
|
175
|
+
# some_index << entry.
|
|
176
|
+
#
|
|
177
|
+
# @param [[Integer, Integer, Integer, Integer, Integer, Integer,
|
|
178
|
+
# Integer, Integer]] item the data to enter as an entry. See the spec fo
|
|
179
|
+
# {IndexEntry}.
|
|
180
|
+
def <<(item)
|
|
181
|
+
@index.insert(-2, IndexEntry.new(*item)) if item.is_a? Array
|
|
182
|
+
@index.insert(-2, item) if item.is_a? IndexEntry
|
|
183
|
+
# leave the terminating entry intact
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Returns the number of entries in the index, including the null revision
|
|
187
|
+
def size
|
|
188
|
+
@index.size
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# Iterates over each entry in the index, including the null revision
|
|
192
|
+
def each(&b)
|
|
193
|
+
@index.each(&b)
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
##
|
|
198
|
+
# = IndexVersion0
|
|
199
|
+
# This handles old versions of the index file format.
|
|
200
|
+
# These are apparently so old they were version 0.
|
|
201
|
+
class IndexVersion0 < Index
|
|
202
|
+
# Binary data format for each revision entry
|
|
203
|
+
INDEX_FORMAT_V0 = "N4 a20 a20 a20"
|
|
204
|
+
# The size of each revision entry
|
|
205
|
+
BLOCK_SIZE = (4 * 4) + (3 * 20)
|
|
206
|
+
# The offset into the entry where the SHA1 is stored for validation
|
|
207
|
+
SHA1_OFFSET = 56
|
|
208
|
+
|
|
209
|
+
# Return the size of 1 entry
|
|
210
|
+
def entry_size; BLOCK_SIZE; end
|
|
211
|
+
# Return what version this index is
|
|
212
|
+
def version; REVLOG_VERSION_0; end
|
|
213
|
+
# Does the index store the data with the revision index entries?
|
|
214
|
+
def inline?; false; end
|
|
215
|
+
|
|
216
|
+
# Initializes the index by reading from the provided filename. Users probably
|
|
217
|
+
# don't need this because {Index}#{parse} will do this for you.
|
|
218
|
+
#
|
|
219
|
+
# @param [String] inputfile the path to the index file
|
|
220
|
+
def initialize(opener, inputfile)
|
|
221
|
+
@opener = opener
|
|
222
|
+
@indexfile = inputfile
|
|
223
|
+
@node_map = {Node::NULL_ID => Node::NULL_REV}
|
|
224
|
+
@index = []
|
|
225
|
+
n = offset = 0
|
|
226
|
+
if File.exists?(opener.join(inputfile))
|
|
227
|
+
opener.open(inputfile) do |f|
|
|
228
|
+
|
|
229
|
+
while !f.eof?
|
|
230
|
+
current = f.read(BLOCK_SIZE)
|
|
231
|
+
entry = current.unpack(INDEX_FORMAT_V0)
|
|
232
|
+
new_entry = IndexEntry.new(offset_version(entry[0],0), entry[1], -1, entry[2], entry[3],
|
|
233
|
+
(@node_map[entry[4]] || nullrev), (@node_map[entry[5]] || nullrev),
|
|
234
|
+
entry[6])
|
|
235
|
+
@index << new_entry.fix_signs
|
|
236
|
+
@node_map[entry[6]] = n
|
|
237
|
+
n += 1
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
@cache = nil
|
|
242
|
+
self
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
##
|
|
246
|
+
# This method writes the index to file. Pretty 1337h4><.
|
|
247
|
+
#
|
|
248
|
+
# @param [String] index_file the path to the index file.
|
|
249
|
+
def write_entry(index_file, entry, journal, data)
|
|
250
|
+
curr = self.size - 1
|
|
251
|
+
|
|
252
|
+
node_map[entry.last] = curr
|
|
253
|
+
|
|
254
|
+
link = entry[4]
|
|
255
|
+
data_file = index_file[0..-3] + ".d"
|
|
256
|
+
|
|
257
|
+
entry = pack_entry entry, link
|
|
258
|
+
|
|
259
|
+
data_file_handle = open(data_file, "a")
|
|
260
|
+
index_file_handle = open(index_file, "a+")
|
|
261
|
+
|
|
262
|
+
journal << [data_file, offset]
|
|
263
|
+
journal << [index_file, curr * entry.size]
|
|
264
|
+
|
|
265
|
+
data_file_handle.write data[:compression] if data[:compression].any?
|
|
266
|
+
data_file_handle.write data[:text]
|
|
267
|
+
|
|
268
|
+
data_file_handle.flush
|
|
269
|
+
index_file_handle.write entry
|
|
270
|
+
end
|
|
271
|
+
##
|
|
272
|
+
# This takes an entry and packs it into binary data for writing to
|
|
273
|
+
# the file.
|
|
274
|
+
#
|
|
275
|
+
# @param [IndexEntry] entry the revision entry to pack up for writing
|
|
276
|
+
# @param rev unused by version 0. Kept to make the interface uniform
|
|
277
|
+
# @return [String] the Binary data packed up for writing.
|
|
278
|
+
def pack_entry(entry, rev)
|
|
279
|
+
entry = IndexEntry.new(*entry) if entry.kind_of? Array
|
|
280
|
+
entry.fix_signs
|
|
281
|
+
e2 = [RevlogSupport::Support.offset_type(entry.offset_flags),
|
|
282
|
+
entry.compressed_len, entry.base_rev, entry.link_rev,
|
|
283
|
+
@index[entry.parent_one_rev].node_id,
|
|
284
|
+
@index[entry.parent_two_rev].node_id, entry.node_id]
|
|
285
|
+
e2.pack(INDEX_FORMAT_V0)
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
##
|
|
290
|
+
# = IndexVersionNG
|
|
291
|
+
# This is the current version of the index. I'm not sure why they call
|
|
292
|
+
# it Version 'NG' but they do. An index of this type is *not* inline.
|
|
293
|
+
class IndexVersionNG < Index
|
|
294
|
+
VERSION_FORMAT = "N"
|
|
295
|
+
# The binary format used for pack/unpack
|
|
296
|
+
INDEX_FORMAT_NG = "Q NNNNNN a20 x12"
|
|
297
|
+
# The distance into the entry to go to find the SHA1 hash
|
|
298
|
+
SHA1_OFFSET = 32
|
|
299
|
+
# The size of a single block in the index
|
|
300
|
+
BLOCK_SIZE = 8 + (6 * 4) + 20 + 12
|
|
301
|
+
|
|
302
|
+
##
|
|
303
|
+
# Initializes the index by parsing the given file.
|
|
304
|
+
#
|
|
305
|
+
# @param [String] inputfile the path to the index file.
|
|
306
|
+
def initialize(opener, inputfile)
|
|
307
|
+
@opener = opener
|
|
308
|
+
@indexfile = inputfile
|
|
309
|
+
@cache = nil
|
|
310
|
+
@index = []
|
|
311
|
+
@node_map = {Node::NULL_ID => Node::NULL_REV}
|
|
312
|
+
|
|
313
|
+
opened = parse_file
|
|
314
|
+
|
|
315
|
+
if opened
|
|
316
|
+
first_entry = @index[0]
|
|
317
|
+
type = get_version(first_entry.offset_flags)
|
|
318
|
+
first_entry.offset_flags = offset_version(0, type) #turn off inline
|
|
319
|
+
@index[0] = first_entry
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
@index << IndexEntry.new(0,0,0,-1,-1,-1,-1,Node::NULL_ID)
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
##
|
|
326
|
+
# returns the size of 1 block in this type of index
|
|
327
|
+
def entry_size; BLOCK_SIZE; end
|
|
328
|
+
|
|
329
|
+
# returns the version number of the index
|
|
330
|
+
def version; REVLOG_VERSION_NG; end
|
|
331
|
+
# returns whether or not the index stores data with revision info
|
|
332
|
+
def inline?; false; end
|
|
333
|
+
|
|
334
|
+
##
|
|
335
|
+
# Parses each index entry. Internal use only.
|
|
336
|
+
#
|
|
337
|
+
# @return [Boolean] whether the file was opened
|
|
338
|
+
def parse_file
|
|
339
|
+
n = 0
|
|
340
|
+
begin
|
|
341
|
+
@opener.open(@indexfile,"r") do |f|
|
|
342
|
+
until f.eof?
|
|
343
|
+
# read the entry
|
|
344
|
+
entry = IndexEntry.new(f).fix_signs
|
|
345
|
+
# store it in the map
|
|
346
|
+
@node_map[entry.node_id] = n
|
|
347
|
+
# add it to the index
|
|
348
|
+
@index << entry
|
|
349
|
+
n += 1
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
return true
|
|
353
|
+
rescue Errno::ENOENT
|
|
354
|
+
return false
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
##
|
|
359
|
+
# Packs up the revision entry for writing to the binary file.
|
|
360
|
+
#
|
|
361
|
+
# @param [IndexEntry] entry this is the entry that has to be formatted
|
|
362
|
+
# into binary.
|
|
363
|
+
# @param [Fixnum] rev this is the index number of the entry - if it's
|
|
364
|
+
# the first revision (rev == 0) then we treat it slightly differently.
|
|
365
|
+
# @return [String] the entry converted into binary suitable for writing.
|
|
366
|
+
def pack_entry(entry, rev)
|
|
367
|
+
entry = IndexEntry.new(*entry) if entry.kind_of? Array
|
|
368
|
+
p = entry.to_s
|
|
369
|
+
if rev == 0 || rev == 1
|
|
370
|
+
p = [version].pack(VERSION_FORMAT) + p[4..-1] # initial entry
|
|
371
|
+
end
|
|
372
|
+
p
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
##
|
|
376
|
+
# This method writes the index to file. Pretty 1337h4><.
|
|
377
|
+
#
|
|
378
|
+
# @param [String] index_file the path to the index file.
|
|
379
|
+
def write_entry(index_file, entry, journal, data, index_file_handle = nil)
|
|
380
|
+
curr = self.size - 1
|
|
381
|
+
|
|
382
|
+
link = (entry.is_a? Array) ? entry[4] : entry.link_rev
|
|
383
|
+
data_file = index_file[0..-3] + ".d"
|
|
384
|
+
|
|
385
|
+
entry = pack_entry entry, link
|
|
386
|
+
|
|
387
|
+
@opener.open(data_file, "a+") do |data_file_handle|
|
|
388
|
+
data_file_handle.write data[:compression] if data[:compression].any?
|
|
389
|
+
data_file_handle.write data[:text]
|
|
390
|
+
|
|
391
|
+
data_file_handle.flush
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
index_file_handle ||= (opened = true && @opener.open(index_file, "a+"))
|
|
395
|
+
|
|
396
|
+
index_file_handle.write entry
|
|
397
|
+
index_file_handle.close if opened
|
|
398
|
+
|
|
399
|
+
#journal << [data_file, offset]
|
|
400
|
+
#journal << [index_file, curr * entry.size]
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
##
|
|
406
|
+
# = LazyIndex
|
|
407
|
+
# When this gets filled in, this class will let us access an index without loading
|
|
408
|
+
# every entry first. This is handy because index files can get pretty fuckin big.
|
|
409
|
+
class LazyIndex < Index
|
|
410
|
+
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
##
|
|
414
|
+
# = IndexInlineNG
|
|
415
|
+
# This is a variant of the current version of the index format, in which the data
|
|
416
|
+
# is stored in the actual index file itself, right after the little revision
|
|
417
|
+
# entry block (see {IndexEntry}). This means less IO, which is good.
|
|
418
|
+
#
|
|
419
|
+
class IndexInlineNG < IndexVersionNG
|
|
420
|
+
VERSION_FORMAT = "N"
|
|
421
|
+
# We're inline!
|
|
422
|
+
INDEX_FORMAT_NG = "Q NNNNNN a20 x12"
|
|
423
|
+
# The distance into the entry to go to find the SHA1 hash
|
|
424
|
+
SHA1_OFFSET = 32
|
|
425
|
+
# The size of a single block in the index
|
|
426
|
+
BLOCK_SIZE = 8 + (6 * 4) + 20 + 12
|
|
427
|
+
|
|
428
|
+
def inline?; true; end
|
|
429
|
+
def version; REVLOG_VERSION_NG | REVLOG_NG_INLINE_DATA; end
|
|
430
|
+
def pack_entry(entry, rev)
|
|
431
|
+
entry = IndexEntry.new(*entry) if entry.kind_of? Array
|
|
432
|
+
p = entry.to_s
|
|
433
|
+
if rev == 0 || rev == 1
|
|
434
|
+
p = [version].pack(VERSION_FORMAT) + p[4..-1] # initial entry
|
|
435
|
+
end
|
|
436
|
+
p
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
##
|
|
441
|
+
# @todo "not sure what the 0 is for yet or i'd make this a hash" (see code)
|
|
442
|
+
# This method overrides the parent class' method that reads entries sequentially
|
|
443
|
+
# from the index file. Each entry is followed by the data for that revision
|
|
444
|
+
# so we have to skip over that data for our purposes.
|
|
445
|
+
def parse_file
|
|
446
|
+
n = offset = 0
|
|
447
|
+
begin
|
|
448
|
+
@opener.open(@indexfile,"r") do |f|
|
|
449
|
+
return false if f.eof?
|
|
450
|
+
while !f.eof?
|
|
451
|
+
# read 1 entry
|
|
452
|
+
entry = IndexEntry.new(f).fix_signs
|
|
453
|
+
# store it in the map
|
|
454
|
+
@node_map[entry.node_id] = n
|
|
455
|
+
# add it to the index
|
|
456
|
+
@index << entry
|
|
457
|
+
n += 1
|
|
458
|
+
break if entry.compressed_len < 0
|
|
459
|
+
|
|
460
|
+
# skip past the data, too!
|
|
461
|
+
f.seek(entry.compressed_len, IO::SEEK_CUR)
|
|
462
|
+
end
|
|
463
|
+
end
|
|
464
|
+
return true
|
|
465
|
+
rescue Errno::ENOENT
|
|
466
|
+
return false
|
|
467
|
+
end
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
##
|
|
471
|
+
# This method writes the index to file. Pretty 1337h4><.
|
|
472
|
+
#
|
|
473
|
+
# @param [String] index_file the path to the index file.
|
|
474
|
+
def write_entry(index_file, entry, journal, data, index_file_handle = nil)
|
|
475
|
+
curr = self.size - 1
|
|
476
|
+
link = (entry.is_a? Array) ? entry[4] : entry.link_rev
|
|
477
|
+
|
|
478
|
+
entry = pack_entry entry, curr
|
|
479
|
+
|
|
480
|
+
index_file_handle ||= (opened = true && @opener.open(index_file, "a+"))
|
|
481
|
+
|
|
482
|
+
index_file_handle.write entry
|
|
483
|
+
index_file_handle.write data[:compression] if data[:compression].any?
|
|
484
|
+
index_file_handle.write data[:text]
|
|
485
|
+
|
|
486
|
+
index_file_handle.close if opened
|
|
487
|
+
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
end
|
|
492
|
+
end
|
|
493
|
+
end
|