This repository has been archived by the owner on Oct 28, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
modman-gen.rb
executable file
·201 lines (182 loc) · 5.78 KB
/
modman-gen.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#!/usr/bin/env ruby
require 'find'
$ignored_files = %w(.gitignore Gruntfile.js modman package.json README.md README)
$ignored_dirs = %w(.git)
# Finds unique directories that exist in the first path, but not the second.
#
# first - String path to a directory.
# second - String path to another directory.
#
# Examples
#
# # Given the following directory structure:
# a/
# foo/
# bar/
# baz/
# b/
# foo/
# bar/
# qux/
#
# find_unique_directories('./a', './b')
# # => ["/foo/baz"]
#
# Returns Array<String>, each item representing a path (leading directory component omitted).
def find_unique_directories(first, second)
directory_list = []
Find.find(first) do |dir|
next if dir == first
relative_dir = dir.gsub(/#{first}/, '')
Find.prune if $ignored_dirs.include? relative_dir
next unless FileTest.directory?(dir)
# test for this directory in the 'second' directory
relative_dir = dir.gsub(/#{first}/, '')
unless FileTest.directory?(second + relative_dir)
directory_list << relative_dir
Find.prune
end
end
directory_list
end
# Finds unique files that exist in the first path, but not the second. Files that exist in the 'exclude' path will be omitted.
#
# first - String path to a directory.
# exclude - Array<String> paths of directories, files contained in any of these directories will be excluded from the resulting output.
#
# Examples
#
# # Given the following directory/file structure:
# a/
# bar/
# fileone
# filetwo
# foo/
# filethree
# b/
# bar/
# fileone
# qux/
# filefour
#
# find_unique_files('./a', ['/bar'])
# # => ["/foo/filethree"]
#
# Returns Array<String>, each item representing a path (leading directory component omitted).
def find_unique_files(first, exclude)
file_list = []
Find.find(first) do |file|
relative_file_path = file.gsub(/#{first}/, '')
next if $ignored_files.include? relative_file_path
next if file == first
relative_dir = file.gsub(/#{first}/, '')
Find.prune if $ignored_dirs.include? relative_dir
next if FileTest.directory?(file)
# Make sure this file isn't in a path in the 'exclude' array
exclude_file = false
exclude.each do |dir|
if relative_file_path =~ /^#{dir}/
exclude_file = true
break
end
end
unless exclude_file
file_list << relative_file_path
end
end
file_list
end
# Converts many globbable paths to a globbed modman entries
#
# paths - An Array<String> containing multiple paths.
#
# Examples
#
# paths = %w(app/code/Community/Bar app/code/Community/Baz app/code/Community/Foo 123.php)
# globify_and_format(paths)
# # => ["app/code/community/*\tapp/code/community/", "123.php\t123.php"]
#
# Returns Array<String> paths as modman entries. The +paths+ argument is also modified.
def globify_and_format(paths)
# Alphabetize our paths before getting started.
paths.sort!
paths.each_index do |index|
total_paths = paths.count
path_exploded = paths[index].split('/')
path_exploded.delete_at(-1)
path = path_exploded.join('/')
globbed = []
unless path == ''
((index + 1)..(total_paths - 1)).to_a.each do |i|
i_exploded = paths[i].split('/')
i_exploded.delete_at(-1)
i_path = i_exploded.join('/')
if i_path === path
globbed << i
else
# At this point, we've found all the "globbable" lines. We now need to check the next line to make sure that
# our globbed path doesn't INCLUDE the next path when it expands.
#
# Example:
# paths => {
# [0] => js/custom.js,
# [1] => js/main.js,
# [2] => js/helper.js,
# [3] => js/scriptaculous/custom.js,
# [4] => js/scriptaculous/helper.js
# }
# === Becomes ===
# paths => {
# [0] => js/*
# [1] => js/scriptaculous/*
# }
#
# These two lines conflict, and may overwrite valid files. Instead, we SHOULDN'T glob if the next line is a
# subdirectory.
i_exploded.delete_at(-1)
i_path = i_exploded.join('/')
globbed = [] if i_path == path
break
end
end
end
# convert paths to true modman-style entries
# each entry is a simple 1-to-1 mapping
if globbed.empty?
paths[index] = paths[index] + "\t" + paths[index]
else
paths.slice!(globbed[0]..globbed[-1])
paths[index] = path + "/*\t" + path + "/"
end
end
end
# Main program begin (only if called directly)
if __FILE__ == $0
directory = Dir.getwd
if ARGV[0].nil?
directory = directory.split('/')
# Ensure that we are in a modman module directory
unless directory[-2] == '.modman'
puts "It looks like you aren't in a Modman module directory."
puts "You can specify a target Magento directory on the command line."
exit 1
end
# Put together the 'module_directory' and 'target_directory' directories
module_directory = directory.join('/') + '/'
directory.delete_at(-2)
directory.delete_at(-1)
target_directory = directory.join('/') + '/'
else
module_directory = directory + '/'
target_directory = ARGV[0]
end
# Find all directories that exist in the module directory, but not the target directory
uniq_directories = find_unique_directories(module_directory, target_directory)
# Find all files that exist in the module directory, but not the target directory (already found in uniq_directories)
uniq_files = find_unique_files(module_directory, uniq_directories)
# Glob and format the directories and files
modman_entries = uniq_directories + uniq_files
globify_and_format(modman_entries)
# Output the modman file
modman_entries.each { |line| puts line }
end