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,203 @@
|
|
|
1
|
+
module Amp
|
|
2
|
+
class StandardErrorReporter
|
|
3
|
+
def self.report str
|
|
4
|
+
STDERR.puts str
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
##
|
|
9
|
+
# Provides a journal interface so when a large number of transactions
|
|
10
|
+
# are occurring, and any one could fail, we can rollback the changes.
|
|
11
|
+
class Journal
|
|
12
|
+
DEFAULT_OPTS = {:reporter => StandardErrorReporter, :after_close => nil}
|
|
13
|
+
|
|
14
|
+
attr_accessor :report, :journal, :after_close
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
# @return [Amp::Journal]
|
|
18
|
+
def self.start(file, opts=DEFAULT_OPTS)
|
|
19
|
+
journal = Journal.new opts[:reporter], file, &opts[:after_close]
|
|
20
|
+
|
|
21
|
+
if block_given?
|
|
22
|
+
begin
|
|
23
|
+
yield journal
|
|
24
|
+
ensure
|
|
25
|
+
journal.close
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
journal
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
##
|
|
33
|
+
# Initializes the journal to get ready for some transactions.
|
|
34
|
+
#
|
|
35
|
+
# @param [#report] reporter an object that will keep track of any alerts
|
|
36
|
+
# we have to send out. Must respond to #report.
|
|
37
|
+
# @param [String] journal the path to the journal file to use
|
|
38
|
+
# @param [Integer] createmode An octal number that sets the filemode
|
|
39
|
+
# of the journal file we'll be using
|
|
40
|
+
# @param [Proc] after_close A proc to call (with no args) after we
|
|
41
|
+
# close (finish) the transaction.
|
|
42
|
+
def initialize(reporter=StandardErrorReporter, journal="journal#{rand(10000)}", createmode=nil, &after_close)
|
|
43
|
+
@count = 1
|
|
44
|
+
@reporter = reporter
|
|
45
|
+
@after_close = after_close
|
|
46
|
+
@entries = []
|
|
47
|
+
@map = {}
|
|
48
|
+
@journal_file = journal
|
|
49
|
+
|
|
50
|
+
@file = open(@journal_file, "w")
|
|
51
|
+
|
|
52
|
+
FileUtils.chmod(createmode & 0666, @journal_file) unless createmode.nil?
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
##
|
|
56
|
+
# Kills the journal - used when shit goes down and we gotta give up
|
|
57
|
+
# on the transactions.
|
|
58
|
+
def delete
|
|
59
|
+
if @journal_file
|
|
60
|
+
abort if @entries.any?
|
|
61
|
+
@file.close
|
|
62
|
+
FileUtils.safe_unlink @journal_file
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
##
|
|
67
|
+
# Adds an entry to the journal. Since all our files are just being appended
|
|
68
|
+
# to all the time, all we really need is to keep track of how long the file
|
|
69
|
+
# was when we last knew it to be safe. In other words, if the file started
|
|
70
|
+
# off at 20 bytes, then an error happened, we just truncate it to 20 bytes.
|
|
71
|
+
#
|
|
72
|
+
# All params should be contained in the array
|
|
73
|
+
#
|
|
74
|
+
# @param file the name of the file we're modifying and need to track
|
|
75
|
+
# @param offset the length of the file we're storing
|
|
76
|
+
# @param data any extra data to hold onto
|
|
77
|
+
def add_entry(array)
|
|
78
|
+
file, offset, data = array[0], array[1], array[2]
|
|
79
|
+
return if @map[file]
|
|
80
|
+
@entries << {:file => file, :offset => offset, :data => data}
|
|
81
|
+
@map[file] = @entries.size - 1
|
|
82
|
+
|
|
83
|
+
# tell the journal how to truncate this revision
|
|
84
|
+
@file.write("#{file}\0#{offset}\n")
|
|
85
|
+
@file.flush
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
##
|
|
89
|
+
# Alias for {add_entry}
|
|
90
|
+
alias :<< :add_entry
|
|
91
|
+
|
|
92
|
+
##
|
|
93
|
+
# Finds the entry for a given file's path
|
|
94
|
+
# @param [String] file the path to the file
|
|
95
|
+
# @return [Hash] A hash with the values :file, :offset, and :data, as
|
|
96
|
+
# they were when they were stored by {add_entry} or {update}
|
|
97
|
+
def find_file(file)
|
|
98
|
+
return @entries[@map[file]] if @map[file]
|
|
99
|
+
nil
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
##
|
|
103
|
+
# Alias for {find_file}
|
|
104
|
+
alias :find :find_file
|
|
105
|
+
|
|
106
|
+
##
|
|
107
|
+
# Updates an entry's data, based on the filename. The file must already
|
|
108
|
+
# have been journaled.
|
|
109
|
+
#
|
|
110
|
+
# @param [String] file the file to update
|
|
111
|
+
# @param [Fixnum] offset the new offset to store
|
|
112
|
+
# @param [String] data the new data to store
|
|
113
|
+
def replace(file, offset, data=nil)
|
|
114
|
+
raise IndexError.new("journal lookup failed #{file}") unless @map[file]
|
|
115
|
+
index = @map[file]
|
|
116
|
+
@entries[index] = {:file => file, :offset => offset, :data => data}
|
|
117
|
+
@file.write("#{file}\0#{offset}\n")
|
|
118
|
+
@file.flush
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
##
|
|
122
|
+
# Alias for {replace}
|
|
123
|
+
alias :update :replace
|
|
124
|
+
|
|
125
|
+
##
|
|
126
|
+
# No godly idea what this is for
|
|
127
|
+
def nest
|
|
128
|
+
@count += 1
|
|
129
|
+
self
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
##
|
|
133
|
+
# Is the journal running right now?
|
|
134
|
+
def running?
|
|
135
|
+
@count > 0
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
##
|
|
139
|
+
# Closes up the journal. Will call the after_close proc passed
|
|
140
|
+
# during instantiation.
|
|
141
|
+
def close
|
|
142
|
+
@count -= 1
|
|
143
|
+
return if @count != 0
|
|
144
|
+
@file.close
|
|
145
|
+
@entries = []
|
|
146
|
+
if @after_close
|
|
147
|
+
@after_close.call
|
|
148
|
+
else
|
|
149
|
+
FileUtils.safe_unlink(@journal_file)
|
|
150
|
+
end
|
|
151
|
+
@journal_file = nil
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
##
|
|
155
|
+
# Abort, abort! abandon ship! This rolls back any changes we've made
|
|
156
|
+
# during the current journalling session.
|
|
157
|
+
def abort
|
|
158
|
+
return unless @entries && @entries.any?
|
|
159
|
+
@reporter.report "transaction abort!\n"
|
|
160
|
+
@entries.each do |hash|
|
|
161
|
+
file, offset = hash[:file], hash[:offset]
|
|
162
|
+
begin
|
|
163
|
+
fp = open(File.join(".hg","store",file), "a")
|
|
164
|
+
fp.truncate offset
|
|
165
|
+
fp.close
|
|
166
|
+
rescue
|
|
167
|
+
@reporter.report "Failed to truncate #{File.join(".hg","store",file)}\n"
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
@entries = []
|
|
171
|
+
@reporter.report "rollback completed\n"
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
##
|
|
175
|
+
# If we crashed during an abort, the journal file is gonna be sitting aorund
|
|
176
|
+
# somewhere. So, we should rollback any changes it left lying around.
|
|
177
|
+
#
|
|
178
|
+
# @param [String] file the journal file to use during the rollback
|
|
179
|
+
def self.rollback(file)
|
|
180
|
+
files = {}
|
|
181
|
+
fp = open(file)
|
|
182
|
+
fp.each_line do |line|
|
|
183
|
+
file, offset = line.split("\0")
|
|
184
|
+
files[file] = offset.to_i
|
|
185
|
+
end
|
|
186
|
+
fp.close
|
|
187
|
+
files.each do |file, offset|
|
|
188
|
+
if o > 0
|
|
189
|
+
fp = open(file, "a")
|
|
190
|
+
fp.truncate o.to_i
|
|
191
|
+
fp.close
|
|
192
|
+
else
|
|
193
|
+
fp = open(f)
|
|
194
|
+
fn = fp.path
|
|
195
|
+
fp.close
|
|
196
|
+
FileUtils.safe_unlink fn
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
FileUtils.safe_unlink file
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
module Amp
|
|
2
|
+
module Repositories
|
|
3
|
+
##
|
|
4
|
+
# = Lock
|
|
5
|
+
# Manages a given lock file, indicating that the enclosing folder should not
|
|
6
|
+
# be modified. Typically used during destructive operations on a repo (such as
|
|
7
|
+
# a commit or push).
|
|
8
|
+
#
|
|
9
|
+
# We must be compatible with Mercurial's lock format, unfortunately. Doesn't life
|
|
10
|
+
# suck?
|
|
11
|
+
#####
|
|
12
|
+
##### From Mercurial code, explaining their format:
|
|
13
|
+
#####
|
|
14
|
+
#
|
|
15
|
+
# lock is symlink on platforms that support it, file on others.
|
|
16
|
+
#
|
|
17
|
+
# symlink is used because create of directory entry and contents
|
|
18
|
+
# are atomic even over nfs.
|
|
19
|
+
#
|
|
20
|
+
# old-style lock: symlink to pid
|
|
21
|
+
# new-style lock: symlink to hostname:pid
|
|
22
|
+
class Lock
|
|
23
|
+
@@host = nil
|
|
24
|
+
|
|
25
|
+
##
|
|
26
|
+
# Initializes the lock to a given file name, and creates the lock, effectively
|
|
27
|
+
# locking the containing directory.
|
|
28
|
+
#
|
|
29
|
+
# @param [String] file the path to the the lock file to create
|
|
30
|
+
# @param [Hash<Symbol => Object>] opts the options to use when creating the lock
|
|
31
|
+
# @option [Integer] options :timeout (-1) the length of time to keep trying to create the lock.
|
|
32
|
+
# defaults to -1 (indefinitely)
|
|
33
|
+
# @option [Proc, #call] options :release_fxn (nil) A proc to run when the
|
|
34
|
+
# lock is released
|
|
35
|
+
# @option [String] options :desc (nil) A description of the lock
|
|
36
|
+
def initialize(file, opts={:timeout => -1})
|
|
37
|
+
@file = file
|
|
38
|
+
@held = false
|
|
39
|
+
@timeout = opts[:timeout]
|
|
40
|
+
@release_fxn = opts[:release_fxn]
|
|
41
|
+
@description = opts[:desc]
|
|
42
|
+
apply_lock
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
##
|
|
46
|
+
# Applies the lock. Will sleep the thread for +timeout+ time trying to apply the lock before
|
|
47
|
+
# giving up and raising an error.
|
|
48
|
+
def apply_lock
|
|
49
|
+
timeout = @timeout
|
|
50
|
+
while true do
|
|
51
|
+
begin
|
|
52
|
+
# try_lock will raise of there is already a lock.
|
|
53
|
+
try_lock
|
|
54
|
+
return true
|
|
55
|
+
rescue LockHeld => e
|
|
56
|
+
# We'll put up with this exception for @timeout times, then give up.
|
|
57
|
+
if timeout != 0
|
|
58
|
+
sleep(1)
|
|
59
|
+
timeout > 0 && timeout -= 1
|
|
60
|
+
next
|
|
61
|
+
end
|
|
62
|
+
# Timeout's up? Raise an exception.
|
|
63
|
+
raise LockHeld.new(Errno::ETIMEDOUT::Errno, e.filename, @desc, e.locker)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
##
|
|
69
|
+
# Attempts to apply the lock. Raises if unsuccessful. Contains the logic for actually naming
|
|
70
|
+
# the lock.
|
|
71
|
+
def try_lock
|
|
72
|
+
if @@host.nil?
|
|
73
|
+
@@host = Socket.gethostname
|
|
74
|
+
end
|
|
75
|
+
lockname = "#{@@host}:#{Process.pid}"
|
|
76
|
+
while !@held
|
|
77
|
+
begin
|
|
78
|
+
make_a_lock(@file, lockname)
|
|
79
|
+
@held = true
|
|
80
|
+
rescue Errno::EEXIST
|
|
81
|
+
locker = test_lock
|
|
82
|
+
unless locker.nil?
|
|
83
|
+
raise LockHeld.new(Errno::EAGAIN::Errno, @file, @desc, locker)
|
|
84
|
+
end
|
|
85
|
+
rescue SystemCallError => e
|
|
86
|
+
raise LockUnavailable.new(e.errno, e.to_s, @file, @desc)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
##
|
|
92
|
+
# Creates a lock at the given location, with info about the locking process. Uses
|
|
93
|
+
# a symlink if possible, because even over NFS, creating a symlink is atomic. Nice.
|
|
94
|
+
# Otherwise, it will call make_a_lock_in_file on inferior OS's (cough windows cough)
|
|
95
|
+
# and put the data in there.
|
|
96
|
+
#
|
|
97
|
+
# The symlink is actually a non-working symlink - it points the filename (such as "hglock")
|
|
98
|
+
# to the data, even though the data is not an actual file. So hglock -> "medgar:25043" is
|
|
99
|
+
# a sort-of possible lock this method would create.
|
|
100
|
+
#
|
|
101
|
+
# @param [String] file the filename of the lock
|
|
102
|
+
# @param [String] info the info to store in the lock
|
|
103
|
+
def make_a_lock(file, info)
|
|
104
|
+
begin
|
|
105
|
+
File.symlink(info, file)
|
|
106
|
+
rescue Errno::EEXIST
|
|
107
|
+
raise
|
|
108
|
+
rescue
|
|
109
|
+
make_a_lock_in_file(file, info)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
##
|
|
114
|
+
# Creates a lock at the given location, storing the info about the locking process in
|
|
115
|
+
# an actual lock file. These locks are not preferred, because symlinks are atomic even
|
|
116
|
+
# over NFS. Anyway, very simple. Create the file, write in the info, close 'er up.
|
|
117
|
+
# That's 1 line in ruby, folks.
|
|
118
|
+
#
|
|
119
|
+
# @see make_a_lock
|
|
120
|
+
# @param [String] file the filename of the lock
|
|
121
|
+
# @param [String] info the info to store in the lock
|
|
122
|
+
def make_a_lock_in_file(file, info)
|
|
123
|
+
File.open(file, "w+") {|out| out.write info }
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
##
|
|
127
|
+
# Reads in the data associated with a lock file.
|
|
128
|
+
#
|
|
129
|
+
# @param [String] file the path to the lock file to read
|
|
130
|
+
# @return [String] the data in the lock. In the format "#{locking_host}:#{locking_pid}"
|
|
131
|
+
def read_lock(file)
|
|
132
|
+
begin
|
|
133
|
+
return File.readlink(file)
|
|
134
|
+
rescue Errno::EINVAL, Errno::ENOSYS
|
|
135
|
+
return File.read(file)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
##
|
|
140
|
+
# Checks to see if there is a process running with id +pid+.
|
|
141
|
+
#
|
|
142
|
+
# @param [Fixnum] pid the process ID to look up
|
|
143
|
+
# @return [Boolean] is there a process with the given pid?
|
|
144
|
+
def test_pid(pid)
|
|
145
|
+
return true if Platform::OS == :vms
|
|
146
|
+
|
|
147
|
+
begin
|
|
148
|
+
# Doesn't actually kill it
|
|
149
|
+
Process.kill(0, pid)
|
|
150
|
+
true
|
|
151
|
+
rescue Errno::ESRCH::Errno
|
|
152
|
+
true
|
|
153
|
+
rescue
|
|
154
|
+
false
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
##
|
|
160
|
+
# Text from mercurial code:
|
|
161
|
+
#
|
|
162
|
+
# return id of locker if lock is valid, else None.
|
|
163
|
+
#
|
|
164
|
+
# If old-style lock, we cannot tell what machine locker is on.
|
|
165
|
+
# with new-style lock, if locker is on this machine, we can
|
|
166
|
+
# see if locker is alive. If locker is on this machine but
|
|
167
|
+
# not alive, we can safely break lock.
|
|
168
|
+
#
|
|
169
|
+
# The lock file is only deleted when None is returned.
|
|
170
|
+
def test_lock
|
|
171
|
+
locker = read_lock(@file)
|
|
172
|
+
host, pid = locker.split(":", 1)
|
|
173
|
+
return locker if pid.nil? || host != @@host
|
|
174
|
+
|
|
175
|
+
pid = pid.to_i
|
|
176
|
+
return locker if pid == 0
|
|
177
|
+
|
|
178
|
+
return locker if test_pid pid
|
|
179
|
+
|
|
180
|
+
# if locker dead, break lock. must do this with another lock
|
|
181
|
+
# held, or can race and break valid lock.
|
|
182
|
+
begin
|
|
183
|
+
the_lock = Lock.new(@file + ".break")
|
|
184
|
+
the_lock.try_lock
|
|
185
|
+
File.unlink(@file)
|
|
186
|
+
the_lock.release
|
|
187
|
+
rescue LockError
|
|
188
|
+
return locker
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
##
|
|
193
|
+
# Releases the lock, signalling that it is now safe to modify the directory in which
|
|
194
|
+
# the lock is found.
|
|
195
|
+
def release
|
|
196
|
+
if @held
|
|
197
|
+
@held = false
|
|
198
|
+
@release_fxn.call if @release_fxn
|
|
199
|
+
|
|
200
|
+
File.unlink(@file) rescue ""
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
module Amp
|
|
2
|
+
module Repositories
|
|
3
|
+
|
|
4
|
+
##
|
|
5
|
+
# = BundleRepository
|
|
6
|
+
# This class represents a read-only repository that combines both local
|
|
7
|
+
# repository data with a bundle file. The bundle file contains un-merged-in
|
|
8
|
+
# changesets - this is useful for, say, previewing the results of a pull
|
|
9
|
+
# action.
|
|
10
|
+
#
|
|
11
|
+
# A bundle is stored in the following manner:
|
|
12
|
+
# - Changelog entries
|
|
13
|
+
# - Manifest entries
|
|
14
|
+
# - Modified File entry #1
|
|
15
|
+
# - Modified File entry #2
|
|
16
|
+
# - ...
|
|
17
|
+
# - Modified file entry #N
|
|
18
|
+
class BundleRepository < LocalRepository
|
|
19
|
+
def initialize(path="", config=nil, bundle_name="")
|
|
20
|
+
@temp_parent = nil
|
|
21
|
+
# Figure out what to do here - if there's no current local repository, that
|
|
22
|
+
# takes some special work.
|
|
23
|
+
begin
|
|
24
|
+
super(path, false, config) # don't create, just look for a repository
|
|
25
|
+
rescue
|
|
26
|
+
# Ok, no local repository. Let's make one really quickly.
|
|
27
|
+
@temp_parent = File.join(Dir.tmpdir, File.amp_make_tmpname("bundlerepo"))
|
|
28
|
+
File.mkdir(@temp_parent)
|
|
29
|
+
tmprepo = LocalRepository.new(@temp_parent, true, config) # true -> create
|
|
30
|
+
super(@temp_parent, false, config) # and proceed as scheduled!
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Set up our URL variable, if anyone asks us what it is
|
|
34
|
+
if path
|
|
35
|
+
@url = "bundle:#{path}+#{bundle_name}"
|
|
36
|
+
else
|
|
37
|
+
@url = "bundle:#{bundle_name}"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
@temp_file = nil
|
|
41
|
+
@bundle_file = File.open(bundle_name, "r")
|
|
42
|
+
|
|
43
|
+
@bundle_file.seek(0, IO::SEEK_END)
|
|
44
|
+
Amp::UI.debug "Bundle File Size: #{@bundle_file.tell}"
|
|
45
|
+
@bundle_file.seek(0, IO::SEEK_SET)
|
|
46
|
+
|
|
47
|
+
# OK, now for the fun part - check the header to see if we're compressed.
|
|
48
|
+
header = @bundle_file.read(6)
|
|
49
|
+
# And switch based on that header
|
|
50
|
+
if !header.start_with?("HG")
|
|
51
|
+
# Not even an HG file. FML. Bail
|
|
52
|
+
raise abort("#{bundle_name}: not a Mercurial bundle file")
|
|
53
|
+
elsif not header.start_with?("HG10")
|
|
54
|
+
# Not a version we understand, bail
|
|
55
|
+
raise abort("#{bundle_name}: unknown bundle version")
|
|
56
|
+
elsif header == "HG10BZ" || header == "HG10GZ"
|
|
57
|
+
# Compressed! We'll have to save to a new file, because this could get messy.
|
|
58
|
+
temp_file = Tempfile.new("hg-bundle-hg10un", @root)
|
|
59
|
+
@temp_file_path = temp_file.path
|
|
60
|
+
# Are we BZip, or GZip?
|
|
61
|
+
case header
|
|
62
|
+
when "HG10BZ"
|
|
63
|
+
# fuck BZip. Seriously.
|
|
64
|
+
headerio = StringIO.new "BZ", (ruby_19? ? "w+:ASCII-8BIT" : "w+")
|
|
65
|
+
input = Amp::Support::MultiIO.new(headerio, @bundle_file)
|
|
66
|
+
decomp = BZ2::Reader.new(input)
|
|
67
|
+
when "HG10GZ"
|
|
68
|
+
# Gzip is much nicer.
|
|
69
|
+
decomp = Zlib::GzipReader.new(@bundle_file)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# We're writing this in an uncompressed fashion, of course.
|
|
73
|
+
@temp_file.write("HG10UN")
|
|
74
|
+
# While we can uncompressed....
|
|
75
|
+
while !r.eof? do
|
|
76
|
+
# Write the uncompressed data to our new file!
|
|
77
|
+
@temp_file.write decomp.read(4096)
|
|
78
|
+
end
|
|
79
|
+
# and close 'er up
|
|
80
|
+
@temp_file.close
|
|
81
|
+
|
|
82
|
+
# Close the compressed bundle file
|
|
83
|
+
@bundle_file.close
|
|
84
|
+
# And re-open the uncompressed bundle file!
|
|
85
|
+
@bundle_file = File.open(@temp_file_path, "r")
|
|
86
|
+
# Skip the header.
|
|
87
|
+
@bundle_file.seek(6)
|
|
88
|
+
elsif header == "HG10UN"
|
|
89
|
+
# uncompressed, do nothing
|
|
90
|
+
else
|
|
91
|
+
# We have no idae what's going on
|
|
92
|
+
raise abort("#{bundle_name}: unknown bundle compression type")
|
|
93
|
+
end
|
|
94
|
+
# This hash stores pairs of {filename => position_in_bundle_file_of_this_file}
|
|
95
|
+
@bundle_files_positions = {}
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
##
|
|
99
|
+
# Gets the changelog of the repository. This is different from {LocalRepository#changelog}
|
|
100
|
+
# in that it uses a {BundleChangeLog}. Also, since the manifest is stored in the bundle
|
|
101
|
+
# directly after the changelog, by checking our position in the bundle file, we can save
|
|
102
|
+
# where the bundle_file is stored.
|
|
103
|
+
#
|
|
104
|
+
# @return [BundleChangeLog] the changelog for this repository.
|
|
105
|
+
def changelog
|
|
106
|
+
@changelog ||= Bundles::BundleChangeLog.new(@store.opener, @bundle_file)
|
|
107
|
+
@manifest_start ||= @bundle_file.tell
|
|
108
|
+
@changelog
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
##
|
|
112
|
+
# Gets the manifest of the repository. This is different from {LocalRepository#manifest}
|
|
113
|
+
# in that it uses a {BundleManifest}. The file logs are stored in the bundle directly
|
|
114
|
+
# after the manifest, so once we load the manifest, we save where the file logs start
|
|
115
|
+
# when we are done loading the manifest.
|
|
116
|
+
#
|
|
117
|
+
# This has the side-effect of loading the changelog, if it hasn't been loaded already -#
|
|
118
|
+
# this is necessary because the manifest changesets are stored after the changelog changesets,
|
|
119
|
+
# and we must fully load the changelog changesets to know where to look for the manifest changesets.
|
|
120
|
+
#
|
|
121
|
+
# Don't look at me, I didn't design the file format.
|
|
122
|
+
#
|
|
123
|
+
# @return [BundleChangeLog] the changelog for this repository.
|
|
124
|
+
def manifest
|
|
125
|
+
return @manifest if @manifest
|
|
126
|
+
@bundle_file.seek manifest_start
|
|
127
|
+
@manifest ||= Bundles::BundleManifest.new @store.opener, @bundle_file, proc {|n| changelog.rev(n) }
|
|
128
|
+
@file_start ||= @bundle_file.tell
|
|
129
|
+
@manifest
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
##
|
|
133
|
+
# Returns the position in the bundle file where the manifest changesets are located.
|
|
134
|
+
# This involves loading the changelog first - see {#manifest}
|
|
135
|
+
#
|
|
136
|
+
# @return [Integer] the position in the bundle file where we can find the manifest
|
|
137
|
+
# changesets.
|
|
138
|
+
def manifest_start
|
|
139
|
+
changelog && @manifest_start
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
##
|
|
143
|
+
# Returns the position in the bundle file where the file log changesets are located.
|
|
144
|
+
# This involves loading the changelog and the manifest first - see {#manifest}.
|
|
145
|
+
#
|
|
146
|
+
# @return [Integer] the position in the bundle file where we can find the file-log
|
|
147
|
+
# changesets.
|
|
148
|
+
def file_start
|
|
149
|
+
manifest && @file_start
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
##
|
|
153
|
+
# Gets the file-log for the given path, so we can look at an individual
|
|
154
|
+
# file's history, for example. However, we need to be cognizant of files that
|
|
155
|
+
# traverse the local repository's history as well as the bundle file.
|
|
156
|
+
#
|
|
157
|
+
# @param [String] f the path to the file
|
|
158
|
+
# @return [FileLog] a filelog (a type of revision log) for the given file
|
|
159
|
+
def file(filename)
|
|
160
|
+
|
|
161
|
+
# Load the file-log positions now - we didn't do this in the constructor for a reason
|
|
162
|
+
# (if they don't ask for them, don't load them!)
|
|
163
|
+
if @bundle_files_positions.empty?
|
|
164
|
+
# Jump to the file position
|
|
165
|
+
@bundle_file.seek file_start
|
|
166
|
+
while true
|
|
167
|
+
# get a changegroup chunk - it'll be the filename
|
|
168
|
+
chunk = RevlogSupport::ChangeGroup.get_chunk @bundle_file
|
|
169
|
+
# no filename? bail
|
|
170
|
+
break if chunk.nil? || chunk.empty?
|
|
171
|
+
|
|
172
|
+
# Now that we've read the filename, we're at the start of the changelogs for that
|
|
173
|
+
# file. So let's save this position for later.
|
|
174
|
+
@bundle_files_positions[chunk] = @bundle_file.tell
|
|
175
|
+
# Then read chunks until we get to the next file!
|
|
176
|
+
RevlogSupport::ChangeGroup.each_chunk(@bundle_file) {|c|}
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Remove leading slash
|
|
181
|
+
filename = filename.shift("/")
|
|
182
|
+
|
|
183
|
+
# Does this file cross local history as well as the bundle?
|
|
184
|
+
if @bundle_files_positions[filename]
|
|
185
|
+
# If so, we'll need to make a BundleFileLog. Meh.
|
|
186
|
+
@bundle_file.seek @bundle_files_positions[filename]
|
|
187
|
+
Bundles::BundleFileLog.new @store.opener, filename, @bundle_file, proc {|n| changelog.rev(n) }
|
|
188
|
+
else
|
|
189
|
+
# Nope? Make a normal FileLog!
|
|
190
|
+
FileLog.new(@store.opener, filename)
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
##
|
|
195
|
+
# Gets the URL for this repository - unused, I believe.
|
|
196
|
+
#
|
|
197
|
+
# @return [String] the URL for the repository
|
|
198
|
+
def url; @url; end
|
|
199
|
+
|
|
200
|
+
##
|
|
201
|
+
# Closes the repository - in this case, it closes the bundle_file. Analogous to closing
|
|
202
|
+
# an SSHRepository's socket.
|
|
203
|
+
def close
|
|
204
|
+
@bundle_file.close
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# We can't copy files. Read-only.
|
|
208
|
+
def can_copy?; false; end
|
|
209
|
+
# Gets the current working directory. Not sure why we need this.
|
|
210
|
+
def get_cwd; Dir.pwd; end
|
|
211
|
+
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|