mercurial-ruby 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +32 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +86 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/lib/mercurial-ruby.rb +66 -0
- data/lib/mercurial-ruby/branch.rb +45 -0
- data/lib/mercurial-ruby/changed_file.rb +51 -0
- data/lib/mercurial-ruby/command.rb +77 -0
- data/lib/mercurial-ruby/commit.rb +152 -0
- data/lib/mercurial-ruby/config_file.rb +119 -0
- data/lib/mercurial-ruby/configuration.rb +14 -0
- data/lib/mercurial-ruby/diff.rb +50 -0
- data/lib/mercurial-ruby/factories/branch_factory.rb +91 -0
- data/lib/mercurial-ruby/factories/changed_file_factory.rb +50 -0
- data/lib/mercurial-ruby/factories/commit_factory.rb +154 -0
- data/lib/mercurial-ruby/factories/diff_factory.rb +63 -0
- data/lib/mercurial-ruby/factories/hook_factory.rb +45 -0
- data/lib/mercurial-ruby/factories/node_factory.rb +111 -0
- data/lib/mercurial-ruby/factories/tag_factory.rb +48 -0
- data/lib/mercurial-ruby/file_index.rb +209 -0
- data/lib/mercurial-ruby/helper.rb +23 -0
- data/lib/mercurial-ruby/hook.rb +23 -0
- data/lib/mercurial-ruby/manifest.rb +58 -0
- data/lib/mercurial-ruby/node.rb +100 -0
- data/lib/mercurial-ruby/repository.rb +94 -0
- data/lib/mercurial-ruby/root_node.rb +27 -0
- data/lib/mercurial-ruby/shell.rb +64 -0
- data/lib/mercurial-ruby/style.rb +23 -0
- data/lib/mercurial-ruby/tag.rb +33 -0
- data/lib/stdlib_exts/string.rb +12 -0
- data/lib/styles/changeset.style +5 -0
- data/lib/styles/file_index.style +3 -0
- data/mercurial-ruby.gemspec +227 -0
- data/test/fixtures.rb +28 -0
- data/test/fixtures/test-repo/.DotFile +1 -0
- data/test/fixtures/test-repo/.hg/00changelog.i +0 -0
- data/test/fixtures/test-repo/.hg/branch +1 -0
- data/test/fixtures/test-repo/.hg/cache/branchheads +6 -0
- data/test/fixtures/test-repo/.hg/cache/tags +7 -0
- data/test/fixtures/test-repo/.hg/dirstate +0 -0
- data/test/fixtures/test-repo/.hg/hgrc +3 -0
- data/test/fixtures/test-repo/.hg/last-message.txt +1 -0
- data/test/fixtures/test-repo/.hg/requires +4 -0
- data/test/fixtures/test-repo/.hg/store/00changelog.i +0 -0
- data/test/fixtures/test-repo/.hg/store/00manifest.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/_file _with _whitespace.pdf.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/_l_i_c_e_n_s_e.txt.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/_l_i_c_e_n_s_e2.txt.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/_l_i_c_e_n_s_e3.txt.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/_l_i_c_e_n_s_e4.txt.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/_r_e_a_d_m_e.markdown.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/_r_e_a_d_m_e.markup.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/_rakefile.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/_rakefile2.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/_rakefile3.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/check ~5c this ~5c out ~22 now.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/minitest__mixin.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/options.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/rdoc__mixin.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/rspec__mixin.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/shindo__mixin.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/shoulda__mixin.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/_gemfile.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/_l_i_c_e_n_s_e.txt.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/_r_e_a_d_m_e.rdoc.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/_rakefile.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/bacon/flunking.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/bacon/helper.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/bundler__setup.erb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/features/default.feature.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/features/support/env.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/jeweler__tasks.erb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/micronaut/flunking.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/micronaut/helper.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/minitest/flunking.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/minitest/helper.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/other__tasks.erb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/riot/flunking.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/riot/helper.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/rspec/flunking.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/rspec/helper.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/rspec/~2erspec.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/shindo/flunking.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/shindo/helper.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/shoulda/flunking.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/shoulda/helper.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/testspec/flunking.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/testspec/helper.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/testunit/flunking.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/testunit/helper.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/~2edocument.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/templates/~2egitignore.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory two/~2e_d_s___store.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory__1/rubygems__dot__org__tasks.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory__1/rubygems__tasks.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory__1/specification.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory__1/tasks.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/directory__1/~2e_d_s___store.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/empty-file.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/goose.png.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/goose/pretty-thing.txt.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/new-directory/another-boring-file.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/new-directory/something.csv.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/new-directory/subdirectory/_e_u_l_a5seat___chin___sim02.03.04.pdf.d +0 -0
- data/test/fixtures/test-repo/.hg/store/data/new-directory/subdirectory/_e_u_l_a5seat___chin___sim02.03.04.pdf.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/new-directory/subdirectory/_file _with _whitespace.pdf.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/new-directory/subdirectory/beansprout.png.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/new-file.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/old-directory/minitest__mixin.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/old-directory/options.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/old-directory/rspec__mixin.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/old-directory/shindo__mixin.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/old-directory/testunit__mixin.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/old-directory/yard__mixin.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/riot__mixin.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/riot__mixin__copy.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/style.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/super-cow.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/superman.txt.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/testspec__mixin.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/testspec__mixin__new.rb.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/~2e_dot_file.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/~2ehgignore.i +0 -0
- data/test/fixtures/test-repo/.hg/store/data/~2ehgtags.i +0 -0
- data/test/fixtures/test-repo/.hg/store/fncache +79 -0
- data/test/fixtures/test-repo/.hg/store/undo +0 -0
- data/test/fixtures/test-repo/.hg/undo.bookmarks +0 -0
- data/test/fixtures/test-repo/.hg/undo.branch +1 -0
- data/test/fixtures/test-repo/.hg/undo.desc +2 -0
- data/test/fixtures/test-repo/.hg/undo.dirstate +0 -0
- data/test/fixtures/test-repo/.hgignore +1 -0
- data/test/fixtures/test-repo/.hgtags +1 -0
- data/test/fixtures/test-repo/LICENSE3.txt +15 -0
- data/test/fixtures/test-repo/LICENSE4.txt +17 -0
- data/test/fixtures/test-repo/README.markup +218 -0
- data/test/fixtures/test-repo/Rakefile3 +83 -0
- data/test/fixtures/test-repo/check // this // out /" now" "b/data/test/fixtures/test-repo/check // this // out / → now +0 -0
- data/test/fixtures/test-repo/empty-file +0 -0
- data/test/fixtures/test-repo/goose.png +0 -0
- data/test/fixtures/test-repo/goose/pretty-thing.txt +0 -0
- data/test/fixtures/test-repo/new-directory/another-boring-file +78 -0
- data/test/fixtures/test-repo/new-directory/something.csv +1 -0
- data/test/fixtures/test-repo/new-directory/subdirectory/EULA5seat_Chin_Sim02.03.04.pdf +0 -0
- data/test/fixtures/test-repo/new-directory/subdirectory/File With Whitespace.pdf b/data/test/fixtures/test-repo/new-directory/subdirectory/File With → Whitespace.pdf +0 -0
- data/test/fixtures/test-repo/new-directory/subdirectory/beansprout.png +0 -0
- data/test/fixtures/test-repo/riot_mixin.rb +45 -0
- data/test/fixtures/test-repo/style +4 -0
- data/test/fixtures/test-repo/superman.txt +1 -0
- data/test/fixtures/test-repo/testspec_mixin_new.rb +44 -0
- data/test/helper.rb +41 -0
- data/test/test_branch_factory.rb +46 -0
- data/test/test_changed_file.rb +46 -0
- data/test/test_changed_file_factory.rb +16 -0
- data/test/test_command.rb +62 -0
- data/test/test_commit.rb +66 -0
- data/test/test_commit_factory.rb +101 -0
- data/test/test_config_file.rb +105 -0
- data/test/test_configuration.rb +26 -0
- data/test/test_diff.rb +39 -0
- data/test/test_diff_factory.rb +38 -0
- data/test/test_file_index.rb +113 -0
- data/test/test_hook.rb +39 -0
- data/test/test_hook_factory.rb +40 -0
- data/test/test_manifest.rb +39 -0
- data/test/test_node.rb +34 -0
- data/test/test_node_factory.rb +125 -0
- data/test/test_repository.rb +58 -0
- data/test/test_shell.rb +33 -0
- data/test/test_tag_factory.rb +27 -0
- metadata +328 -0
@@ -0,0 +1,152 @@
|
|
1
|
+
module Mercurial
|
2
|
+
|
3
|
+
#
|
4
|
+
# The class represents Mercurial changeset. Obtained by running an +hg log+ command.
|
5
|
+
# Contains a lot of information, including it's hash ID, author name and email, list of changed files, etc.
|
6
|
+
#
|
7
|
+
# The class represents Commit object itself, {Mercurial::CommitFactory CommitFactory} is responsible
|
8
|
+
# for assembling instances of Commit. For the list of all possible commit-related operations please
|
9
|
+
# look documentation for {Mercurial::CommitFactory CommitFactory}.
|
10
|
+
#
|
11
|
+
# Read more about Mercurial commits:
|
12
|
+
#
|
13
|
+
# http://mercurial.selenic.com/wiki/Commit
|
14
|
+
#
|
15
|
+
class Commit
|
16
|
+
include Mercurial::Helper
|
17
|
+
|
18
|
+
# Instance of {Mercurial::Repository Repository}.
|
19
|
+
attr_reader :repository
|
20
|
+
|
21
|
+
# Mercurial changeset ID. 40-chars long SHA1 hash.
|
22
|
+
attr_reader :hash_id
|
23
|
+
|
24
|
+
# Name of the user committed the change.
|
25
|
+
attr_reader :author
|
26
|
+
|
27
|
+
# Email of the user committed the change.
|
28
|
+
attr_reader :author_email
|
29
|
+
|
30
|
+
# Exact date and time of the commit. Contains Ruby Time object.
|
31
|
+
attr_reader :date
|
32
|
+
|
33
|
+
# Full commit message, with line breaks and other stuff.
|
34
|
+
attr_reader :message
|
35
|
+
|
36
|
+
# Array of {Mercurial::ChangedFile ChangedFile} objects.
|
37
|
+
attr_reader :changed_files
|
38
|
+
|
39
|
+
# Array of commit's branches.
|
40
|
+
attr_reader :branches_names
|
41
|
+
|
42
|
+
# Array of commit's tags.
|
43
|
+
attr_reader :tags_names
|
44
|
+
|
45
|
+
# Array of commit's parents.
|
46
|
+
attr_reader :parents_ids
|
47
|
+
|
48
|
+
alias :id :hash_id
|
49
|
+
|
50
|
+
def initialize(repository, opts={}) #:nodoc:
|
51
|
+
@repository = repository
|
52
|
+
@hash_id = opts[:hash_id]
|
53
|
+
@author = opts[:author]
|
54
|
+
@author_email = opts[:author_email]
|
55
|
+
@date = Time.iso8601(opts[:date])
|
56
|
+
@message = opts[:message]
|
57
|
+
@changed_files = files_to_array(opts[:changed_files])
|
58
|
+
@branches_names = branches_or_tags_to_array(opts[:branches_names])
|
59
|
+
@tags_names = branches_or_tags_to_array(opts[:tags_names])
|
60
|
+
@parents_ids = parents_to_array(opts[:parents])
|
61
|
+
end
|
62
|
+
|
63
|
+
def merge?
|
64
|
+
parents.size > 1
|
65
|
+
end
|
66
|
+
|
67
|
+
def blank?
|
68
|
+
hash_id == '0'*40
|
69
|
+
end
|
70
|
+
|
71
|
+
def diffs
|
72
|
+
repository.diffs.for_commit(self)
|
73
|
+
end
|
74
|
+
|
75
|
+
def parents
|
76
|
+
repository.commits.by_hash_ids(parents_ids)
|
77
|
+
end
|
78
|
+
|
79
|
+
def parent_id
|
80
|
+
parents_ids.first
|
81
|
+
end
|
82
|
+
|
83
|
+
def exist_in_branches
|
84
|
+
repository.branches.for_commit(hash_id)
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_hash
|
88
|
+
{
|
89
|
+
'id' => hash_id,
|
90
|
+
'parents' => parents_ids.map { |p| { 'id' => p.id } },
|
91
|
+
'branches' => branches_names,
|
92
|
+
'tags' => tags_names,
|
93
|
+
'message' => message,
|
94
|
+
'date' => date,
|
95
|
+
'author' => {
|
96
|
+
'name' => author,
|
97
|
+
'email' => author_email
|
98
|
+
}
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
protected
|
103
|
+
|
104
|
+
def files_to_array(array)
|
105
|
+
[].tap do |returning|
|
106
|
+
array.each do |files|
|
107
|
+
if files
|
108
|
+
files.split(';').map do |file_with_mode|
|
109
|
+
returning << Mercurial::ChangedFileFactory.new_from_hg(file_with_mode)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
remove_files_duplicates(returning)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def remove_files_duplicates(files)
|
119
|
+
Mercurial::ChangedFileFactory.delete_hg_artefacts(files)
|
120
|
+
end
|
121
|
+
|
122
|
+
def branches_or_tags_to_array(branches_str)
|
123
|
+
string_to_array(branches_str) do |returning|
|
124
|
+
returning << branches_str
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def parents_to_array(string)
|
129
|
+
string_to_array(string) do |returning|
|
130
|
+
string.split(' ').map do |hg_hash|
|
131
|
+
returning << hg_hash_to_hash_id(hg_hash)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def string_to_array(string, &block)
|
137
|
+
if string && !string.empty?
|
138
|
+
[].tap do |returning|
|
139
|
+
block.call(returning)
|
140
|
+
end
|
141
|
+
else
|
142
|
+
[]
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def hg_hash_to_hash_id(hg_hash)
|
147
|
+
hg_hash.split(':').last
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module Mercurial
|
2
|
+
|
3
|
+
#
|
4
|
+
# Represents +.hg/hgrc+ configuration file stored in the repository.
|
5
|
+
# Useful for adding/removing various settings.
|
6
|
+
#
|
7
|
+
# You can read more about hgrc here:
|
8
|
+
#
|
9
|
+
# http://www.selenic.com/mercurial/hgrc.5.html
|
10
|
+
#
|
11
|
+
class ConfigFile
|
12
|
+
|
13
|
+
attr_reader :repository
|
14
|
+
|
15
|
+
def initialize(repository)
|
16
|
+
@repository = repository
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
# Returns absolute path to the config file:
|
21
|
+
#
|
22
|
+
# config.path # => /home/ilya/repos/fancyrepo/.hg/hgrc
|
23
|
+
#
|
24
|
+
def path
|
25
|
+
File.join(repository.path, '.hg', 'hgrc')
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# Returns true if the config file actually exists on disk.
|
30
|
+
# For new repositories it's missing by default.
|
31
|
+
#
|
32
|
+
def exists?
|
33
|
+
File.exists?(path)
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# Returns contents of the config file as a string.
|
38
|
+
#
|
39
|
+
def contents
|
40
|
+
File.read(path) if exists?
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Adds specified setting to a specified section of the config:
|
45
|
+
#
|
46
|
+
# config.add_setting('merge-tools', 'kdiff3.executable', '~/bin/kdiff3')
|
47
|
+
#
|
48
|
+
# It will write the following content to the +hgrc+:
|
49
|
+
#
|
50
|
+
# [merge-tools]
|
51
|
+
# kdiff3.executable = ~/bin/kdiff3
|
52
|
+
#
|
53
|
+
def add_setting(header, name, value)
|
54
|
+
new_setting = %Q{[#{ header }]\n#{ name } = #{ value }\n}
|
55
|
+
write do
|
56
|
+
if contents.nil?
|
57
|
+
new_setting
|
58
|
+
elsif contents.scan(header_regexp(header)).empty?
|
59
|
+
contents << "\n\n#{ new_setting }"
|
60
|
+
else
|
61
|
+
contents.gsub(header_regexp(header), new_setting)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# Removes specified setting from the hgrc:
|
68
|
+
#
|
69
|
+
# config.delete_setting!('merge-tools', 'kdiff3.executable')
|
70
|
+
#
|
71
|
+
def delete_setting!(header, name)
|
72
|
+
write do
|
73
|
+
contents.gsub(find_setting(header, name), '')
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
#
|
78
|
+
# Returns content of the specified section of hgrc.
|
79
|
+
#
|
80
|
+
def find_header(header)
|
81
|
+
{}.tap do |returning|
|
82
|
+
contents.scan(header_with_content_regexp(header)).flatten.first.split("\n").each do |setting|
|
83
|
+
name, value = *setting.split('=').map(&:strip)
|
84
|
+
returning[name] = value
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
#
|
90
|
+
# Returns content of the specified setting from a section.
|
91
|
+
#
|
92
|
+
def find_setting(header, setting) #:nodoc:
|
93
|
+
contents.scan(setting_regexp(header, setting)).flatten.first
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def write(&block)
|
99
|
+
new_content = block.call
|
100
|
+
File.open(path, 'w') do |f|
|
101
|
+
f << new_content
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def header_regexp(header)
|
106
|
+
/(\[#{ Regexp.escape(header) }\]\s*)/
|
107
|
+
end
|
108
|
+
|
109
|
+
def header_with_content_regexp(header)
|
110
|
+
/\[#{ Regexp.escape(header) }\]\s*([^\[\]]*)/i
|
111
|
+
end
|
112
|
+
|
113
|
+
def setting_regexp(header, setting)
|
114
|
+
/\[#{ Regexp.escape(header) }\]\s*[^\[\]]*(^#{ Regexp.escape(setting) }.+\n*)/i
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Mercurial
|
2
|
+
|
3
|
+
#
|
4
|
+
# The class represents Mercurial diff. Obtained by running an +hg diff+ command.
|
5
|
+
#
|
6
|
+
# The class represents Diff object itself, {Mercurial::DiffFactory DiffFactory} is responsible
|
7
|
+
# for assembling instances of Diff. For the list of all possible diff-related operations please
|
8
|
+
# look documentation for {Mercurial::DiffFactory DiffFactory}.
|
9
|
+
#
|
10
|
+
class Diff
|
11
|
+
|
12
|
+
# Instance of {Mercurial::Commit Commit}.
|
13
|
+
attr_reader :commit
|
14
|
+
|
15
|
+
# SHA1 hash of version a of the file.
|
16
|
+
attr_reader :hash_a
|
17
|
+
|
18
|
+
# SHA1 hash of version b of the file.
|
19
|
+
attr_reader :hash_b
|
20
|
+
|
21
|
+
# Version a if the file name.
|
22
|
+
attr_reader :file_a
|
23
|
+
|
24
|
+
# Version b of the file name.
|
25
|
+
attr_reader :file_b
|
26
|
+
|
27
|
+
# Diff body.
|
28
|
+
attr_reader :body
|
29
|
+
|
30
|
+
def initialize(commit, opts={})
|
31
|
+
@commit = commit
|
32
|
+
@hash_a = opts[:hash_a]
|
33
|
+
@hash_b = opts[:hash_b]
|
34
|
+
@file_a = opts[:file_a]
|
35
|
+
@file_b = opts[:file_b]
|
36
|
+
@body = opts[:body]
|
37
|
+
@binary = opts[:binary]
|
38
|
+
end
|
39
|
+
|
40
|
+
def file_name
|
41
|
+
file_b || file_a
|
42
|
+
end
|
43
|
+
|
44
|
+
def binary?
|
45
|
+
!! @binary
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Mercurial
|
2
|
+
|
3
|
+
#
|
4
|
+
# This class represents a factory for {Mercurial::Branch Branch} instances.
|
5
|
+
#
|
6
|
+
class BranchFactory
|
7
|
+
include Mercurial::Helper
|
8
|
+
|
9
|
+
# Instance of {Mercurial::Repository Repository}.
|
10
|
+
attr_reader :repository
|
11
|
+
|
12
|
+
def initialize(repository)
|
13
|
+
@repository = repository
|
14
|
+
end
|
15
|
+
|
16
|
+
# Return an array of {Mercurial::Branch Branch} instances for all branches in the repository.
|
17
|
+
#
|
18
|
+
# == Example:
|
19
|
+
# repository.branches.all
|
20
|
+
#
|
21
|
+
def all
|
22
|
+
hg_to_array "branches -c" do |line|
|
23
|
+
build(line)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Return an array of {Mercurial::Branch Branch} instances for all active branches in the repository.
|
28
|
+
#
|
29
|
+
# == Example:
|
30
|
+
# repository.branches.active
|
31
|
+
#
|
32
|
+
def active
|
33
|
+
all.find_all do |b|
|
34
|
+
b.active?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Return an array of {Mercurial::Branch Branch} instances for all closed branches in the repository.
|
39
|
+
#
|
40
|
+
# == Example:
|
41
|
+
# repository.branches.closed
|
42
|
+
#
|
43
|
+
def closed
|
44
|
+
all.find_all do |b|
|
45
|
+
b.closed?
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Return a {Mercurial::Branch Branch} instance for a branch with a specified name.
|
50
|
+
#
|
51
|
+
# == Example:
|
52
|
+
# repository.branches.by_name('branchname')
|
53
|
+
#
|
54
|
+
def by_name(name)
|
55
|
+
all.find do |b|
|
56
|
+
b.name == name
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Return an array of {Mercurial::Branch Branch} instances where a specified commit exists.
|
61
|
+
# Experimental, doesn't always return a correct list of branches.
|
62
|
+
#
|
63
|
+
# == Example:
|
64
|
+
# repository.branches.for_commit('291a498f04e9')
|
65
|
+
#
|
66
|
+
def for_commit(hash_id)
|
67
|
+
hg_to_array ["log -r 'descendants(?) and head()' --template '\n{branches}'", hash_id] do |line|
|
68
|
+
build_with_name_only(line)
|
69
|
+
end.compact.uniq
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def build(data)
|
75
|
+
name, last_commit, status = *data.scan(/([\w-]+)\s+\d+:(\w+)\s*\(*(\w*)\)*/).first
|
76
|
+
Mercurial::Branch.new(
|
77
|
+
repository,
|
78
|
+
name,
|
79
|
+
:commit => last_commit,
|
80
|
+
:status => status
|
81
|
+
)
|
82
|
+
end
|
83
|
+
|
84
|
+
def build_with_name_only(name)
|
85
|
+
name = 'default' if name == ''
|
86
|
+
Mercurial::Branch.new(repository, name)
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Mercurial
|
2
|
+
|
3
|
+
class ChangedFileFactory
|
4
|
+
|
5
|
+
FILE_COPY_SEPARATOR = '->'
|
6
|
+
|
7
|
+
def self.new_from_hg(str)
|
8
|
+
if str.include?(FILE_COPY_SEPARATOR)
|
9
|
+
copied_file = str.split(FILE_COPY_SEPARATOR)
|
10
|
+
initial_name = copied_file.first[2..-1]
|
11
|
+
name = copied_file[1]
|
12
|
+
else
|
13
|
+
initial_name = nil
|
14
|
+
name = str[2..-1]
|
15
|
+
end
|
16
|
+
|
17
|
+
Mercurial::ChangedFile.new(
|
18
|
+
:initial_name => initial_name,
|
19
|
+
:name => name,
|
20
|
+
:mode => str[0..0]
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.delete_hg_artefacts(files)
|
25
|
+
#
|
26
|
+
# For unknown reason Mercurial post duplicated
|
27
|
+
# entries for moved and copied files. First as
|
28
|
+
# a pair of A and D operations, then as C.
|
29
|
+
#
|
30
|
+
files.reverse.each do |file|
|
31
|
+
if file.copied?
|
32
|
+
add = files.find{|f| f.added? && f.name == file.name}
|
33
|
+
delete = files.find{|f| f.deleted? && f.name == file.initial_name}
|
34
|
+
|
35
|
+
if add && delete
|
36
|
+
file.mode_letter = 'R'
|
37
|
+
files.delete_at(files.index(add))
|
38
|
+
files.delete_at(files.index(delete))
|
39
|
+
|
40
|
+
elsif add
|
41
|
+
files.delete_at(files.index(add))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
files
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|