ext 0.0.10 → 0.1.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.
- data/README +11 -10
- data/Rakefile +2 -2
- data/lib/{ext → extensions}/string.rb +0 -0
- data/lib/{ext → extensions}/symbol.rb +0 -0
- data/lib/externals/configuration/configuration.rb +112 -77
- data/lib/externals/configuration/old_configuration.rb +166 -0
- data/lib/externals/ext.rb +181 -48
- data/lib/externals/old_project.rb +114 -0
- data/lib/externals/old_scms/old_git_project.rb +116 -0
- data/lib/externals/old_scms/old_svn_project.rb +98 -0
- data/lib/externals/project.rb +59 -52
- data/lib/externals/project_types/rails.rb +18 -6
- data/lib/externals/scms/git_project.rb +6 -0
- data/lib/externals/scms/svn_project.rb +5 -0
- data/test/test_checkout_git.rb +4 -0
- data/test/test_checkout_with_subprojects_git.rb +10 -1
- data/test/test_checkout_with_subprojects_svn.rb +26 -12
- data/test/test_upgrade_externals_file.rb +84 -0
- metadata +9 -4
data/README
CHANGED
@@ -17,12 +17,14 @@ short form. The longer form applies the action to the main project. The short
|
|
17
17
|
forms apply the action to all sub projects.
|
18
18
|
|
19
19
|
The commands and usage are as follows (from 'ext help'):
|
20
|
+
There's a tutorial available at http://nopugs.com/ext-tutorial
|
20
21
|
|
21
|
-
ext [OPTIONS] <command> [repository[
|
22
|
+
ext [OPTIONS] <command> [repository] [-b <branch>] [path]
|
22
23
|
-g, --git same as '--scm git' Uses git to checkout/export the main project
|
23
24
|
-s, --svn, --subversion same as '--scm svn' Uses subversion to checkout/export the main project
|
24
25
|
-t, --type TYPE The type of project the main project is. For example, 'rails'.
|
25
26
|
--scm SCM The SCM used to manage the main project. For example, '--scm svn'.
|
27
|
+
-b, --branch BRANCH The branch you want the subproject to checkout when doing 'ext install'
|
26
28
|
-w, --workdir DIR The working directory to execute commands from. Use this if for some reason you
|
27
29
|
cannot execute ext from the main project's directory (or if it's just inconvenient, such as in a script
|
28
30
|
or in a Capistrano task)
|
@@ -32,7 +34,7 @@ ext [OPTIONS] <command> [repository[:branch]] [path]
|
|
32
34
|
|
33
35
|
|
34
36
|
Commands that apply to the main project or the .externals file:
|
35
|
-
update_ignore, install, init, touch_emptydirs, help
|
37
|
+
update_ignore, install, init, touch_emptydirs, help, upgrade_externals_file
|
36
38
|
|
37
39
|
update_ignore Adds all paths to subprojects that are
|
38
40
|
registered in .externals to the ignore feature of the
|
@@ -40,12 +42,12 @@ update_ignore Adds all paths to subprojects that are
|
|
40
42
|
and so you probably only will run this if you are manually
|
41
43
|
maintaining .externals
|
42
44
|
|
43
|
-
install Usage: ext install <repository[
|
45
|
+
install Usage: ext install <repository> [-b <branch>] [path]
|
44
46
|
Registers <repository> in .externals under the appropriate
|
45
47
|
SCM. Checks out the project, and also adds it to the ignore
|
46
|
-
feature offered by the SCM of the main project. If the SCM
|
47
|
-
is not obvious from the repository URL, use the --scm,
|
48
|
-
or --svn flags.
|
48
|
+
feature offered by the SCM of the main project. If the SCM
|
49
|
+
type is not obvious from the repository URL, use the --scm,
|
50
|
+
--git, or --svn flags.
|
49
51
|
|
50
52
|
init Creates a .externals file containing only [main]
|
51
53
|
It will try to determine the SCM used by the main project,
|
@@ -61,6 +63,9 @@ touch_emptydirs Recurses through all directories from the
|
|
61
63
|
|
62
64
|
help You probably just ran this command just now.
|
63
65
|
|
66
|
+
upgrade_externals_fileConverts the old format that stored
|
67
|
+
as [main][svn][git] to [<path1>][<path2>]...
|
68
|
+
|
64
69
|
|
65
70
|
|
66
71
|
Commands that apply to the main project and all subprojects:
|
@@ -93,14 +98,10 @@ co, ex, st, up
|
|
93
98
|
|
94
99
|
co Like checkout, but skips the main project and
|
95
100
|
only checks out subprojects.
|
96
|
-
|
97
101
|
ex Like export, but skips the main project.
|
98
|
-
|
99
102
|
st Like status, but skips the main project.
|
100
|
-
|
101
103
|
up Like update, but skips the main project.
|
102
104
|
|
103
|
-
|
104
105
|
The externals project is copyright 2008 by Miles Georgi, nopugs.com, azimux.com
|
105
106
|
and is released under the MIT license.
|
106
107
|
|
data/Rakefile
CHANGED
@@ -6,12 +6,12 @@ require 'rake/gempackagetask'
|
|
6
6
|
Rake::TestTask.new('test') do |task|
|
7
7
|
task.libs = [File.expand_path('lib'),File.expand_path('test')]
|
8
8
|
task.pattern = './test/test_*.rb'
|
9
|
-
task.warning = true
|
9
|
+
#task.warning = true
|
10
10
|
end
|
11
11
|
|
12
12
|
gem_specification = Gem::Specification.new do |specification|
|
13
13
|
specification.name = 'ext'
|
14
|
-
specification.version = '0.0
|
14
|
+
specification.version = '0.1.0'
|
15
15
|
specification.platform = Gem::Platform::RUBY
|
16
16
|
specification.rubyforge_project = 'ext'
|
17
17
|
|
File without changes
|
File without changes
|
@@ -1,78 +1,104 @@
|
|
1
1
|
module Externals
|
2
2
|
module Configuration
|
3
|
-
|
4
|
-
|
3
|
+
SECTION_TITLE_REGEX_NO_GROUPS = /^\s*\[(?:[^\]]*)\]\s*$/
|
4
|
+
SECTION_TITLE_REGEX = /^\s*\[([^\]]*)\]\s*$/
|
5
5
|
|
6
6
|
|
7
7
|
class Section
|
8
|
-
attr_accessor :title_string, :body_string, :title, :rows
|
8
|
+
attr_accessor :title_string, :body_string, :title, :rows
|
9
9
|
|
10
|
-
def
|
11
|
-
title == 'main'
|
12
|
-
end
|
13
|
-
|
14
|
-
def initialize title_string, body_string, scm = nil
|
10
|
+
def initialize title_string, body_string
|
15
11
|
self.title_string = title_string
|
16
12
|
self.body_string = body_string
|
17
|
-
self.scm = scm
|
18
13
|
|
19
14
|
self.title = SECTION_TITLE_REGEX.match(title_string)[1]
|
20
|
-
|
21
|
-
self.scm ||= self.title
|
22
15
|
|
23
16
|
raise "Invalid section title: #{title_string}" unless title
|
24
17
|
|
25
|
-
self.rows = body_string.split(/\n/)
|
18
|
+
self.rows = body_string.strip.split(/\n/)
|
26
19
|
end
|
27
20
|
|
28
|
-
def setting key
|
29
|
-
if !main?
|
30
|
-
raise "this isn't a section of the configuration that can contain settings"
|
31
|
-
end
|
32
21
|
|
22
|
+
SETTING_REGEX = /^\s*([\.\w_-]+)\s*=\s*([^#\n]*)(?:#[^\n]*)?$/
|
23
|
+
SET_SETTING_REGEX = /^(\s*(?:[\.\w_-]+)\s*=\s*)(?:[^#\n]*)(#[^\n]*)?$/
|
24
|
+
|
25
|
+
def attributes
|
26
|
+
retval = {}
|
33
27
|
rows.each do |row|
|
34
|
-
if row =~
|
28
|
+
if row =~ SETTING_REGEX
|
29
|
+
retval[$1.strip] = $2.strip
|
30
|
+
end
|
31
|
+
end
|
32
|
+
retval
|
33
|
+
end
|
34
|
+
def setting key
|
35
|
+
rows.each do |row|
|
36
|
+
if row =~ SETTING_REGEX && key.to_s == $1
|
35
37
|
return $2.strip
|
36
38
|
end
|
37
39
|
end
|
38
40
|
nil
|
39
41
|
end
|
42
|
+
def set_setting key, value
|
43
|
+
key = key.to_s
|
44
|
+
found = nil
|
45
|
+
|
46
|
+
rows.each_with_index do |row, index|
|
47
|
+
if row =~ SETTING_REGEX && key == $1
|
48
|
+
raise "found #{key} twice!" if found
|
49
|
+
found = index
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
if found
|
54
|
+
if rows[found] !~ SET_SETTING_REGEX
|
55
|
+
raise "thought I found the row, but didn't"
|
56
|
+
end
|
57
|
+
rows[found] = "#{$1}#{value}#{$2}"
|
58
|
+
else
|
59
|
+
rows << "#{key} = #{value}"
|
60
|
+
end
|
61
|
+
value
|
62
|
+
end
|
40
63
|
|
41
64
|
def [] key
|
42
65
|
setting(key)
|
43
66
|
end
|
67
|
+
def []= key, value
|
68
|
+
set_setting(key, value)
|
69
|
+
end
|
44
70
|
|
45
71
|
|
46
|
-
def projects
|
47
|
-
return @projects if @projects
|
48
|
-
|
49
|
-
@projects = []
|
50
|
-
|
51
|
-
if main?
|
52
|
-
@projects = [Ext.project_class(self['scm']).new(".", :is_main)]
|
53
|
-
else
|
54
|
-
rows.each do |row|
|
55
|
-
if Project.project_line?(row)
|
56
|
-
@projects << Ext.project_class(title).new(row)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
@projects
|
60
|
-
end
|
61
|
-
end
|
72
|
+
# def projects
|
73
|
+
# return @projects if @projects
|
74
|
+
#
|
75
|
+
# @projects = []
|
76
|
+
#
|
77
|
+
# if main?
|
78
|
+
# @projects = [Ext.project_class(self['scm']).new(".", :is_main)]
|
79
|
+
# else
|
80
|
+
# rows.each do |row|
|
81
|
+
# if Project.project_line?(row)
|
82
|
+
# @projects << Ext.project_class(title).new(row)
|
83
|
+
# end
|
84
|
+
# end
|
85
|
+
# @projects
|
86
|
+
# end
|
87
|
+
# end
|
62
88
|
|
63
89
|
def add_row(row)
|
64
90
|
rows << row
|
65
91
|
|
66
92
|
self.body_string = body_string.chomp + "\n#{row}\n"
|
67
|
-
clear_caches
|
93
|
+
#clear_caches
|
68
94
|
end
|
69
95
|
|
70
|
-
def clear_caches
|
71
|
-
@projects = nil
|
72
|
-
end
|
96
|
+
# def clear_caches
|
97
|
+
# @projects = nil
|
98
|
+
# end
|
73
99
|
|
74
100
|
def to_s
|
75
|
-
"#{
|
101
|
+
"[#{title}]\n#{rows.join("\n")}"
|
76
102
|
end
|
77
103
|
end
|
78
104
|
|
@@ -88,33 +114,39 @@ module Externals
|
|
88
114
|
sections.detect {|section| section.title == title}
|
89
115
|
end
|
90
116
|
|
117
|
+
def []= title, hash
|
118
|
+
add_empty_section title
|
119
|
+
section = self[title]
|
120
|
+
hash.each_pair do |key,value|
|
121
|
+
section[key] = value
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
91
125
|
def add_empty_section title
|
92
126
|
raise "Section already exists" if self[title]
|
93
|
-
sections << Section.new("
|
127
|
+
sections << Section.new("[#{title.to_s}]", "")
|
94
128
|
end
|
95
|
-
|
129
|
+
|
96
130
|
def self.new_empty
|
97
131
|
new nil, true
|
98
132
|
end
|
99
133
|
|
100
|
-
def initialize
|
101
|
-
|
102
|
-
self.file_string = ''
|
103
|
-
return
|
104
|
-
end
|
105
|
-
|
106
|
-
if !externals_file && File.exists?('.externals')
|
107
|
-
open('.externals', 'r') do |f|
|
108
|
-
externals_file = f.read
|
109
|
-
end
|
110
|
-
end
|
134
|
+
def initialize file_string = nil, empty = false
|
135
|
+
self.file_string = file_string
|
111
136
|
|
112
|
-
|
137
|
+
return if empty
|
138
|
+
raise "I was given no file_string" unless file_string
|
113
139
|
|
114
|
-
|
140
|
+
# if !externals_file && File.exists?('.externals')
|
141
|
+
# open('.externals', 'r') do |f|
|
142
|
+
# externals_file = f.read
|
143
|
+
# end
|
144
|
+
# end
|
115
145
|
|
116
|
-
|
117
|
-
|
146
|
+
#externals_file ||= ""
|
147
|
+
|
148
|
+
titles = file_string.grep SECTION_TITLE_REGEX
|
149
|
+
bodies = file_string.split SECTION_TITLE_REGEX_NO_GROUPS
|
118
150
|
|
119
151
|
if titles.size > 0 && bodies.size > 0
|
120
152
|
if titles.size + 1 != bodies.size
|
@@ -129,31 +161,34 @@ module Externals
|
|
129
161
|
end
|
130
162
|
end
|
131
163
|
|
132
|
-
def projects
|
133
|
-
retval = []
|
134
|
-
sections.each do |section|
|
135
|
-
retval += section.projects
|
136
|
-
end
|
137
|
-
|
138
|
-
retval
|
139
|
-
end
|
140
|
-
|
141
|
-
def subprojects
|
142
|
-
retval = []
|
143
|
-
sections.each do |section|
|
144
|
-
retval += section.projects unless section.main?
|
145
|
-
end
|
146
|
-
|
147
|
-
retval
|
148
|
-
end
|
149
|
-
|
150
|
-
def write path = ".externals"
|
164
|
+
# def projects
|
165
|
+
# retval = []
|
166
|
+
# sections.each do |section|
|
167
|
+
# retval += section.projects
|
168
|
+
# end
|
169
|
+
#
|
170
|
+
# retval
|
171
|
+
# end
|
172
|
+
|
173
|
+
# def subprojects
|
174
|
+
# retval = []
|
175
|
+
# sections.each do |section|
|
176
|
+
# retval += section.projects unless section.main?
|
177
|
+
# end
|
178
|
+
#
|
179
|
+
# retval
|
180
|
+
# end
|
181
|
+
|
182
|
+
def write path # = ".externals"
|
183
|
+
raise "no path given" unless path
|
151
184
|
open(path, 'w') do |f|
|
152
|
-
|
153
|
-
f.write section.to_s
|
154
|
-
end
|
185
|
+
f.write to_s
|
155
186
|
end
|
156
187
|
end
|
188
|
+
|
189
|
+
def to_s
|
190
|
+
sections.map(&:to_s).join("\n\n")
|
191
|
+
end
|
157
192
|
end
|
158
193
|
end
|
159
194
|
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
module Externals
|
2
|
+
module OldConfiguration
|
3
|
+
SECTION_TITLE_REGEX = /^\s*\[(\w+)\]\s*$/
|
4
|
+
SECTION_TITLE_REGEX_NO_GROUPS = /^\s*\[(?:\w+)\]\s*$/
|
5
|
+
|
6
|
+
|
7
|
+
class Section
|
8
|
+
attr_accessor :title_string, :body_string, :title, :rows, :scm
|
9
|
+
|
10
|
+
def main?
|
11
|
+
title == 'main'
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize title_string, body_string, scm = nil
|
15
|
+
self.title_string = title_string
|
16
|
+
self.body_string = body_string
|
17
|
+
self.scm = scm
|
18
|
+
|
19
|
+
self.title = SECTION_TITLE_REGEX.match(title_string)[1]
|
20
|
+
|
21
|
+
self.scm ||= self.title
|
22
|
+
|
23
|
+
raise "Invalid section title: #{title_string}" unless title
|
24
|
+
|
25
|
+
self.rows = body_string.split(/\n/)
|
26
|
+
end
|
27
|
+
|
28
|
+
def setting key
|
29
|
+
if !main?
|
30
|
+
raise "this isn't a section of the configuration that can contain settings"
|
31
|
+
end
|
32
|
+
|
33
|
+
rows.each do |row|
|
34
|
+
if row =~ /\s*(\w+)\s*=\s*([^#\n]*)(?:#[^\n])?$/ && key.to_s == $1
|
35
|
+
return $2.strip
|
36
|
+
end
|
37
|
+
end
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def [] key
|
42
|
+
setting(key)
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def projects
|
47
|
+
return @projects if @projects
|
48
|
+
|
49
|
+
@projects = []
|
50
|
+
|
51
|
+
if main?
|
52
|
+
@projects = [Ext.old_project_class(self['scm']).new(".", :is_main)]
|
53
|
+
else
|
54
|
+
rows.each do |row|
|
55
|
+
if Project.project_line?(row)
|
56
|
+
@projects << Ext.old_project_class(title).new(row)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
@projects
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def add_row(row)
|
64
|
+
rows << row
|
65
|
+
|
66
|
+
self.body_string = body_string.chomp + "\n#{row}\n"
|
67
|
+
clear_caches
|
68
|
+
end
|
69
|
+
|
70
|
+
def clear_caches
|
71
|
+
@projects = nil
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_s
|
75
|
+
"#{title_string}#{body_string}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class Configuration
|
80
|
+
attr_accessor :file_string
|
81
|
+
|
82
|
+
def sections
|
83
|
+
@sections ||= []
|
84
|
+
end
|
85
|
+
|
86
|
+
def [] title
|
87
|
+
title = title.to_s
|
88
|
+
sections.detect {|section| section.title == title}
|
89
|
+
end
|
90
|
+
|
91
|
+
def add_empty_section title
|
92
|
+
raise "Section already exists" if self[title]
|
93
|
+
sections << Section.new("\n\n[#{title.to_s}]\n", "")
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.new_empty
|
97
|
+
new nil, true
|
98
|
+
end
|
99
|
+
|
100
|
+
def initialize externals_file = nil, empty = false
|
101
|
+
if empty
|
102
|
+
self.file_string = ''
|
103
|
+
return
|
104
|
+
end
|
105
|
+
|
106
|
+
if !externals_file && File.exists?('.externals')
|
107
|
+
open('.externals', 'r') do |f|
|
108
|
+
externals_file = f.read
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
externals_file ||= ""
|
113
|
+
|
114
|
+
self.file_string = externals_file
|
115
|
+
|
116
|
+
titles = externals_file.grep SECTION_TITLE_REGEX
|
117
|
+
bodies = externals_file.split SECTION_TITLE_REGEX_NO_GROUPS
|
118
|
+
|
119
|
+
if titles.size > 0 && bodies.size > 0
|
120
|
+
if titles.size + 1 != bodies.size
|
121
|
+
raise "bodies and sections do not match up"
|
122
|
+
end
|
123
|
+
|
124
|
+
bodies = bodies[1..(bodies.size - 1)]
|
125
|
+
|
126
|
+
(0...(bodies.size)).each do |index|
|
127
|
+
sections << Section.new(titles[index], bodies[index])
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def projects
|
133
|
+
retval = []
|
134
|
+
sections.each do |section|
|
135
|
+
retval += section.projects
|
136
|
+
end
|
137
|
+
|
138
|
+
retval
|
139
|
+
end
|
140
|
+
|
141
|
+
def subprojects
|
142
|
+
retval = []
|
143
|
+
sections.each do |section|
|
144
|
+
retval += section.projects unless section.main?
|
145
|
+
end
|
146
|
+
|
147
|
+
retval
|
148
|
+
end
|
149
|
+
|
150
|
+
def main_project
|
151
|
+
sections.each do |section|
|
152
|
+
return section.projects.first if section.main?
|
153
|
+
end
|
154
|
+
nil
|
155
|
+
end
|
156
|
+
|
157
|
+
def write path = ".externals"
|
158
|
+
open(path, 'w') do |f|
|
159
|
+
sections.each do |section|
|
160
|
+
f.write section.to_s
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|