ext 1.1.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +44 -15
- data/LICENSE-MPL-2.0.txt +373 -0
- data/LICENSE.txt +9 -0
- data/README +5 -13
- data/lib/externals/command.rb +6 -5
- data/lib/externals/configuration/configuration.rb +26 -21
- data/lib/externals/ext.rb +147 -175
- data/lib/externals/extensions/file_utils.rb +11 -11
- data/lib/externals/extensions/string.rb +7 -10
- data/lib/externals/project.rb +27 -41
- data/lib/externals/scms/git_project.rb +64 -53
- data/lib/externals/scms/svn_project.rb +55 -27
- data/version.rb +4 -0
- metadata +23 -82
- data/MIT_LICENSE.txt +0 -22
- data/Rakefile +0 -77
- data/lib/externals/extensions/symbol.rb +0 -7
- data/lib/externals/project_types/rails.rb +0 -35
- data/test/setup/empty_plugin.svn.gz +0 -0
- data/test/setup/foreign_key_migrations.svn.gz +0 -0
- data/test/setup/redhillonrails_core.svn.gz +0 -0
- data/test/test_checkout_git.rb +0 -32
- data/test/test_checkout_with_subprojects_git.rb +0 -169
- data/test/test_checkout_with_subprojects_svn.rb +0 -384
- data/test/test_file_utils_extensions.rb +0 -29
- data/test/test_freeze_to_revision.rb +0 -176
- data/test/test_git_project_extract_name.rb +0 -20
- data/test/test_help.rb +0 -27
- data/test/test_init_git.rb +0 -62
- data/test/test_out_of_date_git_subproject.rb +0 -83
- data/test/test_projects.rb +0 -148
- data/test/test_rails_detection.rb +0 -23
- data/test/test_string_extensions.rb +0 -51
- data/test/test_svn_branches.rb +0 -353
- data/test/test_touch_emptydirs.rb +0 -59
- data/test/test_version.rb +0 -33
data/lib/externals/ext.rb
CHANGED
|
@@ -4,59 +4,55 @@ require 'optparse'
|
|
|
4
4
|
require 'externals/command'
|
|
5
5
|
require 'fileutils'
|
|
6
6
|
|
|
7
|
+
require_relative "../../version"
|
|
8
|
+
|
|
7
9
|
Dir.entries(File.join(File.dirname(__FILE__), 'extensions')).each do |extension|
|
|
8
10
|
require "externals/extensions/#{extension}" if extension =~ /.rb$/
|
|
9
11
|
end
|
|
10
12
|
|
|
11
13
|
module Externals
|
|
12
|
-
VERSION = '1.1.3'
|
|
13
|
-
PROJECT_TYPES_DIRECTORY = File.join(File.dirname(__FILE__), '..', 'externals','project_types')
|
|
14
|
-
|
|
15
14
|
# Full commands operate on the main project as well as the externals
|
|
16
15
|
# short commands only operate on the externals
|
|
17
16
|
# Main commands only operate on the main project
|
|
18
17
|
FULL_COMMANDS_HASH = [
|
|
19
18
|
[:checkout, "ext checkout <repository>",
|
|
20
|
-
|
|
19
|
+
%{Checks out <repository>, and checks out any subprojects
|
|
21
20
|
registered in <repository>'s .externals file.}],
|
|
22
21
|
[:export, "ext export <repository>",
|
|
23
|
-
|
|
22
|
+
%{Like checkout except this command fetches as little
|
|
24
23
|
history as possible.}],
|
|
25
24
|
[:status, "ext status",
|
|
26
|
-
|
|
25
|
+
%{Prints out the status of the main project, followed by
|
|
27
26
|
the status of each subproject.}],
|
|
28
27
|
[:update, "ext update",
|
|
29
|
-
|
|
28
|
+
%{Brings the main project, and all subprojects, up to the
|
|
30
29
|
latest version.}]
|
|
31
|
-
]
|
|
30
|
+
].freeze
|
|
32
31
|
SHORT_COMMANDS_HASH = [
|
|
33
32
|
[:co, "Like checkout, but skips the main project and
|
|
34
33
|
only checks out subprojects."],
|
|
35
34
|
[:ex, "Like export, but skips the main project."],
|
|
36
35
|
[:st, "Like status, but skips the main project."],
|
|
37
36
|
[:up, "Like update, but skips the main project."]
|
|
38
|
-
]
|
|
37
|
+
].freeze
|
|
39
38
|
MAIN_COMMANDS_HASH = [
|
|
40
39
|
[:freeze, "ext freeze <subproject> [REVISION]",
|
|
41
|
-
|
|
40
|
+
%{Locks a subproject into a specific revision/branch. If no
|
|
42
41
|
revision is supplied, the current revision/branch of the
|
|
43
42
|
project will be used. You can specify the subproject by name
|
|
44
43
|
or path.}],
|
|
45
44
|
[:help, "You probably just ran this command just now."],
|
|
46
45
|
[:init, "Creates a .externals file containing only [main]
|
|
47
|
-
It will try to determine the SCM used by the main project,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
[:install, "ext install <repository> [-b <branch>] [path]",
|
|
53
|
-
"Registers <repository> in .externals under the appropriate
|
|
54
|
-
SCM. Checks out the project, and also adds it to the ignore
|
|
46
|
+
It will try to determine the SCM used by the main project."],
|
|
47
|
+
[:install, "ext install <repository> [-b <branch>] <path>",
|
|
48
|
+
"Registers <repository> in .externals under the appropriate
|
|
49
|
+
SCM. Checks out the subproject at given path,
|
|
50
|
+
and also adds it to the ignore
|
|
55
51
|
feature offered by the SCM of the main project. If the SCM
|
|
56
52
|
type is not obvious from the repository URL, use the --scm,
|
|
57
53
|
--git, or --svn flags."],
|
|
58
54
|
[:switch, "ext switch <branch_name>",
|
|
59
|
-
|
|
55
|
+
"Changes to the named branch <branch_name> and updates any
|
|
60
56
|
subprojects and applies any changes that have been made to the
|
|
61
57
|
.externals file."],
|
|
62
58
|
[:touch_emptydirs, "Recurses through all directories from the
|
|
@@ -64,10 +60,10 @@ module Externals
|
|
|
64
60
|
comes across. Useful for dealing with SCMs that refuse to
|
|
65
61
|
track empty directories (such as git, for example)"],
|
|
66
62
|
[:unfreeze, "ext unfreeze <subproject>",
|
|
67
|
-
|
|
63
|
+
%{Unfreezes a previously frozen subproject. You can specify
|
|
68
64
|
the subproject by name or path.}],
|
|
69
65
|
[:uninstall, "ext uninstall [-f|--force_removal] <project>",
|
|
70
|
-
|
|
66
|
+
"Removes a subproject from being tracked by ext. If you
|
|
71
67
|
want the files associated with this subproject deleted as well
|
|
72
68
|
(if, for example, you wish to reinstall it from a different
|
|
73
69
|
repository) then you can use the -f option to remove the files."],
|
|
@@ -77,11 +73,10 @@ module Externals
|
|
|
77
73
|
and so you probably only will run this if you are manually
|
|
78
74
|
maintaining .externals"],
|
|
79
75
|
[:version, "Displays the version number of externals and exits."],
|
|
80
|
-
]
|
|
81
|
-
|
|
76
|
+
].freeze
|
|
82
77
|
|
|
83
78
|
FULL_COMMANDS = FULL_COMMANDS_HASH.map(&:first)
|
|
84
|
-
SHORT_COMMANDS =
|
|
79
|
+
SHORT_COMMANDS = SHORT_COMMANDS_HASH.map(&:first)
|
|
85
80
|
MAIN_COMMANDS = MAIN_COMMANDS_HASH.map(&:first)
|
|
86
81
|
|
|
87
82
|
COMMANDS = FULL_COMMANDS + SHORT_COMMANDS + MAIN_COMMANDS
|
|
@@ -89,40 +84,14 @@ module Externals
|
|
|
89
84
|
COULD_NOT_DETERMINE_SCM = 1
|
|
90
85
|
NO_EXTERNALS_FILE = 2
|
|
91
86
|
|
|
92
|
-
Dir.entries(File.join(File.dirname(__FILE__), '..', 'externals','scms')).each do |project|
|
|
87
|
+
Dir.entries(File.join(File.dirname(__FILE__), '..', 'externals', 'scms')).each do |project|
|
|
93
88
|
require "externals/scms/#{project}" if project =~ /_project.rb$/
|
|
94
89
|
end
|
|
95
90
|
|
|
96
|
-
Dir.entries(PROJECT_TYPES_DIRECTORY).each do |type|
|
|
97
|
-
require File.join(PROJECT_TYPES_DIRECTORY, type) if type =~ /\.rb$/
|
|
98
|
-
end
|
|
99
|
-
|
|
100
91
|
class Ext
|
|
101
92
|
include FileUtils
|
|
102
93
|
extend FileUtils
|
|
103
94
|
|
|
104
|
-
attr_accessor :path_calculator
|
|
105
|
-
|
|
106
|
-
def self.project_types
|
|
107
|
-
types = Dir.entries(PROJECT_TYPES_DIRECTORY).select do |file|
|
|
108
|
-
file =~ /\.rb$/
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
types.map do |type|
|
|
112
|
-
/^(.*)\.rb$/.match(type)[1]
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def self.project_type_files
|
|
117
|
-
project_types.map do |project_type|
|
|
118
|
-
"#{File.join(PROJECT_TYPES_DIRECTORY, project_type)}.rb"
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
project_type_files.each do |file|
|
|
123
|
-
require file
|
|
124
|
-
end
|
|
125
|
-
|
|
126
95
|
def self.new_opts main_options, sub_options
|
|
127
96
|
opts = OptionParser.new(
|
|
128
97
|
"ext [OPTIONS] <command> [repository] [-b <branch>] [path]"
|
|
@@ -133,37 +102,35 @@ module Externals
|
|
|
133
102
|
|
|
134
103
|
project_classes.each do |project_class|
|
|
135
104
|
project_class.fill_in_opts(opts, main_options, sub_options,
|
|
136
|
-
|
|
105
|
+
:summary_width => summary_width)
|
|
137
106
|
end
|
|
138
107
|
|
|
139
|
-
opts.on("--type TYPE", "-t TYPE",
|
|
140
|
-
String,
|
|
141
|
-
*"The type of project the main project is.
|
|
142
|
-
For example, 'rails'.".lines_by_width(summary_width)
|
|
143
|
-
) {|type| sub_options[:type] = main_options[:type] = type}
|
|
144
108
|
opts.on("--scm SCM", "-s SCM",
|
|
145
|
-
|
|
146
|
-
|
|
109
|
+
String,
|
|
110
|
+
*"The SCM used to manage the main project. For example, '--scm svn'.".lines_by_width(summary_width)
|
|
147
111
|
) {|scm| sub_options[:scm] = main_options[:scm] = scm}
|
|
148
112
|
opts.on("--branch BRANCH", "-b BRANCH",
|
|
149
|
-
|
|
150
|
-
|
|
113
|
+
String,
|
|
114
|
+
*"The branch you want the
|
|
151
115
|
subproject to checkout when doing 'ext install'".lines_by_width(summary_width)
|
|
152
116
|
) {|branch| sub_options[:branch] = main_options[:branch] = branch}
|
|
153
117
|
opts.on("--revision REVISION", "-r REVISION",
|
|
154
|
-
|
|
155
|
-
|
|
118
|
+
String,
|
|
119
|
+
*"The revision you want the
|
|
156
120
|
subproject to checkout when doing 'ext install'".lines_by_width(summary_width)
|
|
157
121
|
) {|revision| sub_options[:revision] = main_options[:revision] = revision}
|
|
158
122
|
opts.on("--force_removal", "-f",
|
|
159
|
-
|
|
160
|
-
|
|
123
|
+
String,
|
|
124
|
+
*"When doing an uninstall of a subproject,
|
|
161
125
|
remove it's files and subfolders, too.".lines_by_width(summary_width)
|
|
162
|
-
) {
|
|
163
|
-
opts.on(
|
|
126
|
+
) { sub_options[:force_removal] = true }
|
|
127
|
+
opts.on(
|
|
128
|
+
"--workdir DIR", "-w DIR", String,
|
|
129
|
+
*"The working directory to execute commands from. Use this if for some reason you
|
|
164
130
|
cannot execute ext from the main project's directory (or if it's just inconvenient, such as in a script
|
|
165
131
|
or in a Capistrano task)".lines_by_width(summary_width)) {|dir|
|
|
166
132
|
raise "No such directory: #{dir}" unless File.exist?(dir) && File.directory?(dir)
|
|
133
|
+
|
|
167
134
|
main_options[:workdir] = dir
|
|
168
135
|
}
|
|
169
136
|
opts.on(
|
|
@@ -187,7 +154,7 @@ module Externals
|
|
|
187
154
|
|
|
188
155
|
unless args.nil? || args.empty?
|
|
189
156
|
command = args[0]
|
|
190
|
-
args = args[1..
|
|
157
|
+
args = args[1..] || []
|
|
191
158
|
end
|
|
192
159
|
|
|
193
160
|
command &&= command.to_sym
|
|
@@ -196,20 +163,23 @@ module Externals
|
|
|
196
163
|
command = :version if main_options[:version]
|
|
197
164
|
|
|
198
165
|
if !command || command.to_s == ''
|
|
166
|
+
# :nocov:
|
|
199
167
|
puts "hey... you didn't tell me what you want to do."
|
|
200
168
|
puts "Try 'ext help' for a list of commands"
|
|
201
|
-
exit
|
|
169
|
+
exit 1
|
|
170
|
+
# :nocov:
|
|
202
171
|
end
|
|
203
172
|
|
|
204
173
|
unless COMMANDS.index command
|
|
174
|
+
# :nocov:
|
|
205
175
|
puts "unknown command: #{command}"
|
|
206
176
|
puts "for a list of commands try 'ext help'"
|
|
207
|
-
exit
|
|
177
|
+
exit 1
|
|
178
|
+
# :nocov:
|
|
208
179
|
end
|
|
209
180
|
|
|
210
|
-
|
|
211
181
|
Dir.chdir(main_options[:workdir] || ".") do
|
|
212
|
-
|
|
182
|
+
new(main_options).send(command, args, sub_options)
|
|
213
183
|
end
|
|
214
184
|
end
|
|
215
185
|
|
|
@@ -220,9 +190,9 @@ module Externals
|
|
|
220
190
|
puts
|
|
221
191
|
end
|
|
222
192
|
|
|
223
|
-
def help(
|
|
193
|
+
def help(_args, _options)
|
|
224
194
|
puts "There's a tutorial available at http://nopugs.com/ext-tutorial\n\n"
|
|
225
|
-
puts "#{self.class.new_opts({},{})
|
|
195
|
+
puts "#{self.class.new_opts({}, {})}\n\n"
|
|
226
196
|
|
|
227
197
|
puts "\nCommands that apply to the main project or the .externals file:"
|
|
228
198
|
puts "#{MAIN_COMMANDS.join(', ')}\n\n"
|
|
@@ -240,6 +210,7 @@ module Externals
|
|
|
240
210
|
@registered_scms = nil
|
|
241
211
|
def self.registered_scms
|
|
242
212
|
return @registered_scms if @registered_scms
|
|
213
|
+
|
|
243
214
|
@registered_scms ||= []
|
|
244
215
|
|
|
245
216
|
scmdir = File.join(File.dirname(__FILE__), 'scms')
|
|
@@ -255,9 +226,10 @@ module Externals
|
|
|
255
226
|
|
|
256
227
|
def projects
|
|
257
228
|
return @projects if @projects
|
|
229
|
+
|
|
258
230
|
@projects = []
|
|
259
231
|
configuration.sections.each do |section|
|
|
260
|
-
@projects << Ext.project_class(section[:scm]||infer_scm(section[:repository])).new(
|
|
232
|
+
@projects << Ext.project_class(section[:scm] || infer_scm(section[:repository])).new(
|
|
261
233
|
section.attributes.merge(:path => section.title))
|
|
262
234
|
end
|
|
263
235
|
#let's set the parents of these projects
|
|
@@ -272,11 +244,14 @@ module Externals
|
|
|
272
244
|
project ||= subprojects.detect do |p|
|
|
273
245
|
File.split(p.path).last.strip == name
|
|
274
246
|
end
|
|
275
|
-
project
|
|
247
|
+
project || subprojects.detect do |p|
|
|
248
|
+
# TODO: test (or delete) this code path!
|
|
249
|
+
# :nocov:
|
|
276
250
|
p.name == name
|
|
251
|
+
# :nocov:
|
|
277
252
|
end
|
|
278
253
|
end
|
|
279
|
-
alias
|
|
254
|
+
alias subproject subproject_by_name_or_path
|
|
280
255
|
|
|
281
256
|
def subprojects
|
|
282
257
|
s = []
|
|
@@ -287,7 +262,7 @@ module Externals
|
|
|
287
262
|
end
|
|
288
263
|
|
|
289
264
|
def main_project
|
|
290
|
-
projects.detect
|
|
265
|
+
projects.detect(&:main_project?)
|
|
291
266
|
end
|
|
292
267
|
|
|
293
268
|
def configuration
|
|
@@ -316,43 +291,17 @@ module Externals
|
|
|
316
291
|
|
|
317
292
|
scm = configuration['.']
|
|
318
293
|
scm = scm['scm'] if scm
|
|
319
|
-
scm
|
|
320
|
-
|
|
321
|
-
type = configuration['.']
|
|
322
|
-
type = type['type'] if type
|
|
323
|
-
|
|
324
|
-
type ||= options[:type]
|
|
325
|
-
|
|
326
|
-
if type
|
|
327
|
-
install_project_type type
|
|
328
|
-
else
|
|
329
|
-
possible_project_types = self.class.project_types.select do |project_type|
|
|
330
|
-
self.class.project_type_detector(project_type).detected?
|
|
331
|
-
end
|
|
332
|
-
|
|
333
|
-
if possible_project_types.size > 1
|
|
334
|
-
raise "We found multiple project types that this could be: #{possible_project_types.join(',')}
|
|
335
|
-
Please use
|
|
336
|
-
the --type option to tell ext which to use."
|
|
337
|
-
else
|
|
338
|
-
possible_project_types.each do |project_type|
|
|
339
|
-
install_project_type project_type
|
|
340
|
-
end
|
|
341
|
-
end
|
|
342
|
-
end
|
|
294
|
+
scm || options[:scm]
|
|
343
295
|
end
|
|
344
296
|
|
|
345
297
|
def self.project_class(scm)
|
|
346
|
-
Externals.
|
|
298
|
+
Externals.const_get("#{scm.to_s.cap_first}Project")
|
|
347
299
|
end
|
|
348
300
|
|
|
349
301
|
def self.project_classes
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
retval << project_class(scm)
|
|
302
|
+
registered_scms.map do |scm|
|
|
303
|
+
project_class(scm)
|
|
353
304
|
end
|
|
354
|
-
|
|
355
|
-
retval
|
|
356
305
|
end
|
|
357
306
|
|
|
358
307
|
SHORT_COMMANDS.each do |command_name|
|
|
@@ -368,16 +317,18 @@ Please use
|
|
|
368
317
|
p.name == project_name_or_path || p.path == project_name_or_path
|
|
369
318
|
end
|
|
370
319
|
|
|
320
|
+
# :nocov:
|
|
371
321
|
raise "no such project" unless project
|
|
322
|
+
# :nocov:
|
|
372
323
|
|
|
373
324
|
project.send command_name, args, options
|
|
374
325
|
else
|
|
375
|
-
subprojects.each {|p| p.send(*
|
|
326
|
+
subprojects.each {|p| p.send(*[command_name, args, options].flatten)}
|
|
376
327
|
end
|
|
377
328
|
end
|
|
378
329
|
end
|
|
379
330
|
|
|
380
|
-
def freeze args,
|
|
331
|
+
def freeze args, _options
|
|
381
332
|
project = subproject_by_name_or_path(args[0])
|
|
382
333
|
|
|
383
334
|
raise "No such project named #{args[0]}" unless project
|
|
@@ -391,7 +342,10 @@ Please use
|
|
|
391
342
|
if branch
|
|
392
343
|
section[:branch] = branch
|
|
393
344
|
else
|
|
345
|
+
# TODO: test (or delete) this code path!
|
|
346
|
+
# :nocov:
|
|
394
347
|
section.rm_setting :branch
|
|
348
|
+
# :nocov:
|
|
395
349
|
end
|
|
396
350
|
end
|
|
397
351
|
section[:revision] = revision
|
|
@@ -401,7 +355,7 @@ Please use
|
|
|
401
355
|
subproject_by_name_or_path(args[0]).up
|
|
402
356
|
end
|
|
403
357
|
|
|
404
|
-
def unfreeze args,
|
|
358
|
+
def unfreeze args, _options
|
|
405
359
|
project = subproject_by_name_or_path(args[0])
|
|
406
360
|
|
|
407
361
|
raise "No such project named #{args[0]}" unless project
|
|
@@ -409,8 +363,10 @@ Please use
|
|
|
409
363
|
section = configuration[project.path]
|
|
410
364
|
|
|
411
365
|
unless section[:revision]
|
|
366
|
+
# :nocov:
|
|
412
367
|
puts "Uhh... #{project.name} wasn't frozen, so I can't unfreeze it."
|
|
413
|
-
exit
|
|
368
|
+
exit 1
|
|
369
|
+
# :nocov:
|
|
414
370
|
end
|
|
415
371
|
|
|
416
372
|
section.rm_setting :revision
|
|
@@ -422,8 +378,10 @@ Please use
|
|
|
422
378
|
|
|
423
379
|
def install args, options
|
|
424
380
|
if !File.exist?('.externals')
|
|
425
|
-
|
|
381
|
+
# :nocov:
|
|
382
|
+
warn "This project does not appear to be managed by externals. Try 'ext init' first"
|
|
426
383
|
exit NO_EXTERNALS_FILE
|
|
384
|
+
# :nocov:
|
|
427
385
|
end
|
|
428
386
|
repository = args[0]
|
|
429
387
|
path = args[1]
|
|
@@ -435,15 +393,17 @@ Please use
|
|
|
435
393
|
scm ||= infer_scm(repository)
|
|
436
394
|
|
|
437
395
|
unless scm
|
|
438
|
-
|
|
396
|
+
# :nocov:
|
|
397
|
+
warn "Unable to determine SCM from the repository name.
|
|
439
398
|
You need to either specify the scm used to manage the subproject
|
|
440
399
|
that you are installing. Use an option to specify it
|
|
441
400
|
(such as --git or --svn)"
|
|
442
401
|
exit COULD_NOT_DETERMINE_SCM
|
|
402
|
+
# :nocov:
|
|
443
403
|
end
|
|
444
404
|
|
|
445
405
|
project = self.class.project_class(scm).new(:repository => repository,
|
|
446
|
-
|
|
406
|
+
:path => path, :scm => scm)
|
|
447
407
|
path = project.path
|
|
448
408
|
|
|
449
409
|
raise "no path" unless path
|
|
@@ -466,7 +426,9 @@ that you are installing. Use an option to specify it
|
|
|
466
426
|
|
|
467
427
|
def uninstall args, options
|
|
468
428
|
unless File.exist?('.externals')
|
|
429
|
+
# :nocov:
|
|
469
430
|
raise "Hmm... there's no .externals file in this directory."
|
|
431
|
+
# :nocov:
|
|
470
432
|
end
|
|
471
433
|
|
|
472
434
|
project = subproject_by_name_or_path(args[0])
|
|
@@ -475,7 +437,6 @@ that you are installing. Use an option to specify it
|
|
|
475
437
|
|
|
476
438
|
main_project.drop_from_ignore project.path
|
|
477
439
|
|
|
478
|
-
|
|
479
440
|
configuration.remove_section(project.path)
|
|
480
441
|
configuration.write '.externals'
|
|
481
442
|
reload_configuration
|
|
@@ -487,15 +448,18 @@ that you are installing. Use an option to specify it
|
|
|
487
448
|
end
|
|
488
449
|
end
|
|
489
450
|
|
|
490
|
-
def update_ignore
|
|
451
|
+
def update_ignore _args, options
|
|
491
452
|
scm = configuration['.']
|
|
492
453
|
scm = scm['scm'] if scm
|
|
493
454
|
|
|
494
455
|
scm ||= options[:scm]
|
|
495
456
|
|
|
496
457
|
unless scm
|
|
497
|
-
|
|
458
|
+
# :nocov:
|
|
459
|
+
raise "You need to either specify the scm as the first line in .externals (for example, scm = git), " \
|
|
460
|
+
"or use an option to specify it
|
|
498
461
|
(such as --git or --svn)"
|
|
462
|
+
# :nocov:
|
|
499
463
|
end
|
|
500
464
|
|
|
501
465
|
project = self.class.project_class(scm).new(:path => ".")
|
|
@@ -507,10 +471,10 @@ that you are installing. Use an option to specify it
|
|
|
507
471
|
end
|
|
508
472
|
end
|
|
509
473
|
|
|
510
|
-
def touch_emptydirs
|
|
474
|
+
def touch_emptydirs _args, _options
|
|
511
475
|
require 'find'
|
|
512
476
|
|
|
513
|
-
excludes = ['.','..','.svn', '.git']
|
|
477
|
+
excludes = ['.', '..', '.svn', '.git']
|
|
514
478
|
|
|
515
479
|
excludes.dup.each do |exclude|
|
|
516
480
|
excludes << "./#{exclude}"
|
|
@@ -522,23 +486,26 @@ that you are installing. Use an option to specify it
|
|
|
522
486
|
if File.directory?(f)
|
|
523
487
|
excluded = false
|
|
524
488
|
File.split(f).each do |part|
|
|
525
|
-
|
|
489
|
+
excluded ||= excludes.index(part)
|
|
526
490
|
end
|
|
527
491
|
|
|
528
|
-
if !excluded && (
|
|
492
|
+
if !excluded && (Dir.entries(f) - excludes).empty?
|
|
529
493
|
paths << f
|
|
530
494
|
end
|
|
531
495
|
end
|
|
532
496
|
end
|
|
533
497
|
|
|
534
498
|
paths.each do |p|
|
|
535
|
-
|
|
499
|
+
# TODO: is there not an easier way to touch a file??
|
|
500
|
+
# rubocop:disable Style/FileOpen
|
|
501
|
+
f = File.open(File.join(p, ".emptydir"), "w")
|
|
502
|
+
# rubocop:enable Style/FileOpen
|
|
503
|
+
ensure
|
|
504
|
+
f.close
|
|
536
505
|
end
|
|
537
|
-
|
|
538
506
|
end
|
|
539
507
|
|
|
540
|
-
|
|
541
|
-
def status args, options
|
|
508
|
+
def status _args, options
|
|
542
509
|
options ||= {}
|
|
543
510
|
scm = options[:scm]
|
|
544
511
|
|
|
@@ -548,24 +515,27 @@ that you are installing. Use an option to specify it
|
|
|
548
515
|
end
|
|
549
516
|
|
|
550
517
|
if !scm
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
518
|
+
# TODO: test (or delete) this code path!
|
|
519
|
+
# :nocov:
|
|
520
|
+
possible_project_classes = self.class.project_classes.select(&:detected?)
|
|
554
521
|
|
|
555
|
-
raise "Could not determine this projects scm" if
|
|
522
|
+
raise "Could not determine this projects scm" if possible_project_classes.empty?
|
|
556
523
|
if possible_project_classes.size > 1
|
|
557
524
|
raise "This project appears to be managed by multiple SCMs: #{
|
|
558
|
-
possible_project_classes.
|
|
525
|
+
possible_project_classes.join(',')}
|
|
559
526
|
Please explicitly declare the SCM (by using --git or --svn, or,
|
|
560
527
|
by creating the .externals file manually"
|
|
561
528
|
end
|
|
562
529
|
|
|
563
530
|
scm = possible_project_classes.first.scm
|
|
531
|
+
# :nocov:
|
|
564
532
|
end
|
|
565
533
|
|
|
566
534
|
unless scm
|
|
535
|
+
# :nocov:
|
|
567
536
|
raise "You need to either specify the scm as the first line in .externals, or use an option to specify it
|
|
568
537
|
(such as --git or --svn)"
|
|
538
|
+
# :nocov:
|
|
569
539
|
end
|
|
570
540
|
|
|
571
541
|
project = main_project
|
|
@@ -587,24 +557,27 @@ by creating the .externals file manually"
|
|
|
587
557
|
end
|
|
588
558
|
|
|
589
559
|
if !scm
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
560
|
+
# TODO: test (or delete) this code path!
|
|
561
|
+
# :nocov:
|
|
562
|
+
possible_project_classes = self.class.project_classes.select(&:detected?)
|
|
593
563
|
|
|
594
|
-
raise "Could not determine this projects scm" if
|
|
564
|
+
raise "Could not determine this projects scm" if possible_project_classes.empty?
|
|
595
565
|
if possible_project_classes.size > 1
|
|
596
566
|
raise "This project appears to be managed by multiple SCMs: #{
|
|
597
|
-
possible_project_classes.
|
|
567
|
+
possible_project_classes.join(',')}
|
|
598
568
|
Please explicitly declare the SCM (by using --git or --svn, or,
|
|
599
569
|
by creating the .externals file manually"
|
|
600
570
|
end
|
|
601
571
|
|
|
602
572
|
scm = possible_project_classes.first.scm
|
|
573
|
+
# :nocov:
|
|
603
574
|
end
|
|
604
575
|
|
|
605
576
|
unless scm
|
|
577
|
+
# :nocov:
|
|
606
578
|
raise "You need to either specify the scm as the first line in .externals, or use an option to specify it
|
|
607
579
|
(such as --git or --svn)"
|
|
580
|
+
# :nocov:
|
|
608
581
|
end
|
|
609
582
|
|
|
610
583
|
old_config = configuration
|
|
@@ -639,7 +612,7 @@ commands below if you actually wish to delete them."
|
|
|
639
612
|
end
|
|
640
613
|
end
|
|
641
614
|
|
|
642
|
-
def update
|
|
615
|
+
def update _args, options
|
|
643
616
|
options ||= {}
|
|
644
617
|
scm = options[:scm]
|
|
645
618
|
|
|
@@ -649,8 +622,10 @@ commands below if you actually wish to delete them."
|
|
|
649
622
|
end
|
|
650
623
|
|
|
651
624
|
unless scm
|
|
625
|
+
# :nocov:
|
|
652
626
|
raise "You need to either specify the scm as the first line in .externals, or use an option to specify it
|
|
653
627
|
(such as --git or --svn)"
|
|
628
|
+
# :nocov:
|
|
654
629
|
end
|
|
655
630
|
|
|
656
631
|
project = main_project
|
|
@@ -673,7 +648,7 @@ commands below if you actually wish to delete them."
|
|
|
673
648
|
end
|
|
674
649
|
|
|
675
650
|
Dir.chdir path do
|
|
676
|
-
self.class.new({}).co [], {}
|
|
651
|
+
self.class.new({}).co [], {}
|
|
677
652
|
end
|
|
678
653
|
end
|
|
679
654
|
|
|
@@ -686,7 +661,10 @@ commands below if you actually wish to delete them."
|
|
|
686
661
|
main_project = do_checkout_or_export repository, path, options, :export
|
|
687
662
|
|
|
688
663
|
if path == "."
|
|
664
|
+
# TODO: test (or delete) this code path!
|
|
665
|
+
# :nocov:
|
|
689
666
|
path = main_project.name
|
|
667
|
+
# :nocov:
|
|
690
668
|
end
|
|
691
669
|
|
|
692
670
|
Dir.chdir path do
|
|
@@ -695,42 +673,27 @@ commands below if you actually wish to delete them."
|
|
|
695
673
|
end
|
|
696
674
|
|
|
697
675
|
def init args, options = {}
|
|
676
|
+
# :nocov:
|
|
698
677
|
raise ".externals already exists" if File.exist?('.externals')
|
|
678
|
+
# :nocov:
|
|
699
679
|
|
|
700
680
|
scm = options[:scm]
|
|
701
|
-
type = options[:type]
|
|
702
681
|
|
|
703
682
|
if !scm
|
|
704
|
-
possible_project_classes = self.class.project_classes.select
|
|
705
|
-
project_class.detected?
|
|
706
|
-
end
|
|
683
|
+
possible_project_classes = self.class.project_classes.select(&:detected?)
|
|
707
684
|
|
|
708
|
-
raise "Could not determine this project's scm" if
|
|
685
|
+
raise "Could not determine this project's scm" if possible_project_classes.empty?
|
|
709
686
|
if possible_project_classes.size > 1
|
|
687
|
+
# :nocov:
|
|
710
688
|
raise "This project appears to be managed by multiple SCMs: #{
|
|
711
|
-
possible_project_classes.
|
|
689
|
+
possible_project_classes.join(',')}
|
|
712
690
|
Please explicitly declare the SCM (using --git or --svn, or, by creating .externals manually"
|
|
691
|
+
# :nocov:
|
|
713
692
|
end
|
|
714
693
|
|
|
715
694
|
scm = possible_project_classes.first.scm
|
|
716
695
|
end
|
|
717
696
|
|
|
718
|
-
if !type
|
|
719
|
-
possible_project_types = self.class.project_types.select do |project_type|
|
|
720
|
-
self.class.project_type_detector(project_type).detected?
|
|
721
|
-
end
|
|
722
|
-
|
|
723
|
-
if possible_project_types.size > 1
|
|
724
|
-
raise "We found multiple project types that this could be: #{possible_project_types.join(',')}
|
|
725
|
-
Please use the --type option to tell ext which to use."
|
|
726
|
-
elsif possible_project_types.size == 0
|
|
727
|
-
puts "WARNING: We could not automatically determine the project type.
|
|
728
|
-
Be sure to specify paths when adding subprojects to your .externals file"
|
|
729
|
-
else
|
|
730
|
-
type = possible_project_types.first
|
|
731
|
-
end
|
|
732
|
-
end
|
|
733
|
-
|
|
734
697
|
config = Configuration::Configuration.new_empty
|
|
735
698
|
raise ".externals already exists" if File.exist?('.externals')
|
|
736
699
|
|
|
@@ -744,33 +707,30 @@ Please use the --type option to tell ext which to use."
|
|
|
744
707
|
options[:branch]
|
|
745
708
|
)
|
|
746
709
|
elsif args[0]
|
|
710
|
+
# TODO: test (or delete) this code path!
|
|
711
|
+
# :nocov:
|
|
747
712
|
config['.'][:repository] = args[0].strip
|
|
713
|
+
# :nocov:
|
|
748
714
|
end
|
|
749
715
|
end
|
|
750
716
|
|
|
751
717
|
config['.'][:scm] = scm
|
|
752
|
-
config['.'][:type] = type if type
|
|
753
718
|
|
|
754
719
|
config.write '.externals'
|
|
755
720
|
reload_configuration
|
|
756
721
|
end
|
|
757
722
|
|
|
758
|
-
def version(
|
|
723
|
+
def version(_args, _options)
|
|
759
724
|
puts Externals::VERSION
|
|
760
725
|
end
|
|
761
726
|
|
|
762
|
-
def self.project_type_detector name
|
|
763
|
-
Externals.module_eval("#{name.classify}Detector", __FILE__, __LINE__)
|
|
764
|
-
end
|
|
765
|
-
|
|
766
|
-
def install_project_type name
|
|
767
|
-
self.path_calculator = Externals.module_eval("#{name.classify}ProjectType::DefaultPathCalculator", __FILE__, __LINE__)
|
|
768
|
-
end
|
|
769
|
-
|
|
770
727
|
protected
|
|
728
|
+
|
|
771
729
|
def do_checkout_or_export repository, path, options, sym
|
|
772
730
|
if File.exist?('.externals')
|
|
731
|
+
# :nocov:
|
|
773
732
|
raise "seems main project is already checked out here?"
|
|
733
|
+
# :nocov:
|
|
774
734
|
else
|
|
775
735
|
#We appear to be attempting to checkout/export a main project
|
|
776
736
|
scm = options[:scm]
|
|
@@ -778,13 +738,18 @@ Please use the --type option to tell ext which to use."
|
|
|
778
738
|
scm ||= infer_scm(repository)
|
|
779
739
|
|
|
780
740
|
if !scm
|
|
741
|
+
# TODO: test (or delete) this code path!
|
|
742
|
+
# :nocov:
|
|
781
743
|
scm ||= configuration['main']
|
|
782
744
|
scm &&= scm['scm']
|
|
745
|
+
# :nocov:
|
|
783
746
|
end
|
|
784
747
|
|
|
785
748
|
unless scm
|
|
749
|
+
# :nocov:
|
|
786
750
|
raise "You need to either specify the scm as the first line in .externals, or use an option to specify it
|
|
787
751
|
(such as --git or --svn)"
|
|
752
|
+
# :nocov:
|
|
788
753
|
end
|
|
789
754
|
|
|
790
755
|
main_project = self.class.project_class(scm).new(
|
|
@@ -799,12 +764,19 @@ Please use the --type option to tell ext which to use."
|
|
|
799
764
|
end
|
|
800
765
|
|
|
801
766
|
def infer_scm(path)
|
|
802
|
-
|
|
803
|
-
|
|
767
|
+
registered_scms.find do |scm|
|
|
768
|
+
project_class(scm).scm_path?(path)
|
|
804
769
|
end
|
|
805
|
-
nil
|
|
806
770
|
end
|
|
807
|
-
end
|
|
808
|
-
end
|
|
809
771
|
|
|
772
|
+
private
|
|
773
|
+
|
|
774
|
+
def registered_scms
|
|
775
|
+
self.class.registered_scms
|
|
776
|
+
end
|
|
810
777
|
|
|
778
|
+
def project_class(scm)
|
|
779
|
+
self.class.project_class(scm)
|
|
780
|
+
end
|
|
781
|
+
end
|
|
782
|
+
end
|