ext 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +9 -0
- data/Rakefile +59 -32
- data/lib/externals/configuration/configuration.rb +22 -0
- data/lib/externals/ext.rb +55 -14
- data/lib/externals/project.rb +9 -5
- data/lib/externals/scms/git_project.rb +43 -12
- data/lib/externals/scms/svn_project.rb +40 -7
- data/lib/externals/test_case.rb +25 -29
- data/test/test_checkout_git.rb +2 -0
- data/test/test_checkout_with_subprojects_git.rb +5 -2
- data/test/test_checkout_with_subprojects_svn.rb +8 -4
- data/test/test_freeze_to_revision.rb +108 -0
- data/test/test_init_git.rb +2 -0
- data/test/test_rails_detection.rb +2 -0
- data/test/test_string_extensions.rb +2 -0
- data/test/test_touch_emptydirs.rb +2 -0
- data/test/test_upgrade_externals_file.rb +2 -0
- metadata +5 -4
data/README
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
Externals is a project that allows you to use the workflow normally made
|
2
2
|
possible by svn:externals in an SCM independent manner.
|
3
3
|
|
4
|
+
Please report bugs to either http://rubyforge.org/projects/ext or
|
5
|
+
http://ext.lighthouseapp.com
|
6
|
+
|
4
7
|
I was inspired to create this project because I had several projects that had
|
5
8
|
a mix of plugins managed by git and by svn. Git's submodule feature is
|
6
9
|
not exactly like svn:externals. Basically, I don't like how you have to manually
|
@@ -49,6 +52,12 @@ install Usage: ext install <repository> [-b <branch>] [path]
|
|
49
52
|
type is not obvious from the repository URL, use the --scm,
|
50
53
|
--git, or --svn flags.
|
51
54
|
|
55
|
+
freeze ext freeze project [REVISION]
|
56
|
+
Locks a subproject into a specific revision/branch. If no
|
57
|
+
revision is supplied, the current revision/branch of the
|
58
|
+
project will be used. You can specify the project by name
|
59
|
+
or path.
|
60
|
+
|
52
61
|
init Creates a .externals file containing only [main]
|
53
62
|
It will try to determine the SCM used by the main project,
|
54
63
|
as well as the project type. You don't have to specify
|
data/Rakefile
CHANGED
@@ -3,6 +3,33 @@ require 'rake/testtask'
|
|
3
3
|
require 'rake/rdoctask'
|
4
4
|
require 'rake/gempackagetask'
|
5
5
|
|
6
|
+
root_dir = File.dirname(__FILE__)
|
7
|
+
|
8
|
+
desc "Creates the starting repositories needed to run the tests.
|
9
|
+
If you plan on running the tests, you only need
|
10
|
+
to run this once."
|
11
|
+
task :prep_test do
|
12
|
+
Dir.chdir File.join(root_dir, 'test') do
|
13
|
+
|
14
|
+
puts `rm -rf cleanreps`
|
15
|
+
Dir.mkdir('cleanreps')
|
16
|
+
Dir.chdir('cleanreps') do
|
17
|
+
%w(redhillonrails_core foreign_key_migrations).each do |p|
|
18
|
+
puts `cp ../setup/#{p}.svn.gz .`
|
19
|
+
puts `gzip -d #{p}.svn.gz`
|
20
|
+
puts `svnadmin create #{p}`
|
21
|
+
puts `svnadmin load #{p} < #{p}.svn`
|
22
|
+
end
|
23
|
+
|
24
|
+
%w(acts_as_list rails).each do |p|
|
25
|
+
puts `git clone --bare git://github.com/rails/#{p}.git #{p}.git`
|
26
|
+
end
|
27
|
+
|
28
|
+
puts `git clone --bare git://github.com/azimux/engines.git engines.git`
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
6
33
|
Rake::TestTask.new('test') do |task|
|
7
34
|
task.libs = [File.expand_path('lib'),File.expand_path('test')]
|
8
35
|
task.pattern = './test/test_*.rb'
|
@@ -11,54 +38,54 @@ end
|
|
11
38
|
|
12
39
|
gem_specification = Gem::Specification.new do |specification|
|
13
40
|
specification.name = 'ext'
|
14
|
-
specification.version = '0.1.
|
41
|
+
specification.version = '0.1.1'
|
15
42
|
specification.platform = Gem::Platform::RUBY
|
16
43
|
specification.rubyforge_project = 'ext'
|
17
|
-
|
18
|
-
specification.summary =
|
19
|
-
%{Provides an SCM agnostic way to manage subprojects with a workflow similar
|
20
|
-
to the svn:externals feature of subversion. It's particularly useful for rails
|
44
|
+
|
45
|
+
specification.summary =
|
46
|
+
%{Provides an SCM agnostic way to manage subprojects with a workflow similar
|
47
|
+
to the svn:externals feature of subversion. It's particularly useful for rails
|
21
48
|
projects that have some plugins managed by svn and some managed by git.}
|
22
|
-
specification.description =
|
23
|
-
%{Provides an SCM agnostic way to manage subprojects with a workflow similar
|
24
|
-
to the scm:externals feature of subversion. It's particularly useful for rails
|
25
|
-
projects that have some plugins managed by svn and some managed by git.
|
26
|
-
|
27
|
-
For example, "ext install git://github.com/rails/rails.git" from within a rails
|
28
|
-
application directory will realize that this belongs in the vendor/rails folder.
|
29
|
-
It will also realize that this URL is a git repository and clone it into that
|
30
|
-
folder.
|
31
|
-
|
32
|
-
It will also add the vendor/rails folder to the ignore feature for the SCM of
|
33
|
-
the main project. Let's say that the main project is being managed by
|
34
|
-
subversion. In that case it adds "rails" to the svn:ignore property of the
|
35
|
-
vendor folder. It also adds the URL to the .externals file so that when this
|
36
|
-
project is checked out via "ext checkout" it knows where to fetch the
|
37
|
-
subprojects.
|
38
|
-
|
39
|
-
There are several other useful commands, such as init, touch_emptydirs, add_all,
|
49
|
+
specification.description =
|
50
|
+
%{Provides an SCM agnostic way to manage subprojects with a workflow similar
|
51
|
+
to the scm:externals feature of subversion. It's particularly useful for rails
|
52
|
+
projects that have some plugins managed by svn and some managed by git.
|
53
|
+
|
54
|
+
For example, "ext install git://github.com/rails/rails.git" from within a rails
|
55
|
+
application directory will realize that this belongs in the vendor/rails folder.
|
56
|
+
It will also realize that this URL is a git repository and clone it into that
|
57
|
+
folder.
|
58
|
+
|
59
|
+
It will also add the vendor/rails folder to the ignore feature for the SCM of
|
60
|
+
the main project. Let's say that the main project is being managed by
|
61
|
+
subversion. In that case it adds "rails" to the svn:ignore property of the
|
62
|
+
vendor folder. It also adds the URL to the .externals file so that when this
|
63
|
+
project is checked out via "ext checkout" it knows where to fetch the
|
64
|
+
subprojects.
|
65
|
+
|
66
|
+
There are several other useful commands, such as init, touch_emptydirs, add_all,
|
40
67
|
export, status. There's a tutorial at http://nopugs.com/ext-tutorial
|
41
68
|
|
42
69
|
The reason I made this project is that I was frustrated by two things:
|
43
70
|
|
44
|
-
1. In my opinion, the workflow for svn:externals is far superior to
|
45
|
-
git-submodule.
|
71
|
+
1. In my opinion, the workflow for svn:externals is far superior to
|
72
|
+
git-submodule.
|
46
73
|
|
47
|
-
2. Even if git-submodule was as useful as svn:externals, I would still like a
|
48
|
-
uniform way to fetch all of the subprojects regardless of the SCM used to manage
|
74
|
+
2. Even if git-submodule was as useful as svn:externals, I would still like a
|
75
|
+
uniform way to fetch all of the subprojects regardless of the SCM used to manage
|
49
76
|
the main project.}
|
50
|
-
|
77
|
+
|
51
78
|
specification.author = "Miles Georgi"
|
52
79
|
specification.email = "azimux@gmail.com"
|
53
80
|
specification.homepage = "http://nopugs.com/ext-tutorial"
|
54
|
-
|
81
|
+
|
55
82
|
specification.test_files = FileList['test/test_*.rb']
|
56
|
-
|
83
|
+
|
57
84
|
specification.bindir = "bin"
|
58
85
|
specification.executables = ['ext']
|
59
86
|
specification.default_executable = "ext"
|
60
|
-
|
61
|
-
specification.files = ['Rakefile', 'README', 'MIT_LICENSE.txt'] +
|
87
|
+
|
88
|
+
specification.files = ['Rakefile', 'README', 'MIT_LICENSE.txt'] +
|
62
89
|
FileList['lib/**/*.rb']
|
63
90
|
#specification.require_path = 'lib'
|
64
91
|
end
|
@@ -60,6 +60,28 @@ module Externals
|
|
60
60
|
end
|
61
61
|
value
|
62
62
|
end
|
63
|
+
|
64
|
+
def rm_setting key
|
65
|
+
key = key.to_s
|
66
|
+
found = nil
|
67
|
+
value = nil
|
68
|
+
|
69
|
+
rows.each_with_index do |row, index|
|
70
|
+
if row =~ SETTING_REGEX && key == $1
|
71
|
+
raise "found #{key} twice!" if found
|
72
|
+
found = index
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
if found
|
77
|
+
value = self[key]
|
78
|
+
if rows[found] !~ SET_SETTING_REGEX
|
79
|
+
raise "thought I found the row, but didn't"
|
80
|
+
end
|
81
|
+
rows.delete rows[found]
|
82
|
+
end
|
83
|
+
value
|
84
|
+
end
|
63
85
|
|
64
86
|
def [] key
|
65
87
|
setting(key)
|
data/lib/externals/ext.rb
CHANGED
@@ -9,8 +9,8 @@ require 'extensions/symbol'
|
|
9
9
|
module Externals
|
10
10
|
#exit status
|
11
11
|
OBSOLETE_EXTERNALS_FILE = 15
|
12
|
-
|
13
|
-
|
12
|
+
|
13
|
+
|
14
14
|
PROJECT_TYPES_DIRECTORY = File.join(File.dirname(__FILE__), '..', 'externals','project_types')
|
15
15
|
|
16
16
|
# Full commands operate on the main project as well as the externals
|
@@ -49,6 +49,11 @@ module Externals
|
|
49
49
|
feature offered by the SCM of the main project. If the SCM
|
50
50
|
type is not obvious from the repository URL, use the --scm,
|
51
51
|
--git, or --svn flags."],
|
52
|
+
[:freeze, "ext freeze project [REVISION]", %{
|
53
|
+
Locks a subproject into a specific revision/branch. If no
|
54
|
+
revision is supplied, the current revision/branch of the
|
55
|
+
project will be used. You can specify the project by name
|
56
|
+
or path.}],
|
52
57
|
[:init, "Creates a .externals file containing only [main]
|
53
58
|
It will try to determine the SCM used by the main project,
|
54
59
|
as well as the project type. You don't have to specify
|
@@ -184,13 +189,13 @@ module Externals
|
|
184
189
|
new(main_options).send(command, args, sub_options)
|
185
190
|
end
|
186
191
|
end
|
187
|
-
|
192
|
+
|
188
193
|
def self.externals_file_obsolete?
|
189
194
|
return false if !File.exists?('.externals')
|
190
|
-
|
195
|
+
|
191
196
|
open('.externals', 'r') do |f|
|
192
197
|
f.read =~ /^\s*\[git\]\s*$|^\s*\[main\]\s*$|^\s*\[svn\]\s*$/
|
193
|
-
end
|
198
|
+
end
|
194
199
|
end
|
195
200
|
|
196
201
|
def print_commands(commands)
|
@@ -241,6 +246,17 @@ module Externals
|
|
241
246
|
p
|
242
247
|
end
|
243
248
|
|
249
|
+
def subproject_by_name_or_path name
|
250
|
+
name = name.strip
|
251
|
+
project = subprojects.detect {|p| p.path.strip == name}
|
252
|
+
project ||= subprojects.detect do |p|
|
253
|
+
File.split(p.path).last.strip == name
|
254
|
+
end
|
255
|
+
project ||= subprojects.detect do |p|
|
256
|
+
p.name == name
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
244
260
|
def subprojects
|
245
261
|
s = []
|
246
262
|
projects.each do |project|
|
@@ -248,7 +264,7 @@ module Externals
|
|
248
264
|
end
|
249
265
|
s
|
250
266
|
end
|
251
|
-
|
267
|
+
|
252
268
|
def main_project
|
253
269
|
projects.detect {|p| p.main_project?}
|
254
270
|
end
|
@@ -275,12 +291,12 @@ module Externals
|
|
275
291
|
|
276
292
|
if options[:upgrade_externals_file]
|
277
293
|
type ||= options[:type]
|
278
|
-
|
294
|
+
|
279
295
|
|
280
296
|
if type
|
281
297
|
install_project_type type
|
282
298
|
else
|
283
|
-
|
299
|
+
|
284
300
|
possible_project_types = self.class.project_types.select do |project_type|
|
285
301
|
self.class.project_type_detector(project_type).detected?
|
286
302
|
end
|
@@ -378,6 +394,31 @@ Please use
|
|
378
394
|
end
|
379
395
|
end
|
380
396
|
|
397
|
+
def freeze args, options
|
398
|
+
project = subproject_by_name_or_path(args[0])
|
399
|
+
|
400
|
+
raise "No such project named #{args[0]}" unless project
|
401
|
+
|
402
|
+
revision = args[1] || project.current_revision
|
403
|
+
|
404
|
+
branch = if project.freeze_involves_branch?
|
405
|
+
project.current_branch
|
406
|
+
end
|
407
|
+
|
408
|
+
section = configuration[project.path]
|
409
|
+
if section[:branch]
|
410
|
+
if branch
|
411
|
+
section[:branch] = branch
|
412
|
+
else
|
413
|
+
section.rm_setting :branch
|
414
|
+
end
|
415
|
+
end
|
416
|
+
section[:revision] = revision
|
417
|
+
configuration.write '.externals'
|
418
|
+
|
419
|
+
subproject_by_name_or_path(args[0]).up
|
420
|
+
end
|
421
|
+
|
381
422
|
def install args, options
|
382
423
|
init args, options unless File.exists? '.externals'
|
383
424
|
repository = args[0]
|
@@ -396,16 +437,16 @@ that you are installing. Use an option to specify it
|
|
396
437
|
(such as --git or --svn)"
|
397
438
|
end
|
398
439
|
|
399
|
-
project = self.class.project_class(scm).new(:repository => repository,
|
440
|
+
project = self.class.project_class(scm).new(:repository => repository,
|
400
441
|
:path => path || path_calculator.new, :scm => scm)
|
401
442
|
path = project.path
|
402
|
-
|
443
|
+
|
403
444
|
raise "no path" unless path
|
404
|
-
|
445
|
+
|
405
446
|
raise "already exists" if configuration[path]
|
406
|
-
|
447
|
+
|
407
448
|
project.branch = options[:branch] if options[:branch]
|
408
|
-
|
449
|
+
|
409
450
|
attributes = project.attributes.dup
|
410
451
|
attributes.delete(:path)
|
411
452
|
configuration[path] = project.attributes
|
@@ -613,7 +654,7 @@ Please use the --type option to tell ext which to use."
|
|
613
654
|
config = Configuration::Configuration.new_empty
|
614
655
|
|
615
656
|
raise ".externals already exists" if File.exists?('.externals')
|
616
|
-
|
657
|
+
|
617
658
|
config.add_empty_section '.'
|
618
659
|
|
619
660
|
config['.'][:scm] = scm
|
data/lib/externals/project.rb
CHANGED
@@ -14,9 +14,9 @@ module Externals
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
|
17
|
+
VALID_ATTRIB = [:name, :path, :repository, :branch, :type, :scm, :revision].map(&:to_s)
|
18
18
|
|
19
|
-
attr_attr_accessor
|
19
|
+
attr_attr_accessor VALID_ATTRIB
|
20
20
|
def attributes
|
21
21
|
@attributes ||= {}
|
22
22
|
end
|
@@ -26,6 +26,10 @@ module Externals
|
|
26
26
|
def main_project?
|
27
27
|
path == '.'
|
28
28
|
end
|
29
|
+
|
30
|
+
def freeze_involves_branch?
|
31
|
+
true
|
32
|
+
end
|
29
33
|
|
30
34
|
def self.scm
|
31
35
|
raise "subclass responsibility"
|
@@ -49,10 +53,10 @@ module Externals
|
|
49
53
|
new_hash
|
50
54
|
end
|
51
55
|
|
52
|
-
|
56
|
+
inVALID_ATTRIB = hash.keys - VALID_ATTRIB
|
53
57
|
|
54
|
-
if !
|
55
|
-
raise "invalid attribute(s): #{
|
58
|
+
if !inVALID_ATTRIB.empty?
|
59
|
+
raise "invalid attribute(s): #{inVALID_ATTRIB.join(', ')}"
|
56
60
|
end
|
57
61
|
|
58
62
|
path = hash.delete('path')
|
@@ -1,10 +1,13 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'project')
|
2
|
+
|
3
|
+
|
1
4
|
module Externals
|
2
5
|
class GitProject < Project
|
3
|
-
|
6
|
+
|
4
7
|
def default_branch
|
5
8
|
'master'
|
6
9
|
end
|
7
|
-
|
10
|
+
|
8
11
|
def co *args
|
9
12
|
puts "path is #{path} repository is #{repository}"
|
10
13
|
if path != '.'
|
@@ -18,11 +21,22 @@ module Externals
|
|
18
21
|
|
19
22
|
puts(gitclonecmd = "git clone \"#{repository}\" #{dest}")
|
20
23
|
puts `#{gitclonecmd}`
|
24
|
+
|
25
|
+
change_to_branch_revision
|
26
|
+
end
|
27
|
+
|
28
|
+
def change_to_branch_revision
|
21
29
|
if branch
|
22
30
|
Dir.chdir path do
|
23
31
|
puts `git checkout --track -b #{branch} origin/#{branch}`
|
24
32
|
end
|
25
33
|
end
|
34
|
+
|
35
|
+
if revision
|
36
|
+
Dir.chdir path do
|
37
|
+
puts `git checkout #{revision}`
|
38
|
+
end
|
39
|
+
end
|
26
40
|
end
|
27
41
|
|
28
42
|
def ex *args
|
@@ -40,15 +54,18 @@ module Externals
|
|
40
54
|
puts(gitclonecmd = "git clone --depth 1 \"#{repository}\" #{dest}")
|
41
55
|
|
42
56
|
puts `#{gitclonecmd}`
|
43
|
-
|
44
|
-
|
45
|
-
end
|
57
|
+
|
58
|
+
change_to_branch_revision
|
46
59
|
end
|
47
60
|
|
48
61
|
def up *args
|
49
|
-
|
50
|
-
|
51
|
-
|
62
|
+
if revision
|
63
|
+
change_to_branch_revision
|
64
|
+
else
|
65
|
+
puts "updating #{path}:"
|
66
|
+
Dir.chdir path do
|
67
|
+
puts `git pull`
|
68
|
+
end
|
52
69
|
end
|
53
70
|
end
|
54
71
|
|
@@ -81,8 +98,6 @@ module Externals
|
|
81
98
|
puts `git add .`
|
82
99
|
end
|
83
100
|
|
84
|
-
|
85
|
-
protected
|
86
101
|
def ignore_contains? path
|
87
102
|
text = ignore_text
|
88
103
|
text.split(/\n/).detect {|r| r.strip == path.strip}
|
@@ -100,7 +115,7 @@ module Externals
|
|
100
115
|
def append_ignore path
|
101
116
|
rows = ignore_text || ''
|
102
117
|
return if rows.index path.strip
|
103
|
-
|
118
|
+
|
104
119
|
rows = rows.split(/\n/)
|
105
120
|
rows << path.strip
|
106
121
|
|
@@ -112,11 +127,27 @@ module Externals
|
|
112
127
|
end
|
113
128
|
end
|
114
129
|
|
130
|
+
def current_revision
|
131
|
+
Dir.chdir path do
|
132
|
+
if `git show HEAD` =~ /^\s*commit\s*([0-9a-fA-F]*)\s*$/i
|
133
|
+
$1
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def current_branch
|
139
|
+
Dir.chdir path do
|
140
|
+
if `git branch -a` =~ /^\s*\*\s*([^\s]*)\s*$/
|
141
|
+
$1
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
115
146
|
def extract_name s
|
116
147
|
if s =~ /\/([\w_-]+)(?:\.git)?$/
|
117
148
|
$1
|
118
149
|
end
|
119
150
|
end
|
120
|
-
|
151
|
+
|
121
152
|
end
|
122
153
|
end
|
@@ -1,30 +1,52 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'project')
|
2
|
+
|
1
3
|
module Externals
|
2
4
|
class SvnProject < Project
|
3
|
-
|
5
|
+
|
4
6
|
def default_branch
|
5
7
|
nil
|
6
8
|
end
|
7
|
-
|
9
|
+
|
8
10
|
def co *args
|
9
11
|
(rmdircmd = "rmdir #{path}")
|
10
12
|
|
11
13
|
`#{rmdircmd}` if File.exists? path
|
12
14
|
puts(svncocmd = "svn co #{repository} #{path}")
|
13
15
|
puts `#{svncocmd}`
|
16
|
+
|
17
|
+
change_to_revision
|
18
|
+
end
|
19
|
+
|
20
|
+
def change_to_revision
|
21
|
+
if revision
|
22
|
+
Dir.chdir path do
|
23
|
+
puts `svn up -r #{revision}`
|
24
|
+
end
|
25
|
+
end
|
14
26
|
end
|
15
27
|
|
16
28
|
def ex *args
|
17
29
|
(rmdircmd = "rmdir #{path}")
|
18
30
|
|
31
|
+
url = repository
|
32
|
+
|
33
|
+
if revision
|
34
|
+
url += "@#{revision}"
|
35
|
+
end
|
36
|
+
|
19
37
|
`#{rmdircmd}` if File.exists? path
|
20
38
|
puts(svncocmd = "svn export #{repository} #{path}")
|
21
39
|
puts `#{svncocmd}`
|
22
40
|
end
|
23
41
|
|
24
42
|
def up *args
|
25
|
-
|
26
|
-
|
27
|
-
|
43
|
+
if revision
|
44
|
+
change_to_revision
|
45
|
+
else
|
46
|
+
puts "updating #{path}:"
|
47
|
+
Dir.chdir path do
|
48
|
+
puts `svn up .`
|
49
|
+
end
|
28
50
|
end
|
29
51
|
end
|
30
52
|
|
@@ -69,8 +91,6 @@ module Externals
|
|
69
91
|
end
|
70
92
|
end
|
71
93
|
|
72
|
-
|
73
|
-
protected
|
74
94
|
def ignore_contains? path
|
75
95
|
ignore_text(path) =~ Regexp.new("^\\s*#{File.basename(path)}\\s*$")
|
76
96
|
end
|
@@ -99,5 +119,18 @@ module Externals
|
|
99
119
|
end
|
100
120
|
ignore_text
|
101
121
|
end
|
122
|
+
|
123
|
+
def current_revision
|
124
|
+
Dir.chdir path do
|
125
|
+
if `svn info` =~ /Revision:\s*(\d+)\s*$/
|
126
|
+
$1
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def freeze_involves_branch?
|
132
|
+
false
|
133
|
+
end
|
134
|
+
|
102
135
|
end
|
103
136
|
end
|
data/lib/externals/test_case.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'test/unit'
|
2
2
|
|
3
3
|
module Externals
|
4
|
-
|
4
|
+
TestCase = Test::Unit::TestCase
|
5
|
+
module ExtTestCase
|
5
6
|
protected
|
6
|
-
|
7
|
+
|
7
8
|
def initialize_test_git_repository
|
8
9
|
scm = 'git'
|
9
10
|
Dir.chdir(File.join(File.dirname(__FILE__), '..', '..', 'test')) do
|
@@ -17,21 +18,21 @@ module Externals
|
|
17
18
|
Line 2
|
18
19
|
Line 3"
|
19
20
|
end
|
20
|
-
|
21
|
+
|
21
22
|
`git add .`
|
22
23
|
`git commit -m "added readme.txt"`
|
23
|
-
|
24
|
+
|
24
25
|
open 'readme.txt', 'a' do |f|
|
25
26
|
f.write "line 4"
|
26
27
|
end
|
27
|
-
|
28
|
+
|
28
29
|
`git add .`
|
29
30
|
`git commit -m "added a line to readme.txt"`
|
30
31
|
end
|
31
32
|
end
|
32
33
|
end
|
33
34
|
end
|
34
|
-
|
35
|
+
|
35
36
|
def initialize_test_svn_repository
|
36
37
|
scm = 'svn'
|
37
38
|
Dir.chdir(File.join(File.dirname(__FILE__), '..', '..', 'test')) do
|
@@ -41,27 +42,27 @@ module Externals
|
|
41
42
|
end
|
42
43
|
end
|
43
44
|
end
|
44
|
-
|
45
|
-
def destroy_test_repository scm
|
45
|
+
|
46
|
+
def destroy_test_repository scm
|
46
47
|
puts(rmcmd = "rm -rf #{repository_dir(scm)}")
|
47
48
|
puts `#{rmcmd}`
|
48
49
|
end
|
49
|
-
|
50
|
+
|
50
51
|
def repository_dir scm = nil
|
51
52
|
if scm.nil?
|
52
|
-
File.join(File.dirname(__FILE__), '..', '..', 'test', 'repositories')
|
53
|
+
File.join(File.dirname(__FILE__), '..', '..', 'test', 'repositories')
|
53
54
|
else
|
54
55
|
File.expand_path(File.join(repository_dir, "#{scm}repo"))
|
55
56
|
end
|
56
57
|
end
|
57
|
-
|
58
|
+
|
58
59
|
def create_test_modules_repository scm
|
59
60
|
Dir.chdir(File.join(File.dirname(__FILE__), '..', '..', 'test')) do
|
60
61
|
`mkdir repositories` unless File.exists? 'repositories'
|
61
62
|
Dir.chdir 'repositories' do
|
62
63
|
puts `svnadmin create #{scm}modulesrepo`
|
63
64
|
end
|
64
|
-
|
65
|
+
|
65
66
|
cmd = "svn checkout \"file:///#{File.expand_path(File.join('repositories', "#{scm}modulesrepo"))}\""
|
66
67
|
puts "about to run #{cmd}"
|
67
68
|
puts `#{cmd}`
|
@@ -70,7 +71,7 @@ module Externals
|
|
70
71
|
open("modules.txt", "w") do |f|
|
71
72
|
f.write "line1 of modules.txt\n"
|
72
73
|
end
|
73
|
-
|
74
|
+
|
74
75
|
SvnProject.add_all
|
75
76
|
puts `svn commit -m "created modules.txt"`
|
76
77
|
end
|
@@ -78,23 +79,23 @@ module Externals
|
|
78
79
|
`rm -rf #{scm}modulesrepo`
|
79
80
|
end
|
80
81
|
end
|
81
|
-
|
82
|
-
def destroy_test_modules_repository scm
|
82
|
+
|
83
|
+
def destroy_test_modules_repository scm
|
83
84
|
puts(rmcmd = "rm -rf #{modules_repository_dir(scm)}")
|
84
85
|
puts `#{rmcmd}`
|
85
86
|
puts(rmcmd = "rm -rf #{modules_repository_dir(scm)}")
|
86
87
|
puts `#{rmcmd}`
|
87
88
|
end
|
88
|
-
|
89
|
+
|
89
90
|
def modules_repository_dir scm = nil
|
90
91
|
if scm.nil?
|
91
|
-
File.join(File.dirname(__FILE__), '..', '..', 'test', 'repositories')
|
92
|
+
File.join(File.dirname(__FILE__), '..', '..', 'test', 'repositories')
|
92
93
|
else
|
93
94
|
File.expand_path(File.join(repository_dir, "#{scm}modulesrepo"))
|
94
95
|
end
|
95
96
|
end
|
96
|
-
|
97
|
-
|
97
|
+
|
98
|
+
|
98
99
|
def create_rails_application
|
99
100
|
Dir.mkdir applications_dir unless File.exists?(applications_dir)
|
100
101
|
Dir.chdir applications_dir do
|
@@ -105,32 +106,27 @@ module Externals
|
|
105
106
|
end
|
106
107
|
end
|
107
108
|
end
|
108
|
-
|
109
|
+
|
109
110
|
def windows?
|
110
111
|
ENV['OS'] =~ /^Win/i
|
111
112
|
end
|
112
|
-
|
113
|
+
|
113
114
|
def destroy_rails_application
|
114
115
|
Dir.chdir applications_dir do
|
115
116
|
`rm -rf rails_app`
|
116
117
|
end
|
117
118
|
end
|
118
|
-
|
119
|
+
|
119
120
|
def root_dir
|
120
121
|
File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
|
121
122
|
end
|
122
|
-
|
123
|
+
|
123
124
|
def applications_dir
|
124
125
|
File.join(root_dir, 'test', 'applications')
|
125
126
|
end
|
126
|
-
|
127
|
+
|
127
128
|
def rails_application_dir
|
128
129
|
File.join(applications_dir, 'rails_app')
|
129
130
|
end
|
130
|
-
|
131
|
-
public
|
132
|
-
def test_true
|
133
|
-
assert true
|
134
|
-
end
|
135
131
|
end
|
136
132
|
end
|
data/test/test_checkout_git.rb
CHANGED
@@ -4,6 +4,9 @@ require 'externals/ext'
|
|
4
4
|
|
5
5
|
module Externals
|
6
6
|
class TestCheckoutWithSubprojectsGit < TestCase
|
7
|
+
include ExtTestCase
|
8
|
+
|
9
|
+
|
7
10
|
def setup
|
8
11
|
destroy_rails_application
|
9
12
|
create_rails_application
|
@@ -24,11 +27,11 @@ module Externals
|
|
24
27
|
`git init`
|
25
28
|
Ext.run "init"
|
26
29
|
raise " could not create .externals" unless File.exists? '.externals'
|
27
|
-
Ext.run "install", "
|
30
|
+
Ext.run "install", File.join(root_dir, 'test', 'cleanreps', "acts_as_list.git")
|
28
31
|
|
29
32
|
#install a couple svn managed subprojects
|
30
33
|
%w(foreign_key_migrations redhillonrails_core).each do |proj|
|
31
|
-
Ext.run "install", "--svn",
|
34
|
+
Ext.run "install", "--svn", 'file:///' + File.join(root_dir, 'test', 'cleanreps', proj)
|
32
35
|
end
|
33
36
|
|
34
37
|
GitProject.add_all
|
@@ -4,6 +4,8 @@ require 'externals/ext'
|
|
4
4
|
|
5
5
|
module Externals
|
6
6
|
class TestCheckoutWithSubprojectsSvn < TestCase
|
7
|
+
include ExtTestCase
|
8
|
+
|
7
9
|
def setup
|
8
10
|
destroy_rails_application
|
9
11
|
create_rails_application
|
@@ -35,16 +37,16 @@ module Externals
|
|
35
37
|
Ext.run "init"
|
36
38
|
raise " could not create .externals" unless File.exists? '.externals'
|
37
39
|
%w(rails acts_as_list).each do |proj|
|
38
|
-
Ext.run "install", "
|
40
|
+
Ext.run "install", File.join(root_dir, 'test', 'cleanreps', "#{proj}.git")
|
39
41
|
end
|
40
42
|
|
41
43
|
#install a couple svn managed subprojects
|
42
44
|
%w(foreign_key_migrations redhillonrails_core).each do |proj|
|
43
|
-
Ext.run "install", "--svn", "
|
45
|
+
Ext.run "install", "--svn", "file:///#{File.join(root_dir, 'test', 'cleanreps', proj)}"
|
44
46
|
end
|
45
47
|
|
46
48
|
#install project with a branch
|
47
|
-
Ext.run "install",
|
49
|
+
Ext.run "install", File.join(root_dir, 'test', 'cleanreps', 'engines.git'), "-b", "edge"
|
48
50
|
|
49
51
|
#install project with a non-default path
|
50
52
|
Ext.run "install", "--svn", "file:///#{modules_repository_dir('svn')}", "modules"
|
@@ -159,7 +161,9 @@ module Externals
|
|
159
161
|
assert(ignore_text =~ /^rails$/)
|
160
162
|
|
161
163
|
Dir.chdir File.join('vendor', 'rails') do
|
162
|
-
|
164
|
+
#can't check this if it's local. It seems --depth 1 is ignored for
|
165
|
+
#repositories on the local machine.
|
166
|
+
#assert `git show 92f944818eece9fe4bc62ffb39accdb71ebc32be` !~ /azimux/
|
163
167
|
end
|
164
168
|
|
165
169
|
%w(foreign_key_migrations redhillonrails_core acts_as_list).each do |proj|
|
@@ -0,0 +1,108 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), '..', 'lib') if $0 == __FILE__
|
2
|
+
require 'externals/test_case'
|
3
|
+
require 'externals/ext'
|
4
|
+
|
5
|
+
module Externals
|
6
|
+
class TestFreezeToRevision < TestCase
|
7
|
+
include ExtTestCase
|
8
|
+
|
9
|
+
def setup
|
10
|
+
destroy_rails_application
|
11
|
+
create_rails_application
|
12
|
+
|
13
|
+
Dir.chdir File.join(root_dir, 'test') do
|
14
|
+
parts = 'workdir/checkout/rails_app/vendor/plugins/foreign_key_migrations/lib/red_hill_consulting/foreign_key_migrations/active_record/connection_adapters/.svn/text-base/table_definition.rb.svn-base'.split('/')
|
15
|
+
if File.exists? File.join(*parts)
|
16
|
+
Dir.chdir File.join(*(parts[0..-2])) do
|
17
|
+
File.delete parts[-1]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
`rm -rf workdir`
|
21
|
+
`mkdir workdir`
|
22
|
+
`cp -r #{rails_application_dir} workdir`
|
23
|
+
Dir.chdir File.join('workdir','rails_app') do
|
24
|
+
Ext.run "touch_emptydirs"
|
25
|
+
|
26
|
+
`git init`
|
27
|
+
Ext.run "init"
|
28
|
+
raise " could not create .externals" unless File.exists? '.externals'
|
29
|
+
Ext.run "install", File.join(root_dir, 'test', 'cleanreps', "acts_as_list.git")
|
30
|
+
|
31
|
+
#install a couple svn managed subprojects
|
32
|
+
%w(foreign_key_migrations redhillonrails_core).each do |proj|
|
33
|
+
Ext.run "install", "--svn", 'file:///' + File.join(root_dir, 'test', 'cleanreps', proj)
|
34
|
+
end
|
35
|
+
|
36
|
+
Ext.run "freeze", "foreign_key_migrations", "2"
|
37
|
+
Ext.run "freeze", "acts_as_list", "9baff190a52c05cc542bfcaa7f77a91ce669f2f8"
|
38
|
+
|
39
|
+
GitProject.add_all
|
40
|
+
`git commit -m "created empty rails app with some subprojects"`
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def teardown
|
46
|
+
destroy_rails_application
|
47
|
+
|
48
|
+
Dir.chdir File.join(root_dir, 'test') do
|
49
|
+
parts = 'workdir/checkout/rails_app/vendor/plugins/foreign_key_migrations/lib/red_hill_consulting/foreign_key_migrations/active_record/connection_adapters/.svn/text-base/table_definition.rb.svn-base'.split('/')
|
50
|
+
if File.exists? File.join(*parts)
|
51
|
+
Dir.chdir File.join(*(parts[0..-2])) do
|
52
|
+
File.delete parts[-1]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
`rm -rf workdir`
|
56
|
+
end
|
57
|
+
# Dir.chdir File.join(root_dir, 'test') do
|
58
|
+
# `rm -rf workdir`
|
59
|
+
# end
|
60
|
+
#XXX
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
def test_freeze_to_revision
|
65
|
+
Dir.chdir File.join(root_dir, 'test') do
|
66
|
+
Dir.chdir 'workdir' do
|
67
|
+
`mkdir checkout`
|
68
|
+
Dir.chdir 'checkout' do
|
69
|
+
source = File.join(root_dir, 'test', 'workdir', 'rails_app')
|
70
|
+
puts "About to checkout #{ source}"
|
71
|
+
Ext.run "checkout", "--git", source
|
72
|
+
|
73
|
+
Dir.chdir 'rails_app' do
|
74
|
+
assert File.exists?('.git')
|
75
|
+
|
76
|
+
assert File.exists?('.gitignore')
|
77
|
+
|
78
|
+
%w(foreign_key_migrations redhillonrails_core acts_as_list).each do |proj|
|
79
|
+
assert(File.read('.gitignore') =~ /^vendor[\/\\]plugins[\/\\]#{proj}$/)
|
80
|
+
end
|
81
|
+
|
82
|
+
Dir.chdir File.join('vendor', 'plugins') do
|
83
|
+
Dir.chdir 'acts_as_list' do
|
84
|
+
%w(8771a632dc26a7782800347993869c964133ea29
|
85
|
+
27a941c80ccaa8afeb9bfecb84c0ff098d8ba962
|
86
|
+
9baff190a52c05cc542bfcaa7f77a91ce669f2f8
|
87
|
+
).each do |hash|
|
88
|
+
assert `git show #{hash}` =~ /^commit\s*#{hash}$/i
|
89
|
+
end
|
90
|
+
assert `git show HEAD` !~ /^\s*commit\s*8771a632dc26a7782800347993869c964133ea29\s*$/i
|
91
|
+
assert `git show HEAD` =~ /^\s*commit\s*9baff190a52c05cc542bfcaa7f77a91ce669f2f8\s*$/i
|
92
|
+
end
|
93
|
+
|
94
|
+
Dir.chdir 'foreign_key_migrations' do
|
95
|
+
assert `svn info` =~ /^Revision:\s*2\s*$/i
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
%w(foreign_key_migrations redhillonrails_core acts_as_list).each do |proj|
|
100
|
+
assert File.exists?(File.join('vendor', 'plugins',proj, 'lib'))
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/test/test_init_git.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ext
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miles Georgi
|
@@ -9,11 +9,11 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-10-17 00:00:00 -07:00
|
13
13
|
default_executable: ext
|
14
14
|
dependencies: []
|
15
15
|
|
16
|
-
description: "Provides an SCM agnostic way to manage subprojects with a workflow similar
|
16
|
+
description: "Provides an SCM agnostic way to manage subprojects with a workflow similar to the scm:externals feature of subversion. It's particularly useful for rails projects that have some plugins managed by svn and some managed by git. For example, \"ext install git://github.com/rails/rails.git\" from within a rails application directory will realize that this belongs in the vendor/rails folder. It will also realize that this URL is a git repository and clone it into that folder. It will also add the vendor/rails folder to the ignore feature for the SCM of the main project. Let's say that the main project is being managed by subversion. In that case it adds \"rails\" to the svn:ignore property of the vendor folder. It also adds the URL to the .externals file so that when this project is checked out via \"ext checkout\" it knows where to fetch the subprojects. There are several other useful commands, such as init, touch_emptydirs, add_all, export, status. There's a tutorial at http://nopugs.com/ext-tutorial The reason I made this project is that I was frustrated by two things: 1. In my opinion, the workflow for svn:externals is far superior to git-submodule. 2. Even if git-submodule was as useful as svn:externals, I would still like a uniform way to fetch all of the subprojects regardless of the SCM used to manage the main project."
|
17
17
|
email: azimux@gmail.com
|
18
18
|
executables:
|
19
19
|
- ext
|
@@ -64,11 +64,12 @@ rubyforge_project: ext
|
|
64
64
|
rubygems_version: 1.2.0
|
65
65
|
signing_key:
|
66
66
|
specification_version: 2
|
67
|
-
summary: Provides an SCM agnostic way to manage subprojects with a workflow similar
|
67
|
+
summary: Provides an SCM agnostic way to manage subprojects with a workflow similar to the svn:externals feature of subversion. It's particularly useful for rails projects that have some plugins managed by svn and some managed by git.
|
68
68
|
test_files:
|
69
69
|
- test/test_checkout_git.rb
|
70
70
|
- test/test_checkout_with_subprojects_git.rb
|
71
71
|
- test/test_checkout_with_subprojects_svn.rb
|
72
|
+
- test/test_freeze_to_revision.rb
|
72
73
|
- test/test_init_git.rb
|
73
74
|
- test/test_rails_detection.rb
|
74
75
|
- test/test_string_extensions.rb
|