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.
- data/.gitignore +12 -0
- data/.hgignore +3 -0
- data/AUTHORS +1 -1
- data/Manifest.txt +99 -38
- data/README.md +3 -3
- data/Rakefile +53 -18
- data/SCHEDULE.markdown +5 -1
- data/TODO.markdown +120 -149
- data/ampfile.rb +3 -1
- data/bin/amp +4 -1
- data/ext/amp/bz2/extconf.rb +1 -1
- data/ext/amp/mercurial_patch/extconf.rb +1 -1
- data/ext/amp/mercurial_patch/mpatch.c +4 -3
- data/ext/amp/priority_queue/extconf.rb +1 -1
- data/ext/amp/support/extconf.rb +1 -1
- data/ext/amp/support/support.c +1 -1
- data/lib/amp.rb +125 -67
- data/lib/amp/commands/command.rb +12 -10
- data/lib/amp/commands/command_support.rb +8 -1
- data/lib/amp/commands/commands/help.rb +2 -20
- data/lib/amp/commands/commands/init.rb +14 -2
- data/lib/amp/commands/commands/templates.rb +6 -4
- data/lib/amp/commands/commands/version.rb +15 -1
- data/lib/amp/commands/commands/workflow.rb +3 -3
- data/lib/amp/commands/commands/workflows/git/add.rb +3 -3
- data/lib/amp/commands/commands/workflows/git/copy.rb +1 -1
- data/lib/amp/commands/commands/workflows/git/rm.rb +4 -2
- data/lib/amp/commands/commands/workflows/hg/add.rb +1 -1
- data/lib/amp/commands/commands/workflows/hg/addremove.rb +2 -2
- data/lib/amp/commands/commands/workflows/hg/annotate.rb +8 -2
- data/lib/amp/commands/commands/workflows/hg/bisect.rb +253 -0
- data/lib/amp/commands/commands/workflows/hg/branch.rb +1 -1
- data/lib/amp/commands/commands/workflows/hg/branches.rb +3 -3
- data/lib/amp/commands/commands/workflows/hg/bundle.rb +3 -3
- data/lib/amp/commands/commands/workflows/hg/clone.rb +4 -5
- data/lib/amp/commands/commands/workflows/hg/commit.rb +37 -1
- data/lib/amp/commands/commands/workflows/hg/copy.rb +2 -1
- data/lib/amp/commands/commands/workflows/hg/debug/index.rb +1 -1
- data/lib/amp/commands/commands/workflows/hg/diff.rb +3 -8
- data/lib/amp/commands/commands/workflows/hg/forget.rb +5 -4
- data/lib/amp/commands/commands/workflows/hg/identify.rb +6 -6
- data/lib/amp/commands/commands/workflows/hg/import.rb +1 -1
- data/lib/amp/commands/commands/workflows/hg/incoming.rb +2 -2
- data/lib/amp/commands/commands/workflows/hg/log.rb +5 -4
- data/lib/amp/commands/commands/workflows/hg/merge.rb +1 -1
- data/lib/amp/commands/commands/workflows/hg/move.rb +5 -3
- data/lib/amp/commands/commands/workflows/hg/outgoing.rb +1 -1
- data/lib/amp/commands/commands/workflows/hg/push.rb +6 -7
- data/lib/amp/commands/commands/workflows/hg/remove.rb +2 -2
- data/lib/amp/commands/commands/workflows/hg/resolve.rb +6 -23
- data/lib/amp/commands/commands/workflows/hg/root.rb +1 -2
- data/lib/amp/commands/commands/workflows/hg/status.rb +21 -12
- data/lib/amp/commands/commands/workflows/hg/tag.rb +2 -2
- data/lib/amp/commands/commands/workflows/hg/untrack.rb +12 -0
- data/lib/amp/commands/commands/workflows/hg/verify.rb +13 -3
- data/lib/amp/commands/commands/workflows/hg/what_changed.rb +18 -0
- data/lib/amp/commands/dispatch.rb +12 -13
- data/lib/amp/dependencies/amp_support.rb +1 -1
- data/lib/amp/dependencies/amp_support/ruby_amp_support.rb +1 -0
- data/lib/amp/dependencies/maruku.rb +136 -0
- data/lib/amp/dependencies/maruku/attributes.rb +227 -0
- data/lib/amp/dependencies/maruku/defaults.rb +71 -0
- data/lib/amp/dependencies/maruku/errors_management.rb +92 -0
- data/lib/amp/dependencies/maruku/helpers.rb +260 -0
- data/lib/amp/dependencies/maruku/input/charsource.rb +326 -0
- data/lib/amp/dependencies/maruku/input/extensions.rb +69 -0
- data/lib/amp/dependencies/maruku/input/html_helper.rb +189 -0
- data/lib/amp/dependencies/maruku/input/linesource.rb +111 -0
- data/lib/amp/dependencies/maruku/input/parse_block.rb +615 -0
- data/lib/amp/dependencies/maruku/input/parse_doc.rb +234 -0
- data/lib/amp/dependencies/maruku/input/parse_span_better.rb +746 -0
- data/lib/amp/dependencies/maruku/input/rubypants.rb +225 -0
- data/lib/amp/dependencies/maruku/input/type_detection.rb +147 -0
- data/lib/amp/dependencies/maruku/input_textile2/t2_parser.rb +163 -0
- data/lib/amp/dependencies/maruku/maruku.rb +33 -0
- data/lib/amp/dependencies/maruku/output/to_ansi.rb +223 -0
- data/lib/amp/dependencies/maruku/output/to_html.rb +991 -0
- data/lib/amp/dependencies/maruku/output/to_markdown.rb +164 -0
- data/lib/amp/dependencies/maruku/output/to_s.rb +56 -0
- data/lib/amp/dependencies/maruku/string_utils.rb +191 -0
- data/lib/amp/dependencies/maruku/structures.rb +167 -0
- data/lib/amp/dependencies/maruku/structures_inspect.rb +87 -0
- data/lib/amp/dependencies/maruku/structures_iterators.rb +61 -0
- data/lib/amp/dependencies/maruku/textile2.rb +1 -0
- data/lib/amp/dependencies/maruku/toc.rb +199 -0
- data/lib/amp/dependencies/maruku/usage/example1.rb +33 -0
- data/lib/amp/dependencies/maruku/version.rb +40 -0
- data/lib/amp/dependencies/priority_queue.rb +2 -1
- data/lib/amp/dependencies/python_config.rb +2 -1
- data/lib/amp/graphs/ancestor.rb +2 -1
- data/lib/amp/graphs/copies.rb +236 -233
- data/lib/amp/help/entries/__default__.erb +31 -0
- data/lib/amp/help/entries/commands.erb +6 -0
- data/lib/amp/help/entries/mdtest.md +35 -0
- data/lib/amp/help/entries/silly +3 -0
- data/lib/amp/help/help.rb +288 -0
- data/lib/amp/profiling_hacks.rb +5 -3
- data/lib/amp/repository/abstract/abstract_changeset.rb +97 -0
- data/lib/amp/repository/abstract/abstract_local_repo.rb +181 -0
- data/lib/amp/repository/abstract/abstract_staging_area.rb +180 -0
- data/lib/amp/repository/abstract/abstract_versioned_file.rb +100 -0
- data/lib/amp/repository/abstract/common_methods/changeset.rb +75 -0
- data/lib/amp/repository/abstract/common_methods/local_repo.rb +277 -0
- data/lib/amp/repository/abstract/common_methods/staging_area.rb +233 -0
- data/lib/amp/repository/abstract/common_methods/versioned_file.rb +71 -0
- data/lib/amp/repository/generic_repo_picker.rb +78 -0
- data/lib/amp/repository/git/repo_format/changeset.rb +336 -0
- data/lib/amp/repository/git/repo_format/staging_area.rb +192 -0
- data/lib/amp/repository/git/repo_format/versioned_file.rb +119 -0
- data/lib/amp/repository/git/repositories/local_repository.rb +164 -0
- data/lib/amp/repository/git/repository.rb +41 -0
- data/lib/amp/repository/mercurial/encoding/mercurial_diff.rb +382 -0
- data/lib/amp/repository/mercurial/encoding/mercurial_patch.rb +1 -0
- data/lib/amp/repository/mercurial/encoding/patch.rb +294 -0
- data/lib/amp/repository/mercurial/encoding/pure_ruby/ruby_mercurial_patch.rb +124 -0
- data/lib/amp/repository/mercurial/merging/merge_ui.rb +327 -0
- data/lib/amp/repository/mercurial/merging/simple_merge.rb +452 -0
- data/lib/amp/repository/mercurial/repo_format/branch_manager.rb +266 -0
- data/lib/amp/repository/mercurial/repo_format/changeset.rb +768 -0
- data/lib/amp/repository/mercurial/repo_format/dir_state.rb +716 -0
- data/lib/amp/repository/mercurial/repo_format/journal.rb +218 -0
- data/lib/amp/repository/mercurial/repo_format/lock.rb +210 -0
- data/lib/amp/repository/mercurial/repo_format/merge_state.rb +228 -0
- data/lib/amp/repository/mercurial/repo_format/staging_area.rb +367 -0
- data/lib/amp/repository/mercurial/repo_format/store.rb +487 -0
- data/lib/amp/repository/mercurial/repo_format/tag_manager.rb +322 -0
- data/lib/amp/repository/mercurial/repo_format/updatable.rb +543 -0
- data/lib/amp/repository/mercurial/repo_format/updater.rb +848 -0
- data/lib/amp/repository/mercurial/repo_format/verification.rb +433 -0
- data/lib/amp/repository/mercurial/repositories/bundle_repository.rb +216 -0
- data/lib/amp/repository/mercurial/repositories/http_repository.rb +386 -0
- data/lib/amp/repository/mercurial/repositories/local_repository.rb +2034 -0
- data/lib/amp/repository/mercurial/repository.rb +119 -0
- data/lib/amp/repository/mercurial/revlogs/bundle_revlogs.rb +249 -0
- data/lib/amp/repository/mercurial/revlogs/changegroup.rb +217 -0
- data/lib/amp/repository/mercurial/revlogs/changelog.rb +339 -0
- data/lib/amp/repository/mercurial/revlogs/file_log.rb +152 -0
- data/lib/amp/repository/mercurial/revlogs/index.rb +500 -0
- data/lib/amp/repository/mercurial/revlogs/manifest.rb +201 -0
- data/lib/amp/repository/mercurial/revlogs/node.rb +20 -0
- data/lib/amp/repository/mercurial/revlogs/revlog.rb +1026 -0
- data/lib/amp/repository/mercurial/revlogs/revlog_support.rb +129 -0
- data/lib/amp/repository/mercurial/revlogs/versioned_file.rb +597 -0
- data/lib/amp/repository/repository.rb +11 -88
- data/lib/amp/server/extension/amp_extension.rb +3 -3
- data/lib/amp/server/fancy_http_server.rb +1 -1
- data/lib/amp/server/fancy_views/_browser.haml +1 -1
- data/lib/amp/server/fancy_views/_diff_file.haml +1 -8
- data/lib/amp/server/fancy_views/changeset.haml +2 -2
- data/lib/amp/server/fancy_views/file.haml +1 -1
- data/lib/amp/server/fancy_views/file_diff.haml +1 -1
- data/lib/amp/support/amp_ui.rb +13 -29
- data/lib/amp/support/generator.rb +1 -1
- data/lib/amp/support/loaders.rb +1 -2
- data/lib/amp/support/logger.rb +10 -16
- data/lib/amp/support/match.rb +18 -4
- data/lib/amp/support/mercurial/ignore.rb +151 -0
- data/lib/amp/support/openers.rb +8 -3
- data/lib/amp/support/support.rb +91 -46
- data/lib/amp/templates/{blank.commit.erb → mercurial/blank.commit.erb} +0 -0
- data/lib/amp/templates/{blank.log.erb → mercurial/blank.log.erb} +0 -0
- data/lib/amp/templates/{default.commit.erb → mercurial/default.commit.erb} +0 -0
- data/lib/amp/templates/{default.log.erb → mercurial/default.log.erb} +0 -0
- data/lib/amp/templates/template.rb +18 -18
- data/man/amp.1 +51 -0
- data/site/src/about/commands.haml +1 -1
- data/site/src/css/amp.css +1 -1
- data/site/src/index.haml +3 -3
- data/tasks/man.rake +39 -0
- data/tasks/stats.rake +1 -10
- data/tasks/yard.rake +1 -50
- data/test/dirstate_tests/test_dir_state.rb +10 -8
- data/test/functional_tests/annotate.out +31 -0
- data/test/functional_tests/test_functional.rb +155 -63
- data/test/localrepo_tests/ampfile.rb +12 -0
- data/test/localrepo_tests/test_local_repo.rb +56 -57
- data/test/manifest_tests/test_manifest.rb +3 -5
- data/test/merge_tests/test_merge.rb +3 -3
- data/test/revlog_tests/test_revlog.rb +14 -6
- data/test/store_tests/test_fncache_store.rb +19 -19
- data/test/test_19_compatibility.rb +46 -0
- data/test/test_base85.rb +2 -2
- data/test/test_bdiff.rb +2 -2
- data/test/test_changegroup.rb +59 -0
- data/test/test_commands.rb +2 -2
- data/test/test_difflib.rb +2 -2
- data/test/test_generator.rb +34 -0
- data/test/test_ignore.rb +203 -0
- data/test/test_journal.rb +18 -13
- data/test/test_match.rb +2 -2
- data/test/test_mdiff.rb +3 -3
- data/test/test_mpatch.rb +3 -3
- data/test/test_multi_io.rb +40 -0
- data/test/test_support.rb +18 -2
- data/test/test_templates.rb +38 -0
- data/test/test_ui.rb +79 -0
- data/test/testutilities.rb +56 -0
- metadata +168 -49
- data/ext/amp/bz2/mkmf.log +0 -38
- data/lib/amp/encoding/mercurial_diff.rb +0 -378
- data/lib/amp/encoding/mercurial_patch.rb +0 -1
- data/lib/amp/encoding/patch.rb +0 -292
- data/lib/amp/encoding/pure_ruby/ruby_mercurial_patch.rb +0 -123
- data/lib/amp/merges/merge_state.rb +0 -164
- data/lib/amp/merges/merge_ui.rb +0 -322
- data/lib/amp/merges/simple_merge.rb +0 -450
- data/lib/amp/repository/branch_manager.rb +0 -234
- data/lib/amp/repository/dir_state.rb +0 -950
- data/lib/amp/repository/journal.rb +0 -203
- data/lib/amp/repository/lock.rb +0 -207
- data/lib/amp/repository/repositories/bundle_repository.rb +0 -214
- data/lib/amp/repository/repositories/http_repository.rb +0 -377
- data/lib/amp/repository/repositories/local_repository.rb +0 -2661
- data/lib/amp/repository/store.rb +0 -485
- data/lib/amp/repository/tag_manager.rb +0 -319
- data/lib/amp/repository/updatable.rb +0 -532
- data/lib/amp/repository/verification.rb +0 -431
- data/lib/amp/repository/versioned_file.rb +0 -475
- data/lib/amp/revlogs/bundle_revlogs.rb +0 -246
- data/lib/amp/revlogs/changegroup.rb +0 -217
- data/lib/amp/revlogs/changelog.rb +0 -338
- data/lib/amp/revlogs/changeset.rb +0 -521
- data/lib/amp/revlogs/file_log.rb +0 -165
- data/lib/amp/revlogs/index.rb +0 -493
- data/lib/amp/revlogs/manifest.rb +0 -195
- data/lib/amp/revlogs/node.rb +0 -18
- data/lib/amp/revlogs/revlog.rb +0 -1045
- data/lib/amp/revlogs/revlog_support.rb +0 -126
- data/lib/amp/support/ignore.rb +0 -144
- data/site/Rakefile +0 -38
- data/test/test_amp.rb +0 -9
- data/test/test_helper.rb +0 -15
data/lib/amp/graphs/ancestor.rb
CHANGED
data/lib/amp/graphs/copies.rb
CHANGED
|
@@ -1,260 +1,263 @@
|
|
|
1
1
|
module Amp
|
|
2
2
|
module Graphs
|
|
3
|
-
|
|
4
|
-
# = CopyCalculator
|
|
5
|
-
#
|
|
6
|
-
# This module manages finding what files have been copied between two
|
|
7
|
-
# changesets, using a base, ancestor changeset. Closely related to merging.
|
|
8
|
-
# We need this class because Mercurial, by default, allows us to copy files
|
|
9
|
-
# and move files, and be smart enough to follow these copies throughout the
|
|
10
|
-
# version history. Other VCS's just treat the moved file as a brand-new file.
|
|
11
|
-
# Thus, when we update from one changeset to another, we need to follow
|
|
12
|
-
# these copies.
|
|
13
|
-
module CopyCalculator
|
|
3
|
+
module Mercurial
|
|
14
4
|
|
|
15
5
|
##
|
|
16
|
-
#
|
|
17
|
-
# node. This is used during updates as part of Mercurial's ability to track renames
|
|
18
|
-
# without git-style guessing. Unfortunately it does require some amount of calculation.
|
|
19
|
-
# This method returns two hashes in an array: [renames, divergent]. "Renames" are
|
|
20
|
-
# moves from one file to another, and "divergent" are two moves of the same file,
|
|
21
|
-
# only with different end-names. See @example for how divergent works.
|
|
6
|
+
# = CopyCalculator
|
|
22
7
|
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
|
|
31
|
-
# a LocalRepository.
|
|
32
|
-
# @param [Changeset] changeset_local The local (or just 1 of the bases) changeset.
|
|
33
|
-
# @param [Changeset] changeset_remote The remote (or the second base) changeset
|
|
34
|
-
# @param [Changeset] changeset_ancestor The common ancestor between {changeset_local}
|
|
35
|
-
# and {changeset_remote}
|
|
36
|
-
# @param [Boolean] check_dirs (false) Whether or not to analyze for directory renames.
|
|
37
|
-
# this is an expensive operation, so it defaults to false.
|
|
38
|
-
# @return [[Hash, Hash]] This method returns two hashes in an array, where the first
|
|
39
|
-
# is a list of normal file-moves ("foo" renamed to "bar" returns {"foo" => "bar"})
|
|
40
|
-
# and the second is a list of divergent file-moves (see @example)
|
|
41
|
-
#
|
|
42
|
-
def self.find_copies(repo, changeset_local, changeset_remote, changeset_ancestor, check_dirs=false)
|
|
43
|
-
# are we udpating from an empty directory? quite easy.
|
|
44
|
-
if changeset_local.nil? || changeset_remote.nil? ||
|
|
45
|
-
changeset_remote == changeset_local
|
|
46
|
-
return {}, {}
|
|
47
|
-
end
|
|
48
|
-
# avoid silly behavior for parent -> working directory
|
|
49
|
-
if changeset_remote.node == nil && c1.node == repo.dirstate.parents.first
|
|
50
|
-
return repo.dirstate.copies, {}
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
limit = find_limit(repo, changeset_local.revision, changeset_remote.revision)
|
|
54
|
-
man_local = changeset_local.manifest
|
|
55
|
-
man_remote = changeset_remote.manifest
|
|
56
|
-
man_ancestor = changeset_ancestor.manifest
|
|
8
|
+
# This module manages finding what files have been copied between two
|
|
9
|
+
# changesets, using a base, ancestor changeset. Closely related to merging.
|
|
10
|
+
# We need this class because Mercurial, by default, allows us to copy files
|
|
11
|
+
# and move files, and be smart enough to follow these copies throughout the
|
|
12
|
+
# version history. Other VCS's just treat the moved file as a brand-new file.
|
|
13
|
+
# Thus, when we update from one changeset to another, we need to follow
|
|
14
|
+
# these copies.
|
|
15
|
+
module CopyCalculator
|
|
57
16
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
17
|
+
##
|
|
18
|
+
# Calculates the copies between 2 changesets, using a pre-calculated common ancestor
|
|
19
|
+
# node. This is used during updates as part of Mercurial's ability to track renames
|
|
20
|
+
# without git-style guessing. Unfortunately it does require some amount of calculation.
|
|
21
|
+
# This method returns two hashes in an array: [renames, divergent]. "Renames" are
|
|
22
|
+
# moves from one file to another, and "divergent" are two moves of the same file,
|
|
23
|
+
# only with different end-names. See @example for how divergent works.
|
|
24
|
+
#
|
|
25
|
+
# @todo Add tracking of directory renames!
|
|
26
|
+
#
|
|
27
|
+
# @example
|
|
28
|
+
# if the local changeset renamed "foo" to "bar", and the remote changeset renamed
|
|
29
|
+
# "foo" to "baz", then the "divergent" hash would be:
|
|
30
|
+
# {"foo" => ["bar", "baz"]}
|
|
31
|
+
#
|
|
32
|
+
# @param [Repository] repo The repo for which we are calculating changes. Typically
|
|
33
|
+
# a LocalRepository.
|
|
34
|
+
# @param [Changeset] changeset_local The local (or just 1 of the bases) changeset.
|
|
35
|
+
# @param [Changeset] changeset_remote The remote (or the second base) changeset
|
|
36
|
+
# @param [Changeset] changeset_ancestor The common ancestor between {changeset_local}
|
|
37
|
+
# and {changeset_remote}
|
|
38
|
+
# @param [Boolean] check_dirs (false) Whether or not to analyze for directory renames.
|
|
39
|
+
# this is an expensive operation, so it defaults to false.
|
|
40
|
+
# @return [[Hash, Hash]] This method returns two hashes in an array, where the first
|
|
41
|
+
# is a list of normal file-moves ("foo" renamed to "bar" returns {"foo" => "bar"})
|
|
42
|
+
# and the second is a list of divergent file-moves (see @example)
|
|
43
|
+
#
|
|
44
|
+
def self.find_copies(repo, changeset_local, changeset_remote, changeset_ancestor, check_dirs=false)
|
|
45
|
+
# are we udpating from an empty directory? quite easy.
|
|
46
|
+
if changeset_local.nil? || changeset_remote.nil? ||
|
|
47
|
+
changeset_remote == changeset_local
|
|
48
|
+
return {}, {}
|
|
62
49
|
end
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
50
|
+
# avoid silly behavior for parent -> working directory
|
|
51
|
+
if changeset_remote.node == nil && c1.node == repo.dirstate.parents.first
|
|
52
|
+
return repo.dirstate.copies, {}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
limit = find_limit(repo, changeset_local.revision, changeset_remote.revision)
|
|
56
|
+
man_local = changeset_local.manifest_entry
|
|
57
|
+
man_remote = changeset_remote.manifest_entry
|
|
58
|
+
man_ancestor = changeset_ancestor.manifest_entry
|
|
59
|
+
|
|
60
|
+
# gets the versioned_file for a given file and node ID
|
|
61
|
+
easy_file_lookup = proc do |file, node|
|
|
62
|
+
if node.size == 20
|
|
63
|
+
return repo.versioned_file(file, :file_id => node)
|
|
64
|
+
end
|
|
65
|
+
cs = (changeset_local.revision == nil) ? changeset_local : changeset_remote
|
|
66
|
+
return cs.get_file(file)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
ctx = easy_file_lookup
|
|
70
|
+
copy = {}
|
|
71
|
+
full_copy = {}
|
|
72
|
+
diverge = {}
|
|
73
|
+
|
|
74
|
+
# check for copies from manifest1 to manifest2
|
|
75
|
+
check_copies = proc do |file, man1, man2|
|
|
76
|
+
vf1 = easy_file_lookup[file, man1[file]]
|
|
77
|
+
find_old_names(vf1, limit) do |old_name|
|
|
78
|
+
full_copy[file] = old_name # remember for dir rename detection
|
|
79
|
+
if man2[old_name] # original file in other manifest?
|
|
80
|
+
# if the original file is unchanged on the other branch,
|
|
81
|
+
# no merge needed
|
|
82
|
+
if man2[old_name] != man_ancestor[old_name]
|
|
83
|
+
vf2 = easy_file_lookup[old_file, man2[old_file]]
|
|
84
|
+
vfa = vf1.ancestor(vf2)
|
|
85
|
+
# related and name changed on only one side?
|
|
86
|
+
if vfa && (vfa.path == file || vfa.path == vf2.path) && (vf1 == vfa || vf2 == vfa)
|
|
87
|
+
copy[file] = old_file
|
|
88
|
+
end
|
|
86
89
|
end
|
|
90
|
+
elsif man_ancestor[old_file]
|
|
91
|
+
(diverge[old_file] ||= []) << file
|
|
87
92
|
end
|
|
88
|
-
elsif man_ancestor[old_file]
|
|
89
|
-
(diverge[old_file] ||= []) << file
|
|
90
93
|
end
|
|
91
94
|
end
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
95
|
+
|
|
96
|
+
UI.debug(" searching for copies back to rev #{limit}")
|
|
97
|
+
|
|
98
|
+
unmatched_1 = double_intersection(man_local, man_remote, man_ancestor)
|
|
99
|
+
unmatched_2 = double_intersection(man_remote, man_local, man_ancestor)
|
|
100
|
+
|
|
101
|
+
UI.debug(" unmatched files in local:\n #{unmatched_1.join("\n")}") if unmatched_1.any?
|
|
102
|
+
UI.debug(" unmatched files in other:\n #{unmatched_2.join("\n")}") if unmatched_2.any?
|
|
103
|
+
|
|
104
|
+
unmatched_1.each {|file| check_copies[file, man_local, man_remote] }
|
|
105
|
+
unmatched_2.each {|file| check_copies[file, man_remote, man_local] }
|
|
106
|
+
|
|
107
|
+
diverge_2 = {}
|
|
108
|
+
diverge.each do |old_file, file_list|
|
|
109
|
+
if file_list.size == 1
|
|
110
|
+
diverge.delete old_file
|
|
111
|
+
else
|
|
112
|
+
file_list.each {|file| diverge_2[file] = true}
|
|
113
|
+
end
|
|
111
114
|
end
|
|
115
|
+
|
|
116
|
+
if !(full_copy.any?) || !check_dirs
|
|
117
|
+
return copy, diverge
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# CHECK FOR DIRECTORY RENAMES
|
|
121
|
+
# TODO TODO TODO
|
|
112
122
|
end
|
|
113
123
|
|
|
114
|
-
|
|
115
|
-
return copy, diverge
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
# CHECK FOR DIRECTORY RENAMES
|
|
119
|
-
# TODO TODO TODO
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
private
|
|
123
|
-
|
|
124
|
-
##
|
|
125
|
-
# Find the earliest revision in the repository that is an ancestor of EITHER a OR b,
|
|
126
|
-
# but NOT both. In other words, find the oldest ancestor on a branch.
|
|
127
|
-
#
|
|
128
|
-
# @param [Repository] repo the repository we're calculatizing on
|
|
129
|
-
# @param [Integer] a one changeset's revision #
|
|
130
|
-
# @param [Integer] b the other changeset's revision #
|
|
131
|
-
# @return [Integer] the earliest revision index that is an ancestor of only 1 of the
|
|
132
|
-
# two changesets.
|
|
133
|
-
def self.find_limit(repo, a, b)
|
|
134
|
-
# basic idea:
|
|
135
|
-
# - mark a and b with different sides
|
|
136
|
-
# - if a parent's children are all on the same side, the parent is
|
|
137
|
-
# on that side, otherwise it is on no side
|
|
138
|
-
# - walk the graph in topological order with the help of a heap;
|
|
139
|
-
# - add unseen parents to side map
|
|
140
|
-
# - clear side of any parent that has children on different sides
|
|
141
|
-
# - track number of interesting revs that might still be on a side
|
|
142
|
-
# - track the lowest interesting rev seen
|
|
143
|
-
# - quit when interesting revs is zero
|
|
144
|
-
changelog = repo.changelog
|
|
145
|
-
working = changelog.size # this revision index is 1 higher than the real highest
|
|
146
|
-
a ||= working
|
|
147
|
-
b ||= working
|
|
124
|
+
private
|
|
148
125
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
parents
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
126
|
+
##
|
|
127
|
+
# Find the earliest revision in the repository that is an ancestor of EITHER a OR b,
|
|
128
|
+
# but NOT both. In other words, find the oldest ancestor on a branch.
|
|
129
|
+
#
|
|
130
|
+
# @param [Repository] repo the repository we're calculatizing on
|
|
131
|
+
# @param [Integer] a one changeset's revision #
|
|
132
|
+
# @param [Integer] b the other changeset's revision #
|
|
133
|
+
# @return [Integer] the earliest revision index that is an ancestor of only 1 of the
|
|
134
|
+
# two changesets.
|
|
135
|
+
def self.find_limit(repo, a, b)
|
|
136
|
+
# basic idea:
|
|
137
|
+
# - mark a and b with different sides
|
|
138
|
+
# - if a parent's children are all on the same side, the parent is
|
|
139
|
+
# on that side, otherwise it is on no side
|
|
140
|
+
# - walk the graph in topological order with the help of a heap;
|
|
141
|
+
# - add unseen parents to side map
|
|
142
|
+
# - clear side of any parent that has children on different sides
|
|
143
|
+
# - track number of interesting revs that might still be on a side
|
|
144
|
+
# - track the lowest interesting rev seen
|
|
145
|
+
# - quit when interesting revs is zero
|
|
146
|
+
changelog = repo.changelog
|
|
147
|
+
working = changelog.size # this revision index is 1 higher than the real highest
|
|
148
|
+
a ||= working
|
|
149
|
+
b ||= working
|
|
150
|
+
|
|
151
|
+
side = {a => -1, b => 1}
|
|
152
|
+
visit = PriorityQueue.new # because i don't have any other data structure that
|
|
153
|
+
visit[-a] = -a # maintains a sorted order
|
|
154
|
+
visit[-b] = -b
|
|
155
|
+
interesting = visit.size # could be 1 if a == b
|
|
156
|
+
limit = working
|
|
157
|
+
while interesting > 0
|
|
158
|
+
r, junk = -(visit.delete_min) # get the next lowest revision
|
|
159
|
+
if r == working
|
|
160
|
+
# different way of getting parents in this case
|
|
161
|
+
parents = repo.dirstate.parents.map {|p| changelog.rev(p)}
|
|
162
|
+
else
|
|
163
|
+
# normal way of getting parents
|
|
164
|
+
parents = changelog.parent_indices_for_index(r)
|
|
165
|
+
end
|
|
166
|
+
parents.each do |parent|
|
|
167
|
+
if !side[parent]
|
|
168
|
+
# haven't seen the parent before, so let's put it on a side.
|
|
169
|
+
side[parent] = side[r]
|
|
170
|
+
interesting += 1 if side[parent] != 0 # if it's on a side
|
|
171
|
+
visit[-parent] = -parent
|
|
172
|
+
elsif side[parent] && side[parent] != side[r]
|
|
173
|
+
# if we're here, then the parent has been seen by BOTH sides. so it's no good.
|
|
174
|
+
side[parent] = 0
|
|
175
|
+
interesting -= 1
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
# if we're here and side[r] isn't 0, then it's an ancestor to [one and only one]
|
|
179
|
+
# of the 2 root nodes. so keep it.
|
|
180
|
+
if side[r] && side[r] != 0
|
|
181
|
+
limit = r
|
|
173
182
|
interesting -= 1
|
|
174
183
|
end
|
|
175
184
|
end
|
|
176
|
-
|
|
177
|
-
# of the 2 root nodes. so keep it.
|
|
178
|
-
if side[r] && side[r] != 0
|
|
179
|
-
limit = r
|
|
180
|
-
interesting -= 1
|
|
181
|
-
end
|
|
185
|
+
limit
|
|
182
186
|
end
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
187
|
+
|
|
188
|
+
##
|
|
189
|
+
# Go back in time until revision {limit}, grabbing old names that {versioned_file}
|
|
190
|
+
# was moved from.
|
|
191
|
+
#
|
|
192
|
+
# @param [VersionedFile] versioned_file the file for which we are finding old names
|
|
193
|
+
# @param [Integer] limit the minimum revision back in time in which we should
|
|
194
|
+
# search for old names
|
|
195
|
+
# @return [Array<String>] old names for the current file.
|
|
196
|
+
def self.find_old_names(versioned_file, limit)
|
|
197
|
+
# wooooo recursion unrolling!
|
|
198
|
+
old = {}
|
|
199
|
+
seen = {}
|
|
200
|
+
orig = versioned_file.path
|
|
201
|
+
visit = [[versioned_file, 0]]
|
|
202
|
+
while visit.any? do
|
|
203
|
+
file, depth = visit.shift
|
|
204
|
+
str = file.to_s
|
|
205
|
+
next if seen[str]
|
|
206
|
+
|
|
207
|
+
seen[str] = true
|
|
208
|
+
if file.path != orig && !old[file.path]
|
|
209
|
+
old[file.path] = [depth, file.path]
|
|
210
|
+
end
|
|
211
|
+
next if file.revision < limit && file.revision != nil
|
|
212
|
+
visit += file.parents.each {|p| [p, depth - 1]}
|
|
208
213
|
end
|
|
209
|
-
|
|
210
|
-
visit += file.parents.each {|p| [p, depth - 1]}
|
|
214
|
+
old.values.sort.map {|o| o[1]}
|
|
211
215
|
end
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
dirs = {}
|
|
226
|
-
files.each do |file|
|
|
227
|
-
file = picky_dirname file
|
|
228
|
-
until dirs[file]
|
|
229
|
-
dirs[file] = true
|
|
216
|
+
|
|
217
|
+
##
|
|
218
|
+
# Returns all the parent directories of every file in the provided array,
|
|
219
|
+
# recursively, as a map. Each entry maps a directory to {true}. It's really
|
|
220
|
+
# just a set, but I'm too lazy to use a set. Sorry.
|
|
221
|
+
#
|
|
222
|
+
# @param [Array<String>] files a list of files for which we need all the parent
|
|
223
|
+
# directories
|
|
224
|
+
# @return [Hash] a map: each entry maps a directory name to {true}, because it's
|
|
225
|
+
# really just a set, because I'm too lazy to use a set.
|
|
226
|
+
def self.all_parent_dirs(files)
|
|
227
|
+
dirs = {}
|
|
228
|
+
files.each do |file|
|
|
230
229
|
file = picky_dirname file
|
|
230
|
+
until dirs[file]
|
|
231
|
+
dirs[file] = true
|
|
232
|
+
file = picky_dirname file
|
|
233
|
+
end
|
|
231
234
|
end
|
|
235
|
+
dirs
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
##
|
|
239
|
+
# This method will find the path of the containing directory for the file
|
|
240
|
+
# pointed to by {path}. We use this instead of File.dirname because we
|
|
241
|
+
# want to return the empty string instead of "." if there is no path separator
|
|
242
|
+
# in the provided string.
|
|
243
|
+
#
|
|
244
|
+
# @param [String] path the path to the file we want the directory name of
|
|
245
|
+
# @return [String] the path of the containing directory of the provided file
|
|
246
|
+
def self.picky_dirname(path)
|
|
247
|
+
Dir.dirname path
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
##
|
|
251
|
+
# Returns a list of elements in d1 that are not in d2 or d3. We have this method
|
|
252
|
+
# because Mercurial's source has this method.
|
|
253
|
+
#
|
|
254
|
+
# @param [Array] d1 a list of items we wish to filter
|
|
255
|
+
# @param [Array] d2 a list of items we do NOT want in d1
|
|
256
|
+
# @param [Array] d3 a list of items we do NOT want in d1
|
|
257
|
+
# @return [Array] a list of items in d1 that are not present in d2 or d3
|
|
258
|
+
def self.double_intersection(d1, d2, d3)
|
|
259
|
+
d1.reject {|i| d2.include?(i) || d3.include?(i) }
|
|
232
260
|
end
|
|
233
|
-
dirs
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
##
|
|
237
|
-
# This method will find the path of the containing directory for the file
|
|
238
|
-
# pointed to by {path}. We use this instead of File.dirname because we
|
|
239
|
-
# want to return the empty string instead of "." if there is no path separator
|
|
240
|
-
# in the provided string.
|
|
241
|
-
#
|
|
242
|
-
# @param [String] path the path to the file we want the directory name of
|
|
243
|
-
# @return [String] the path of the containing directory of the provided file
|
|
244
|
-
def self.picky_dirname(path)
|
|
245
|
-
Dir.dirname path
|
|
246
|
-
end
|
|
247
|
-
|
|
248
|
-
##
|
|
249
|
-
# Returns a list of elements in d1 that are not in d2 or d3. We have this method
|
|
250
|
-
# because Mercurial's source has this method.
|
|
251
|
-
#
|
|
252
|
-
# @param [Array] d1 a list of items we wish to filter
|
|
253
|
-
# @param [Array] d2 a list of items we do NOT want in d1
|
|
254
|
-
# @param [Array] d3 a list of items we do NOT want in d1
|
|
255
|
-
# @return [Array] a list of items in d1 that are not present in d2 or d3
|
|
256
|
-
def self.double_intersection(d1, d2, d3)
|
|
257
|
-
d1.reject {|i| d2.include?(i) || d3.include?(i) }
|
|
258
261
|
end
|
|
259
262
|
end
|
|
260
263
|
end
|