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
|
@@ -0,0 +1,768 @@
|
|
|
1
|
+
module Amp
|
|
2
|
+
module Mercurial
|
|
3
|
+
|
|
4
|
+
##
|
|
5
|
+
# A Changeset is a simple way of accessing the repository within a certain
|
|
6
|
+
# revision. For example, if the user specifies revision # 36, or revision
|
|
7
|
+
# 3adf21, then we can look those up, and work within the repository at the
|
|
8
|
+
# moment of that revision.
|
|
9
|
+
class Changeset < Amp::Repositories::AbstractChangeset
|
|
10
|
+
include Mercurial::RevlogSupport::Node
|
|
11
|
+
|
|
12
|
+
attr_reader :repo
|
|
13
|
+
alias_method :repository, :repo
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# Initializes a new changeset. We need a repository to work with, and also
|
|
17
|
+
# a change_id. this change_id could be a revision index or a node_id for
|
|
18
|
+
# the revision.
|
|
19
|
+
#
|
|
20
|
+
# @param [Repository] repo a repository to work with.
|
|
21
|
+
# @param [Integer, String] change_id an ID or index to lookup to find this
|
|
22
|
+
# changeset.
|
|
23
|
+
#
|
|
24
|
+
def initialize(repo, change_id='')
|
|
25
|
+
change_id = '.' if change_id == ''
|
|
26
|
+
@repo = repo
|
|
27
|
+
if change_id.kind_of? Integer
|
|
28
|
+
@revision = change_id
|
|
29
|
+
@node_id = @repo.changelog.node_id_for_index change_id
|
|
30
|
+
else
|
|
31
|
+
@node_id = @repo.lookup change_id
|
|
32
|
+
@revision = @repo.changelog.rev @node_id
|
|
33
|
+
end
|
|
34
|
+
@parents = nil
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
##
|
|
38
|
+
# Converts the revision to a number
|
|
39
|
+
def to_i; @revision; end
|
|
40
|
+
|
|
41
|
+
##
|
|
42
|
+
# Converts the revision to an easy-to-digest string
|
|
43
|
+
def to_s(opts = {})
|
|
44
|
+
if opts[:template]
|
|
45
|
+
to_templated_s(opts)
|
|
46
|
+
else
|
|
47
|
+
@node_id[0..5].hexlify
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
##
|
|
52
|
+
#
|
|
53
|
+
def to_templated_s(opts={})
|
|
54
|
+
|
|
55
|
+
change_node = node
|
|
56
|
+
revision = self.revision
|
|
57
|
+
log = @repo.changelog
|
|
58
|
+
changes = log.read change_node
|
|
59
|
+
username = changes[1]
|
|
60
|
+
date = Time.at changes[2].first
|
|
61
|
+
files = changes[3]
|
|
62
|
+
description = changes[4]
|
|
63
|
+
extra = changes[5]
|
|
64
|
+
branch = extra["branch"]
|
|
65
|
+
cs_tags = tags
|
|
66
|
+
type = opts[:template_type] || 'log'
|
|
67
|
+
|
|
68
|
+
added = opts[:added] || []
|
|
69
|
+
removed = opts[:removed] || []
|
|
70
|
+
updated = opts[:updated] || []
|
|
71
|
+
config = opts
|
|
72
|
+
|
|
73
|
+
parents = useful_parents log, revision
|
|
74
|
+
parents.map! {|p| [p, log.node(p)[0..5].hexlify] }
|
|
75
|
+
|
|
76
|
+
p1 = useful_parents(log, revision)[0]
|
|
77
|
+
p2 = useful_parents(log, revision)[1]
|
|
78
|
+
|
|
79
|
+
return "" if opts[:no_output]
|
|
80
|
+
|
|
81
|
+
config = opts
|
|
82
|
+
|
|
83
|
+
template = opts[:template]
|
|
84
|
+
template = "default-#{type}" if template.nil? || template.to_s == "default"
|
|
85
|
+
|
|
86
|
+
template = Support::Template['mercurial', template]
|
|
87
|
+
template.render({}, binding)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def useful_parents(log, revision)
|
|
91
|
+
parents = log.parent_indices_for_index revision
|
|
92
|
+
if parents[1] == -1
|
|
93
|
+
if parents[0] >= revision - 1
|
|
94
|
+
parents = []
|
|
95
|
+
else
|
|
96
|
+
parents = [parents[0]]
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
parents
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
##
|
|
103
|
+
# Commits the given changeset to the repository.
|
|
104
|
+
#
|
|
105
|
+
# commit_changeset:
|
|
106
|
+
# foreach file in commit:
|
|
107
|
+
# commit_file file
|
|
108
|
+
# end
|
|
109
|
+
# add_manifest_entry
|
|
110
|
+
# add_changelog_entry
|
|
111
|
+
# Is this changeset a working changeset?
|
|
112
|
+
#
|
|
113
|
+
# @param changeset the changeset to commit. Could be working dir, for
|
|
114
|
+
# example.
|
|
115
|
+
# @param opts the options for committing the changeset.
|
|
116
|
+
# @option [Boolean] opts :force (false) force the commit, even though
|
|
117
|
+
# nothing has changed.
|
|
118
|
+
# @option [Boolean] opts :force_editor (false) force the user to open
|
|
119
|
+
# their editor, even though they provided a message already
|
|
120
|
+
# @option [Boolean] opts :empty_ok (false) is it ok if they have no
|
|
121
|
+
# description of the commit?
|
|
122
|
+
# @option [Boolean] opts :use_dirstate (true) use the DirState for this
|
|
123
|
+
# commit? Used if you're committing the working directory (typical)
|
|
124
|
+
# @option [Boolean] opts :update_dirstate (true) should we update the
|
|
125
|
+
# DirState after the commit? Used if you're committing the working
|
|
126
|
+
# directory.
|
|
127
|
+
# @return [String] the digest referring to this entry in the revlog
|
|
128
|
+
def commit(opts = {:use_dirstate => true, :update_dirstate => true})
|
|
129
|
+
valid = false # don't update the DirState if this is set!
|
|
130
|
+
|
|
131
|
+
commit = ((modified || []) + (added || [])).sort
|
|
132
|
+
remove = removed
|
|
133
|
+
xtra = extra.dup
|
|
134
|
+
branchname = xtra["branch"]
|
|
135
|
+
text = description
|
|
136
|
+
|
|
137
|
+
p1, p2 = parents.map {|p| p.node }
|
|
138
|
+
c1 = repo.changelog.read(p1) # 1 parent's changeset as an array
|
|
139
|
+
c2 = repo.changelog.read(p2) # 2nd parent's changeset as an array
|
|
140
|
+
m1 = repo.manifest.read(c1[0]).dup # 1st parent's manifest
|
|
141
|
+
m2 = repo.manifest.read(c2[0]) # 2nd parent's manifest
|
|
142
|
+
|
|
143
|
+
if opts[:use_dirstate]
|
|
144
|
+
oldname = c1[5]["branch"]
|
|
145
|
+
tests = [ commit.empty?, remove.empty?, ! opts[:force],
|
|
146
|
+
p2 == NULL_ID, branchname == oldname ]
|
|
147
|
+
|
|
148
|
+
if tests.all?
|
|
149
|
+
UI::status "nothing changed"
|
|
150
|
+
return nil
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
xp1 = p1.hexlify
|
|
155
|
+
xp2 = p2 == NULL_ID ? "" : p2.hexlify
|
|
156
|
+
|
|
157
|
+
Hook.run_hook :pre_commit
|
|
158
|
+
journal = Amp::Mercurial::Journal.new(:opener => repo.store_opener)
|
|
159
|
+
|
|
160
|
+
fresh = {} # new = reserved haha i don't know why someone wrote "haha"
|
|
161
|
+
changed = []
|
|
162
|
+
link_rev = repo.size
|
|
163
|
+
|
|
164
|
+
(commit + (remove || [])).each {|file| UI::status file }
|
|
165
|
+
|
|
166
|
+
# foreach file in commit:
|
|
167
|
+
# commit_file file
|
|
168
|
+
# end
|
|
169
|
+
commit.each do |file|
|
|
170
|
+
versioned_file = self[file]
|
|
171
|
+
fresh[file] = versioned_file.commit :manifests => [m1, m2],
|
|
172
|
+
:link_revision => link_rev,
|
|
173
|
+
:journal => journal ,
|
|
174
|
+
:changed => changed
|
|
175
|
+
|
|
176
|
+
new_flags = versioned_file.flags
|
|
177
|
+
|
|
178
|
+
# TODO
|
|
179
|
+
# Clean this shit up
|
|
180
|
+
if [ changed.empty? || changed.last != file,
|
|
181
|
+
m2[file] != fresh[file]
|
|
182
|
+
].all?
|
|
183
|
+
changed << file if m1.flags[file] != new_flags
|
|
184
|
+
end
|
|
185
|
+
m1.flags[file] = new_flags
|
|
186
|
+
|
|
187
|
+
repo.staging_area.normal file if opts[:use_dirstate]
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# add_manifest_entry
|
|
191
|
+
man_entry, updated, added = *add_manifest_entry(:manifests => [m1, m2],
|
|
192
|
+
:changesets => [c1, c2],
|
|
193
|
+
:journal => journal ,
|
|
194
|
+
:link_rev => link_rev,
|
|
195
|
+
:fresh => fresh ,
|
|
196
|
+
:remove => remove ,
|
|
197
|
+
:changed => changed )
|
|
198
|
+
|
|
199
|
+
# get_commit_text
|
|
200
|
+
text = get_commit_text text, :added => added, :updated => updated,
|
|
201
|
+
:removed => removed, :user => user ,
|
|
202
|
+
:empty_ok => opts[:empty_ok] ,
|
|
203
|
+
:use_dirstate => opts[:use_dirstate]
|
|
204
|
+
|
|
205
|
+
# atomically write to the changelog
|
|
206
|
+
# add_changelog_entry
|
|
207
|
+
# for the unenlightened, rents = 'rents = parents
|
|
208
|
+
new_rents = add_changelog_entry :manifest_entry => man_entry,
|
|
209
|
+
:files => (changed + removed),
|
|
210
|
+
:text => text,
|
|
211
|
+
:journal => journal,
|
|
212
|
+
:parents => [p1, p2],
|
|
213
|
+
:user => user,
|
|
214
|
+
:date => date,
|
|
215
|
+
:extra => xtra
|
|
216
|
+
|
|
217
|
+
# Write the dirstate if it needs to be updated
|
|
218
|
+
# basically just bring it up to speed
|
|
219
|
+
if opts[:use_dirstate] || opts[:update_dirstate]
|
|
220
|
+
repo.dirstate.parents = new_rents
|
|
221
|
+
removed.each {|f| repo.dirstate.forget(f) } if opts[:use_dirstate]
|
|
222
|
+
repo.dirstate.write
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# The journal and dirstates are awesome. Leave them be.
|
|
226
|
+
valid = true
|
|
227
|
+
journal.close
|
|
228
|
+
|
|
229
|
+
# if an error and we've gotten this far, then the journal is complete
|
|
230
|
+
# and it deserves to stay (if an error is thrown and journal isn't nil,
|
|
231
|
+
# the rescue will destroy it)
|
|
232
|
+
journal = nil
|
|
233
|
+
|
|
234
|
+
# Run any hooks
|
|
235
|
+
Hook.run_hook :post_commit, :added => added, :modified => updated, :removed => removed,
|
|
236
|
+
:user => user, :date => date, :text => text,
|
|
237
|
+
:revision => repo.changelog.index_size
|
|
238
|
+
return new_rents
|
|
239
|
+
rescue StandardError => e
|
|
240
|
+
if !valid
|
|
241
|
+
repo.dirstate.invalidate!
|
|
242
|
+
end
|
|
243
|
+
if e.kind_of?(AbortError)
|
|
244
|
+
UI::warn "Abort: #{e}"
|
|
245
|
+
else
|
|
246
|
+
UI::warn "Got exception while committing. #{e}"
|
|
247
|
+
UI::warn e.backtrace.join("\n")
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# the journal is a vestigial and incomplete file.
|
|
251
|
+
# destroyzzzzzzzzzzz
|
|
252
|
+
journal.delete if journal
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
##
|
|
256
|
+
# Add an entry to the changelog (the final receipt of the commit).
|
|
257
|
+
#
|
|
258
|
+
# @param [Hash] opts
|
|
259
|
+
# @return [String] the changelog id as to where the revision is in
|
|
260
|
+
# the changelog
|
|
261
|
+
def add_changelog_entry(opts={})
|
|
262
|
+
repo.changelog.delay_update
|
|
263
|
+
new_parents = repo.changelog.add opts[:manifest_entry],
|
|
264
|
+
opts[:files],
|
|
265
|
+
opts[:text],
|
|
266
|
+
opts[:journal],
|
|
267
|
+
opts[:parents][0],
|
|
268
|
+
opts[:parents][1],
|
|
269
|
+
opts[:user],
|
|
270
|
+
opts[:date],
|
|
271
|
+
opts[:extra]
|
|
272
|
+
|
|
273
|
+
repo.changelog.write_pending
|
|
274
|
+
repo.changelog.finalize opts[:journal]
|
|
275
|
+
new_parents
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
##
|
|
279
|
+
# Get the commit text. Ask for it if none is given.
|
|
280
|
+
#
|
|
281
|
+
# @param [String, NilClass] text (optional) the commit message
|
|
282
|
+
# @param [Hash] opts
|
|
283
|
+
def get_commit_text(text=nil, opts={})
|
|
284
|
+
user = opts.delete :user
|
|
285
|
+
|
|
286
|
+
unless opts[:empty_ok] || (text && !text.empty?)
|
|
287
|
+
edit_text = to_templated_s :added => added, :updated => modified,
|
|
288
|
+
:removed => removed, :template_type => :commit
|
|
289
|
+
text = UI::edit edit_text, user
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
lines = text.rstrip.split("\n").map {|r| r.rstrip }.reject {|l| l.empty? }
|
|
293
|
+
raise abort("empty commit message") if lines.empty? && opts[:use_dirstate]
|
|
294
|
+
lines.join("\n")
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def add_manifest_entry(opts={})
|
|
298
|
+
# changed, m1, m2, c1, c2, fresh, remove, journal, link_rev
|
|
299
|
+
updated, added = [], []
|
|
300
|
+
|
|
301
|
+
fresh = opts[:fresh]
|
|
302
|
+
remove = opts[:remove]
|
|
303
|
+
changed = opts[:changed]
|
|
304
|
+
|
|
305
|
+
changesets = opts[:changesets]
|
|
306
|
+
manifests = opts[:manifests]
|
|
307
|
+
|
|
308
|
+
changed.sort.each do |file|
|
|
309
|
+
if manifests[0][file] || manifests[1][file]
|
|
310
|
+
updated << file
|
|
311
|
+
else
|
|
312
|
+
added << file
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
manifests[0].merge! fresh
|
|
317
|
+
|
|
318
|
+
remove.sort!
|
|
319
|
+
remove.reject! {|f| not manifests[0][f] }
|
|
320
|
+
remove.each {|f| manifests[0].delete f }
|
|
321
|
+
|
|
322
|
+
UI::debug "before adding manifest entry"
|
|
323
|
+
|
|
324
|
+
# sorry for making this destructive
|
|
325
|
+
# but it's clean and memory efficient
|
|
326
|
+
# GHC's GC goes like 3 times per second, so STFU
|
|
327
|
+
# I don't have that kind of luxury
|
|
328
|
+
fresh.replace fresh.inject([]) {|a, (k, v)| v ? a << k : a }
|
|
329
|
+
man_entry = repo.manifest.add manifests[0], opts[:journal],
|
|
330
|
+
opts[:link_rev], changesets[0][0], changesets[1][0], [fresh, remove]
|
|
331
|
+
[man_entry, updated, added]
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
##
|
|
335
|
+
# @return [Boolean] is the changeset representing the working directory?
|
|
336
|
+
def working?
|
|
337
|
+
false
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
##
|
|
341
|
+
# Gives an easier way to digest this changeset while reminding us it's a
|
|
342
|
+
# changeset
|
|
343
|
+
def inspect
|
|
344
|
+
"#<Changeset #{to_s}>"
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
##
|
|
348
|
+
# Hash function for putting these bad boys in hashes
|
|
349
|
+
#
|
|
350
|
+
# @return [Integer] a hash value.
|
|
351
|
+
def hash
|
|
352
|
+
return @revision.hash if @revision
|
|
353
|
+
return object_id
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
##
|
|
357
|
+
# Compares 2 changesets so we can sort them and whatnot
|
|
358
|
+
#
|
|
359
|
+
# @param [Changeset] other a changeset we will compare against
|
|
360
|
+
# @return [Integer] -1, 0, or 1. Typical comparison.
|
|
361
|
+
def <=>(other)
|
|
362
|
+
return 0 if @revision.nil? || other.revision.nil?
|
|
363
|
+
@revision <=> other.revision
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
##
|
|
367
|
+
# Are we a null revision?
|
|
368
|
+
# @return [Boolean] null?
|
|
369
|
+
def nil?
|
|
370
|
+
@revision != NULL_REV
|
|
371
|
+
end
|
|
372
|
+
alias_method :null?, :nil?
|
|
373
|
+
|
|
374
|
+
# Gets the raw changeset data for this revision. This includes
|
|
375
|
+
# the user who committed it, the description of the commit, and so on.
|
|
376
|
+
# Returns this: [manifest, user, [time, timezone], files, desc, extra]
|
|
377
|
+
def raw_changeset
|
|
378
|
+
@repo.changelog.read(@node_id)
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
##
|
|
382
|
+
# Returns the {ManifestEntry} for this revision. This will give
|
|
383
|
+
# us info on any file we want, including flags such as executable
|
|
384
|
+
# or if it's a link. Sizes and so on are also included.
|
|
385
|
+
#
|
|
386
|
+
# @return [ManifestEntry] the manifest at this point in time
|
|
387
|
+
def manifest_entry
|
|
388
|
+
@manifest_entry ||= @repo.manifest.read(raw_changeset[0])
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
##
|
|
392
|
+
# Provides access to all the tracked files in the changeset. Needed
|
|
393
|
+
# for API compatibility.
|
|
394
|
+
#
|
|
395
|
+
# @return [Array<String>] all the files tracked in this changeset.
|
|
396
|
+
def all_files
|
|
397
|
+
return manifest_entry.files
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
##
|
|
401
|
+
# Returns the change in the manifest at this revision. I don't entirely
|
|
402
|
+
# know what this is yet.
|
|
403
|
+
def manifest_delta
|
|
404
|
+
@manifest_entry_delta ||= @repo.manifest.read_delta(raw_changeset[0])
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
##
|
|
408
|
+
# Returns the parents of this changeset as {Changeset}s.
|
|
409
|
+
#
|
|
410
|
+
# @return [[Changeset]] the parents of this changeset.
|
|
411
|
+
def parents
|
|
412
|
+
return @parents if @parents
|
|
413
|
+
|
|
414
|
+
p = @repo.changelog.parent_indices_for_index @revision
|
|
415
|
+
p = [p[0]] if p[1] == NULL_REV
|
|
416
|
+
|
|
417
|
+
@parents = p.map {|x| Changeset.new(@repo, x) }
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
##
|
|
421
|
+
# Returns the children of this changeset as {Changeset}s.
|
|
422
|
+
#
|
|
423
|
+
# @return [Array<Changeset>] the children of this changeset.
|
|
424
|
+
def children
|
|
425
|
+
@repo.changelog.children(node_id).map do |node|
|
|
426
|
+
Changeset.new(@repo, node)
|
|
427
|
+
end
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
##
|
|
431
|
+
# Iterates over each entry in the manifest entry.
|
|
432
|
+
#
|
|
433
|
+
# @return [Changeset] self, because that's how #each works
|
|
434
|
+
def each(&block)
|
|
435
|
+
manifest_entry.sort.each(&block)
|
|
436
|
+
self
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
##
|
|
440
|
+
# Checks whether this changeset included a given file or not.
|
|
441
|
+
#
|
|
442
|
+
# @param [String] file the file to lookup
|
|
443
|
+
# @return [Boolean] whether the file is in this changeset's manifest
|
|
444
|
+
def include?(file)
|
|
445
|
+
manifest_entry[file] != nil
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
##
|
|
449
|
+
# Gets the file with the given name, as a {VersionedFile}.
|
|
450
|
+
# @param file the path to the file to retrieve
|
|
451
|
+
# @return [VersionedFile] the file at this revision
|
|
452
|
+
#
|
|
453
|
+
def [](file)
|
|
454
|
+
get_file(file)
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
##
|
|
458
|
+
# Returns the file's info, namely it's node_id and flags it may
|
|
459
|
+
# have at this point in time, such as "x" for executable.
|
|
460
|
+
#
|
|
461
|
+
# @param path the path to the file
|
|
462
|
+
# @return [[String, String]] the [node_id, flags] pair for this file
|
|
463
|
+
def file_info(path)
|
|
464
|
+
if manifest_entry # have we loaded our manifest yet? if so, use that sucker
|
|
465
|
+
result = [manifest_entry[path], manifest_entry.flags[path]]
|
|
466
|
+
if result[0].nil?
|
|
467
|
+
return [NULL_ID, '']
|
|
468
|
+
else
|
|
469
|
+
return result
|
|
470
|
+
end
|
|
471
|
+
end
|
|
472
|
+
if manifest_delta || files[path] # check if it's in the delta... i dunno
|
|
473
|
+
if manifest_delta[path]
|
|
474
|
+
return [manifest_delta[path], manifest_delta.flags[path]]
|
|
475
|
+
end
|
|
476
|
+
end
|
|
477
|
+
# Give us, just look it up the long way in the manifest. not fun. slow.
|
|
478
|
+
node, flag = @repo.manifest.find(raw_changeset[0], path)
|
|
479
|
+
if node.nil?
|
|
480
|
+
return [NULL_ID, '']
|
|
481
|
+
end
|
|
482
|
+
return [node, flag]
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
##
|
|
486
|
+
# Gets the flags for the file at the given path at this revision.
|
|
487
|
+
# @param path the path to the file in question
|
|
488
|
+
# @return [String] the flags for the file, such as "x", "l", or "".
|
|
489
|
+
#
|
|
490
|
+
def flags(path)
|
|
491
|
+
info = file_info(path)[1]
|
|
492
|
+
return "" if info.nil?
|
|
493
|
+
info
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
##
|
|
497
|
+
# Gets the node_id in the manifest_entry for the file at this path, for this
|
|
498
|
+
# specific revision.
|
|
499
|
+
#
|
|
500
|
+
# @param path the path to the file
|
|
501
|
+
# @return [String] the node's ID in the manifest_entry, which we'll use every
|
|
502
|
+
# where we need a node_id.
|
|
503
|
+
def file_node(path)
|
|
504
|
+
file_info(path).first[0..19]
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
##
|
|
508
|
+
# Creates a versioned file for the file at the given path, for the frame
|
|
509
|
+
# of reference of this revision.
|
|
510
|
+
# @param path the path to the file
|
|
511
|
+
# @param [String] file_id the node_id, to save us some computation
|
|
512
|
+
# @param [FileLog] file_log the file_log to use, again to save us computation
|
|
513
|
+
# @return [VersionedFile] the file at this revision.
|
|
514
|
+
#
|
|
515
|
+
def get_file(path, file_id = nil, file_log = nil)
|
|
516
|
+
file_id = file_node(path) if file_id.nil?
|
|
517
|
+
VersionedFile.new(@repo, path, :file_id => file_id, :changeset => self,
|
|
518
|
+
:file_log => file_log)
|
|
519
|
+
end
|
|
520
|
+
#accessors
|
|
521
|
+
# revision index
|
|
522
|
+
def revision; @revision; end
|
|
523
|
+
alias_method :rev, :revision
|
|
524
|
+
# node_id
|
|
525
|
+
def node_id; @node_id; end
|
|
526
|
+
# @see node_id
|
|
527
|
+
alias_method :node, :node_id
|
|
528
|
+
# our node_id in sexy hexy
|
|
529
|
+
def hex; @node_id.hexlify; end
|
|
530
|
+
# the user who committed me!
|
|
531
|
+
def user; raw_changeset[1]; end
|
|
532
|
+
# the date i was committed!
|
|
533
|
+
def date; raw_changeset[2]; end
|
|
534
|
+
def easy_date; Time.at(raw_changeset[2].first); end
|
|
535
|
+
# the files affected in this commit!
|
|
536
|
+
def altered_files; raw_changeset[3]; end
|
|
537
|
+
# pre-API compatibility
|
|
538
|
+
alias_method :files, :altered_files
|
|
539
|
+
|
|
540
|
+
# the message with this commit
|
|
541
|
+
def description; raw_changeset[4]; end
|
|
542
|
+
# What branch i was committed onto
|
|
543
|
+
def branch
|
|
544
|
+
extra["branch"]
|
|
545
|
+
end
|
|
546
|
+
# Any extra stuff I've got in me
|
|
547
|
+
def extra; raw_changeset[5]; end
|
|
548
|
+
# tags
|
|
549
|
+
def tags; @repo.tags_for_node node; end
|
|
550
|
+
|
|
551
|
+
def ancestor(other_changeset)
|
|
552
|
+
node = @repo.changelog.ancestor(self.node, other_changeset.node)
|
|
553
|
+
return Changeset.new(@repo, node)
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
def ancestors
|
|
557
|
+
results = []
|
|
558
|
+
@repo.changelog.ancestors(revision)
|
|
559
|
+
end
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
##
|
|
563
|
+
# This is a special changeset that specifically works within the
|
|
564
|
+
# working directory. We sort of have to combine the old revision
|
|
565
|
+
# logs with the fact that files might be changed, and not in the
|
|
566
|
+
# revision logs! oh, mercy!
|
|
567
|
+
class WorkingDirectoryChangeset < Changeset
|
|
568
|
+
|
|
569
|
+
def initialize(repo, opts={:text => ""})
|
|
570
|
+
@repo = repo
|
|
571
|
+
@revision = nil
|
|
572
|
+
@parents = nil
|
|
573
|
+
@node_id = nil
|
|
574
|
+
@text = opts[:text]
|
|
575
|
+
require 'time' if opts[:date].kind_of?(String)
|
|
576
|
+
@date = opts[:date].kind_of?(String) ? Time.parse(opts[:date]) : opts[:date]
|
|
577
|
+
@user = opts[:user] if opts[:user]
|
|
578
|
+
@parents = opts[:parents].map {|p| Changeset.new(@repo, p)} if opts[:parents]
|
|
579
|
+
@status = opts[:changes] if opts[:changes]
|
|
580
|
+
@manifest = nil
|
|
581
|
+
@extra = opts[:extra] ? opts[:extra].dup : {}
|
|
582
|
+
unless @extra["branch"]
|
|
583
|
+
branch = @repo.dirstate.branch
|
|
584
|
+
# encoding - to UTF-8
|
|
585
|
+
@extra["branch"] = branch
|
|
586
|
+
end
|
|
587
|
+
@extra["branch"] = "default" if @extra["branch"] && @extra["branch"].empty?
|
|
588
|
+
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
##
|
|
592
|
+
# Is this changeset a working changeset?
|
|
593
|
+
#
|
|
594
|
+
# @return [Boolean] is the changeset representing the working directory?
|
|
595
|
+
def working?
|
|
596
|
+
true
|
|
597
|
+
end
|
|
598
|
+
|
|
599
|
+
##
|
|
600
|
+
# Converts to a string.
|
|
601
|
+
# I'm my first parent, plus a little extra.
|
|
602
|
+
# "I am my own grandpa"
|
|
603
|
+
#
|
|
604
|
+
# @return [String]
|
|
605
|
+
def to_s
|
|
606
|
+
parents.first.to_s + "+"
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
|
|
610
|
+
##
|
|
611
|
+
# Do I include a given file? (not sure this is ever used yet)
|
|
612
|
+
def include?(key)
|
|
613
|
+
status = @repo.staging_area.file_status(key)
|
|
614
|
+
![:unknown, :removed].include?(status)
|
|
615
|
+
end
|
|
616
|
+
|
|
617
|
+
def all_files
|
|
618
|
+
repo.staging_area.all_files
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
##
|
|
622
|
+
# Am I nil? never!
|
|
623
|
+
def nil?; false; end
|
|
624
|
+
|
|
625
|
+
##
|
|
626
|
+
# What is the status of the working directory? This little
|
|
627
|
+
# method hides quite a bit of work!
|
|
628
|
+
def status
|
|
629
|
+
@status ||= @repo.status(:unknown => true)
|
|
630
|
+
end
|
|
631
|
+
|
|
632
|
+
##
|
|
633
|
+
# Who is the user working on me?
|
|
634
|
+
def user
|
|
635
|
+
@user ||= @repo.config.username
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
##
|
|
639
|
+
# Well, I guess the working directory's date is... right now!
|
|
640
|
+
def date
|
|
641
|
+
@date ||= Time.new
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
##
|
|
645
|
+
# Who is the working directory's father? Is it Chef? Mr. Garrison?
|
|
646
|
+
# the 1989 denver broncos?
|
|
647
|
+
#
|
|
648
|
+
# hahaha mike that's hilarious
|
|
649
|
+
def parents
|
|
650
|
+
@parents ||= begin
|
|
651
|
+
p = @repo.dirstate.parents
|
|
652
|
+
p = [p[0]] if p[1] == NULL_ID
|
|
653
|
+
p.map {|x| Changeset.new(@repo, x) }
|
|
654
|
+
end
|
|
655
|
+
end
|
|
656
|
+
|
|
657
|
+
##
|
|
658
|
+
# OK, so we've got the last revision's manifest entry, that part's simple and makes sense.
|
|
659
|
+
# except now, we need to get the status of the working directory, and
|
|
660
|
+
# add in all the other files, because they're in the "manifest entry" by being
|
|
661
|
+
# in existence. Oh, and we need to remove any files from the parent's
|
|
662
|
+
# manifest entry that don't exist anymore. Make sense?
|
|
663
|
+
def manifest_entry
|
|
664
|
+
return @manifest_entry if @manifest_entry
|
|
665
|
+
|
|
666
|
+
# Start off with the last revision's manifest_entry, that's safe.
|
|
667
|
+
man = parents()[0].manifest_entry.dup
|
|
668
|
+
# Any copied files since the last revision?
|
|
669
|
+
copied = @repo.dirstate.copy_map
|
|
670
|
+
# Any modified, added, etc files since the last revision?
|
|
671
|
+
modified, added, removed = status[:modified], status[:added], status[:removed]
|
|
672
|
+
deleted, unknown = status[:deleted], status[:unknown]
|
|
673
|
+
# Merge these discoveries in!
|
|
674
|
+
{:a => added, :m => modified, :u => unknown}.each do |k, list|
|
|
675
|
+
list.each do |file|
|
|
676
|
+
copy_name = (copied[file] || file)
|
|
677
|
+
man[file] = (man.flags[copy_name] || NULL_ID) + k.to_s
|
|
678
|
+
man.flags[file] = @repo.dirstate.flags(file)
|
|
679
|
+
end
|
|
680
|
+
end
|
|
681
|
+
|
|
682
|
+
# Delete files from the real manifest entry that don't exist.
|
|
683
|
+
(deleted + removed).each do |file|
|
|
684
|
+
man.delete file if man[file]
|
|
685
|
+
end
|
|
686
|
+
|
|
687
|
+
man
|
|
688
|
+
end
|
|
689
|
+
|
|
690
|
+
##
|
|
691
|
+
# Returns a {VersionedWorkingFile} to represent the file at the given
|
|
692
|
+
# point in time. It represents a file in the working directory, which
|
|
693
|
+
# obvious don't read from the history, but from the actual file in
|
|
694
|
+
# question.
|
|
695
|
+
#
|
|
696
|
+
# @param path the path to the file
|
|
697
|
+
# @param file_log the log for the file to save some computation
|
|
698
|
+
# @return [Amp::VersionedWorkingFile] the file object we can work with
|
|
699
|
+
def get_file(path, file_log=nil)
|
|
700
|
+
VersionedWorkingFile.new(@repo, path, :working_changeset => self,
|
|
701
|
+
:file_log => file_log)
|
|
702
|
+
end
|
|
703
|
+
|
|
704
|
+
##
|
|
705
|
+
# Gets the flags for the file at current state in time
|
|
706
|
+
#
|
|
707
|
+
# @param [String] path the path to the file
|
|
708
|
+
# @return [String] the flags, such as "x", "l", or ""
|
|
709
|
+
def flags(path)
|
|
710
|
+
if @manifest_entry ||= nil
|
|
711
|
+
return manifest_entry.flags[path] || ""
|
|
712
|
+
end
|
|
713
|
+
pnode = parents[0].raw_changeset[0]
|
|
714
|
+
|
|
715
|
+
orig = @repo.dirstate.copy_map[path] || path
|
|
716
|
+
node, flag = @repo.manifest.find(pnode, orig)
|
|
717
|
+
return @repo.dirstate.flags(@repo.working_join(path))
|
|
718
|
+
end
|
|
719
|
+
|
|
720
|
+
def useful_parents(log, revision)
|
|
721
|
+
parents = @parents.map {|p| p.revision}
|
|
722
|
+
if parents[1] == -1
|
|
723
|
+
if parents[0] >= @repo.size - 1
|
|
724
|
+
parents = []
|
|
725
|
+
else
|
|
726
|
+
parents = [parents[0]]
|
|
727
|
+
end
|
|
728
|
+
end
|
|
729
|
+
parents
|
|
730
|
+
end
|
|
731
|
+
|
|
732
|
+
##
|
|
733
|
+
# Recursively walk the directory tree, getting all files that +match+ says
|
|
734
|
+
# are good.
|
|
735
|
+
#
|
|
736
|
+
# @param [Amp::Match] match how to select the files in the tree
|
|
737
|
+
# @param [Boolean] check_ignored (false) should we check for ignored files?
|
|
738
|
+
# @return [Array<String>] an array of filenames in the tree that match +match+
|
|
739
|
+
def walk(match, check_ignored = false)
|
|
740
|
+
tree = @repo.staging_area.walk true, check_ignored, match
|
|
741
|
+
tree.keys.sort
|
|
742
|
+
end
|
|
743
|
+
|
|
744
|
+
# If there's a description, ok then
|
|
745
|
+
def description; @text; end
|
|
746
|
+
# Files affected in this transaction: modified, added, removed.
|
|
747
|
+
def files; (status[:modified] + status[:added] + status[:removed]).sort; end
|
|
748
|
+
# What files have changed?
|
|
749
|
+
def modified; status[:modified]; end
|
|
750
|
+
# What files have we added?
|
|
751
|
+
def added; status[:added]; end
|
|
752
|
+
# What files have been removed?
|
|
753
|
+
def removed; status[:removed]; end
|
|
754
|
+
# What files have been deleted (but not officially)?
|
|
755
|
+
def deleted; status[:deleted]; end
|
|
756
|
+
# What files are hanging out, but untracked?
|
|
757
|
+
def unknown; status[:unknown]; end
|
|
758
|
+
# What files are pristine since the last revision?
|
|
759
|
+
def clean; status[:normal]; end
|
|
760
|
+
# What branch are we in?
|
|
761
|
+
def branch; @extra["branch"]; end
|
|
762
|
+
# Any other extra data? i'd like to hear it
|
|
763
|
+
def extra; @extra; end
|
|
764
|
+
# No children. Returns the empty array.
|
|
765
|
+
def children; []; end
|
|
766
|
+
end
|
|
767
|
+
end
|
|
768
|
+
end
|