svnauto 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/INSTALL +48 -0
- data/LICENSE +22 -0
- data/README +81 -0
- data/THANKS +8 -0
- data/TODO +9 -0
- data/bin/sc +35 -0
- data/doc/manual.txt +241 -0
- data/lib/sc.rb +38 -0
- data/lib/sc/command.rb +118 -0
- data/lib/sc/commands/bug.rb +161 -0
- data/lib/sc/commands/checkout.rb +71 -0
- data/lib/sc/commands/config.rb +58 -0
- data/lib/sc/commands/create.rb +68 -0
- data/lib/sc/commands/experimental.rb +142 -0
- data/lib/sc/commands/info.rb +54 -0
- data/lib/sc/commands/list.rb +40 -0
- data/lib/sc/commands/release.rb +98 -0
- data/lib/sc/config_file.rb +87 -0
- data/lib/sc/constants.rb +40 -0
- data/lib/sc/dispatcher.rb +189 -0
- data/lib/sc/path.rb +51 -0
- data/lib/sc/project.rb +265 -0
- data/lib/sc/repository.rb +108 -0
- data/lib/sc/svn.rb +96 -0
- data/lib/sc/version.rb +111 -0
- data/test/projfiles/file_one +3 -0
- data/test/projfiles/file_two +3 -0
- data/test/setup.rb +97 -0
- data/test/test_bug.rb +55 -0
- data/test/test_checkout.rb +20 -0
- data/test/test_create.rb +20 -0
- data/test/test_experimental.rb +86 -0
- data/test/test_release.rb +37 -0
- data/test/test_version.rb +41 -0
- metadata +99 -0
data/lib/sc/constants.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
################################################################################
|
2
|
+
#
|
3
|
+
# Copyright (C) 2006 Peter J Jones (pjones@pmade.com)
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
#
|
24
|
+
################################################################################
|
25
|
+
module SC
|
26
|
+
module Constants
|
27
|
+
################################################################################
|
28
|
+
# The version number for this copy of SC
|
29
|
+
VERSION = '1.0.0'
|
30
|
+
|
31
|
+
################################################################################
|
32
|
+
# What to call myself
|
33
|
+
ME = 'sc'
|
34
|
+
|
35
|
+
################################################################################
|
36
|
+
TERMINAL = HighLine.new
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
################################################################################
|
@@ -0,0 +1,189 @@
|
|
1
|
+
################################################################################
|
2
|
+
#
|
3
|
+
# Copyright (C) 2006 Peter J Jones (pjones@pmade.com)
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
#
|
24
|
+
################################################################################
|
25
|
+
require 'abbrev'
|
26
|
+
require 'optparse'
|
27
|
+
################################################################################
|
28
|
+
module SC
|
29
|
+
################################################################################
|
30
|
+
class Dispatcher
|
31
|
+
################################################################################
|
32
|
+
def initialize
|
33
|
+
@options = OptionParser.new
|
34
|
+
@command_names = {}
|
35
|
+
@first_names = {}
|
36
|
+
|
37
|
+
Command.commands.each do |command|
|
38
|
+
names = []
|
39
|
+
|
40
|
+
case command.name
|
41
|
+
when Array : command.name.each {|n| names << n.to_s}
|
42
|
+
else names << command.name.to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
@first_names[names.first] = command
|
46
|
+
|
47
|
+
names.each do |name|
|
48
|
+
raise "Duplicate name: #{name}" if @command_names.has_key?(name)
|
49
|
+
@command_names[name] = command
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
@abbrevations = @command_names.keys.abbrev
|
54
|
+
end
|
55
|
+
|
56
|
+
################################################################################
|
57
|
+
def run (args=ARGV)
|
58
|
+
@options.on("-h", "--help", 'This message') do |o|
|
59
|
+
list
|
60
|
+
end
|
61
|
+
|
62
|
+
# it's unfortunate that this is a class method
|
63
|
+
HighLine.use_color = false
|
64
|
+
|
65
|
+
config = ConfigFile.new
|
66
|
+
HighLine.use_color = true if config[:color]
|
67
|
+
|
68
|
+
@options.on('--version', "Show #{Constants::ME} version info") do |o|
|
69
|
+
Constants::TERMINAL.say(Constants::TERMINAL.color(Constants::VERSION, :red))
|
70
|
+
exit
|
71
|
+
end
|
72
|
+
|
73
|
+
@options.on('--verbose', 'Show svn commands as they execute') do |o|
|
74
|
+
$DEBUG = true
|
75
|
+
end
|
76
|
+
|
77
|
+
@options.on('--color', 'Use colored output') do |o|
|
78
|
+
HighLine.use_color = true
|
79
|
+
end
|
80
|
+
|
81
|
+
@options.on('--no-color', "Don't use colored output") do |o|
|
82
|
+
HighLine.use_color = false
|
83
|
+
end
|
84
|
+
|
85
|
+
@project = Project.from_cwd(config)
|
86
|
+
ask_for_repository = nil
|
87
|
+
ask_for_project = nil
|
88
|
+
|
89
|
+
@options.on("-p", "--project NAME", "use project NAME or ':' to prompt") do |name|
|
90
|
+
if name == ':'
|
91
|
+
ask_for_project = true
|
92
|
+
else
|
93
|
+
@project.name = name
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
@options.on("-r", "--repository NAME", "use repository NAME or ':' to prompt") do |name|
|
98
|
+
if name == ':'
|
99
|
+
ask_for_repository = true
|
100
|
+
elsif (@project.repository = config.find_repository(name)).nil?
|
101
|
+
raise "#{name}: no such repository defined"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
subcommand_options = @options.order!(args)
|
106
|
+
klass = klass_from_string(subcommand_options.shift) or list
|
107
|
+
|
108
|
+
if ask_for_repository or (@project.repository.nil? and klass.without_repository.nil?)
|
109
|
+
@project.repository = config.prompt_for_repository
|
110
|
+
|
111
|
+
if @project.repository.nil?
|
112
|
+
raise "please specify a repository, or run from an existing checkout"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
if ask_for_project or (@project.name.nil? and klass.without_project.nil?)
|
117
|
+
@project.prompt_for_name
|
118
|
+
|
119
|
+
if @project.name.nil?
|
120
|
+
raise "please specify a project name, or run from an existing checkout"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
process(klass, subcommand_options, @project)
|
125
|
+
end
|
126
|
+
|
127
|
+
################################################################################
|
128
|
+
def list (with_exit=true)
|
129
|
+
lines = @options.to_s.split(/\r?\n/)
|
130
|
+
lines.first << " command [options]"
|
131
|
+
puts lines.join("\n")
|
132
|
+
puts
|
133
|
+
puts "Avaliable Commands:"
|
134
|
+
|
135
|
+
length = @first_names.keys.inject(0) {|m,o| m >= o.length ? m : o.length} + 4
|
136
|
+
@first_names.keys.sort.each do |name|
|
137
|
+
puts name.rjust(length) + " " + @command_names[name].description
|
138
|
+
end
|
139
|
+
|
140
|
+
exit if with_exit
|
141
|
+
end
|
142
|
+
|
143
|
+
################################################################################
|
144
|
+
def process (klass, options, project)
|
145
|
+
klass.options.on('-h', '--help', 'This message') do |val|
|
146
|
+
puts usage_for(klass)
|
147
|
+
exit
|
148
|
+
end
|
149
|
+
|
150
|
+
klass.reset!
|
151
|
+
command_extras = klass.options.order!(options)
|
152
|
+
return unless klass.instance_methods.include?('run')
|
153
|
+
|
154
|
+
if klass.args_min and command_extras.length < klass.args_min
|
155
|
+
puts usage_for(klass)
|
156
|
+
exit 1
|
157
|
+
elsif klass.args_max and command_extras.length > klass.args_max
|
158
|
+
puts usage_for(klass)
|
159
|
+
exit 1
|
160
|
+
end
|
161
|
+
|
162
|
+
klass.new.run(project, command_extras)
|
163
|
+
end
|
164
|
+
|
165
|
+
################################################################################
|
166
|
+
def usage_for (klass)
|
167
|
+
name = klass.name.is_a?(Array) ? klass.name.first : klass.name
|
168
|
+
|
169
|
+
lines = klass.options.to_s.split(/\r?\n/)
|
170
|
+
lines.first << " #{name} #{klass.usage || '[options]'}"
|
171
|
+
lines.first << "\n#{klass.description}"
|
172
|
+
|
173
|
+
if klass.name.is_a?(Array) and klass.name.length > 1
|
174
|
+
lines.first << "\nShortcuts: #{klass.name[1..-1].join(', ')}"
|
175
|
+
end
|
176
|
+
|
177
|
+
lines.first << "\n\nOptions for the #{name} command:"
|
178
|
+
lines.join("\n")
|
179
|
+
end
|
180
|
+
|
181
|
+
################################################################################
|
182
|
+
def klass_from_string (string)
|
183
|
+
@command_names[@abbrevations[string]]
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
################################################################################
|
188
|
+
end
|
189
|
+
################################################################################
|
data/lib/sc/path.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
################################################################################
|
2
|
+
#
|
3
|
+
# Copyright (C) 2006 Peter J Jones (pjones@pmade.com)
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
#
|
24
|
+
################################################################################
|
25
|
+
module SC
|
26
|
+
################################################################################
|
27
|
+
module Path
|
28
|
+
################################################################################
|
29
|
+
# convert a relative path to home to absolute
|
30
|
+
def self.absolute_from_home (path)
|
31
|
+
home = File.expand_path('~')
|
32
|
+
path.strip!
|
33
|
+
|
34
|
+
# path may start with ~
|
35
|
+
path = File.expand_path(path) if path[0, 1] == '~'
|
36
|
+
|
37
|
+
# allow path to be relative or absolute
|
38
|
+
path[0, 1] == '/' ? path : File.join(home, path)
|
39
|
+
end
|
40
|
+
|
41
|
+
################################################################################
|
42
|
+
# make an absolute path relative to home
|
43
|
+
def self.relative_to_home (path)
|
44
|
+
home = File.expand_path('~')
|
45
|
+
path[0, home.length] == home ? path.sub(home, '~') : path
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
################################################################################
|
50
|
+
end
|
51
|
+
################################################################################
|
data/lib/sc/project.rb
ADDED
@@ -0,0 +1,265 @@
|
|
1
|
+
################################################################################
|
2
|
+
#
|
3
|
+
# Copyright (C) 2006 Peter J Jones (pjones@pmade.com)
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
#
|
24
|
+
################################################################################
|
25
|
+
module SC
|
26
|
+
################################################################################
|
27
|
+
class Project
|
28
|
+
################################################################################
|
29
|
+
# The name of the project
|
30
|
+
attr_accessor :name
|
31
|
+
|
32
|
+
################################################################################
|
33
|
+
# The repository for this project
|
34
|
+
attr_accessor :repository
|
35
|
+
|
36
|
+
################################################################################
|
37
|
+
# Try to get info about the current directory's repository
|
38
|
+
def self.from_cwd (config)
|
39
|
+
url = nil
|
40
|
+
project = nil
|
41
|
+
|
42
|
+
# see if we're in an svn directory
|
43
|
+
Svn.info do |line|
|
44
|
+
m = line.match(/^Repository\s+Root:\s+(.+)$/) and url = m[1]
|
45
|
+
m = line.match(/^URL:\s+(.+)$/) and project = m[1]
|
46
|
+
end
|
47
|
+
|
48
|
+
if url and project
|
49
|
+
# try to find a matching repository
|
50
|
+
repository = config[:repositories].find {|r| r.url == url}
|
51
|
+
repository ||= Repository.new(:url => url)
|
52
|
+
|
53
|
+
new({
|
54
|
+
:repository => repository,
|
55
|
+
:name => project[url.length + 1 .. -1].sub(/\/.*$/, ''),
|
56
|
+
})
|
57
|
+
else
|
58
|
+
new
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
################################################################################
|
63
|
+
# remove special characters from a project name
|
64
|
+
def self.clean_name (non_clean_name)
|
65
|
+
non_clean_name.gsub(/[^\w\d_-]+/, '_')
|
66
|
+
end
|
67
|
+
|
68
|
+
################################################################################
|
69
|
+
# Setup a new project
|
70
|
+
def initialize (options={})
|
71
|
+
@name = options[:name]
|
72
|
+
@repository = options[:repository]
|
73
|
+
end
|
74
|
+
|
75
|
+
################################################################################
|
76
|
+
# get the URL to this project
|
77
|
+
def url
|
78
|
+
"#{@repository.url}/#{@name}"
|
79
|
+
end
|
80
|
+
|
81
|
+
################################################################################
|
82
|
+
# convert to a string
|
83
|
+
def to_s
|
84
|
+
@name
|
85
|
+
end
|
86
|
+
|
87
|
+
################################################################################
|
88
|
+
# prompt the user to pick a project name from the repository
|
89
|
+
def prompt_for_name
|
90
|
+
names = []
|
91
|
+
|
92
|
+
if URI.parse(@repository.url).scheme != 'file'
|
93
|
+
puts "Fetching project list from repository, please wait..."
|
94
|
+
$stdout.flush
|
95
|
+
end
|
96
|
+
|
97
|
+
Svn.list(@repository.url) do |line|
|
98
|
+
next if line.match(/^svn:/)
|
99
|
+
names << line.sub(/\/$/, '').strip
|
100
|
+
end
|
101
|
+
|
102
|
+
if names.empty?
|
103
|
+
raise "there are no projects in the repository #{@repository.url}"
|
104
|
+
end
|
105
|
+
|
106
|
+
@name = Constants::TERMINAL.choose do |menu|
|
107
|
+
menu.header = "Projects"
|
108
|
+
menu.prompt = "Please choose a project: "
|
109
|
+
|
110
|
+
names.each do |name|
|
111
|
+
menu.choice(name) {name}
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
################################################################################
|
117
|
+
# get a list of the directories that sc uses
|
118
|
+
def directories
|
119
|
+
[
|
120
|
+
url,
|
121
|
+
trunk,
|
122
|
+
branches,
|
123
|
+
branches('rel'),
|
124
|
+
branches('bug'),
|
125
|
+
branches('exp'),
|
126
|
+
tags,
|
127
|
+
tags('rel'),
|
128
|
+
tags('bug'),
|
129
|
+
tags('exp'),
|
130
|
+
]
|
131
|
+
end
|
132
|
+
|
133
|
+
################################################################################
|
134
|
+
# create the necessary project directories in the repository
|
135
|
+
def create
|
136
|
+
directories.each do |dir|
|
137
|
+
unless Svn.has_path(dir)
|
138
|
+
Svn.mkdir('-m', "'#{Constants::ME}: creating #{dir} for project #{name}.'", dir)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
################################################################################
|
144
|
+
# get the latest release branch version
|
145
|
+
def latest_release_branch
|
146
|
+
@versions ||= []
|
147
|
+
|
148
|
+
if @versions.empty?
|
149
|
+
Svn.list(release) do |line|
|
150
|
+
next if line.match(/^svn:/)
|
151
|
+
@versions << Version.new(line.sub(/\/$/, '').strip)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
@versions.sort.last
|
156
|
+
end
|
157
|
+
|
158
|
+
################################################################################
|
159
|
+
# get the latest release tag for the given branch version
|
160
|
+
def latest_release_tag (branch_version)
|
161
|
+
tags = []
|
162
|
+
branch_version_str = branch_version.major_minor
|
163
|
+
|
164
|
+
Svn.list(tags('rel')) do |line|
|
165
|
+
tag = line.sub(/\/$/, '').strip
|
166
|
+
next unless tag[0, branch_version_str.length] == branch_version_str
|
167
|
+
tags << Version.new(tag)
|
168
|
+
end
|
169
|
+
|
170
|
+
tags.sort.last
|
171
|
+
end
|
172
|
+
|
173
|
+
################################################################################
|
174
|
+
# checkout to the workspace
|
175
|
+
def checkout (version=nil, to=nil)
|
176
|
+
workspace = @repository.workspace
|
177
|
+
url = trunk
|
178
|
+
co_name = "#{@name}-trunk"
|
179
|
+
|
180
|
+
Dir.mkdir(workspace) unless File.exist?(workspace)
|
181
|
+
|
182
|
+
case version
|
183
|
+
when String
|
184
|
+
url = version
|
185
|
+
co_name = "#{@name}-" + version.sub("#{self.url}/", '').gsub(/\//, '-')
|
186
|
+
co_name.sub!(/branches-/, '')
|
187
|
+
co_name.sub!(/releases/, 'rel')
|
188
|
+
when Version
|
189
|
+
url = version.macro.nil? ? release(version.to_s) : tags("rel/#{version.to_s}")
|
190
|
+
co_name = "#{@name}-rel-#{version}"
|
191
|
+
end
|
192
|
+
|
193
|
+
co_name = to if to
|
194
|
+
local_dir = File.join(workspace, co_name)
|
195
|
+
Svn.checkout(url, local_dir) unless File.exist?(local_dir)
|
196
|
+
|
197
|
+
local_dir
|
198
|
+
end
|
199
|
+
|
200
|
+
################################################################################
|
201
|
+
# do some common stuff for merging
|
202
|
+
def merge (version, start_tag, end_tag, &error_block)
|
203
|
+
tmp_checkout = "#{@name}-merge-tmp-#{$$}"
|
204
|
+
dir = self.checkout(version, tmp_checkout)
|
205
|
+
|
206
|
+
base = self.url
|
207
|
+
start_tag = self.tags(start_tag) unless start_tag[0, base.length] == base
|
208
|
+
end_tag = self.tags(end_tag) unless end_tag[0, base.length] == base
|
209
|
+
|
210
|
+
Dir.chdir(dir) do
|
211
|
+
conflicts = false
|
212
|
+
|
213
|
+
Svn.merge(start_tag, end_tag) do |line|
|
214
|
+
conflicts = true if line.match(/^\s*C/)
|
215
|
+
print line
|
216
|
+
end
|
217
|
+
|
218
|
+
if conflicts
|
219
|
+
message = "merge failed, you need to resolve conflicts in #{dir} "
|
220
|
+
message << yield if block_given?
|
221
|
+
raise message
|
222
|
+
end
|
223
|
+
|
224
|
+
Svn.commit('-m', "'#{Constants::ME}: merging branch using tags #{start_tag} and #{end_tag}'")
|
225
|
+
end
|
226
|
+
|
227
|
+
# clean up after merge
|
228
|
+
system('rm', '-rf', dir) or raise "failed to remove tmp merge directory: #{dir}"
|
229
|
+
end
|
230
|
+
|
231
|
+
|
232
|
+
################################################################################
|
233
|
+
# get the full URL to the trunk for this repository and project
|
234
|
+
def trunk
|
235
|
+
"#{url}/trunk"
|
236
|
+
end
|
237
|
+
|
238
|
+
################################################################################
|
239
|
+
# get the full URL path for branches
|
240
|
+
def branches (subdir=nil)
|
241
|
+
path = "#{url}/branches"
|
242
|
+
path << "/#{subdir}" if subdir
|
243
|
+
path
|
244
|
+
end
|
245
|
+
|
246
|
+
################################################################################
|
247
|
+
# get the full URL path for tags
|
248
|
+
def tags (subdir=nil)
|
249
|
+
path = "#{url}/tags"
|
250
|
+
path << "/#{subdir}" if subdir
|
251
|
+
path
|
252
|
+
end
|
253
|
+
|
254
|
+
################################################################################
|
255
|
+
# get the full URL to the release branch
|
256
|
+
def release (version=nil)
|
257
|
+
path = branches('rel')
|
258
|
+
path << "/#{version}" if version
|
259
|
+
path
|
260
|
+
end
|
261
|
+
|
262
|
+
end
|
263
|
+
################################################################################
|
264
|
+
end
|
265
|
+
################################################################################
|