forked from adamlaska/datatracker
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbower_install.py
More file actions
232 lines (181 loc) · 9.29 KB
/
Copy pathbower_install.py
File metadata and controls
232 lines (181 loc) · 9.29 KB
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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
import os
import sys
import json
import tempfile
import shutil
import hashlib
import glob
import textwrap
from subprocess import call, check_output, CalledProcessError
from optparse import make_option
import debug # pyflakes:ignore
from django.core.management.base import BaseCommand
from django.core.files.storage import FileSystemStorage
from django.conf import settings
from django.contrib.staticfiles.finders import BaseStorageFinder, AppDirectoriesFinder
class BaseDirectoryFinder(BaseStorageFinder):
storage = FileSystemStorage(location=settings.BASE_DIR)
class Command(BaseCommand):
"""
This command goes through any static/ directories of installed apps,
and the directories listed in settings.STATICFILES_DIRS. If package
description files for bower, npm, or grunt are found in any of these
locations, it will use the appropriate package manager to install the
listed packages in a temporary folder, using these commands:
- package.json: npm install
- Gruntfile.js: grunt default
- bower.json: bower install
It will then extract the distribution files to the location indicated in
settings.COMPONENT_ROOT.
"""
help = textwrap.dedent(__doc__).lstrip()
component_root = getattr(settings, 'COMPONENT_ROOT', os.path.join(settings.STATIC_ROOT, "components"))
def add_arguments(self, parser):
parser.add_argument('--with-version', dest='with_version', default=False, action='store_true',
help='Create component directories with version numbers')
parser.add_argument('--keep-packages', dest='keep_packages', default=False, action='store_true',
help='Keep the downloaded bower packages, instead of removing them after moving '
'distribution files to settings.COMPONENT_ROOT')
bower_info = {}
overrides = {}
def npm_install(self, pkg_json_path):
os.chdir(os.path.dirname(pkg_json_path))
call(['npm', 'install'])
def grunt_default(self, grunt_js_path):
os.chdir(os.path.dirname(grunt_js_path))
call(['grunt'])
def bower_install(self, bower_json_path, dest_dir):
"""Runs bower commnand for the passed bower.json path.
:param bower_json_path: bower.json file to install
:param dest_dir: where the compiled result will arrive
"""
# Verify that we are able to run bower, in order to give a good error message in the
# case that it's not installed. Do this separately from the 'bower install' call, in
# order not to warn about a missing bower in the case of installation-related errors.
try:
bower_version = check_output(['bower', '--version']).strip()
except OSError as e:
print("Trying to run bower failed -- is it installed? The error was: %s" % e)
exit(1)
except CalledProcessError as e:
print("Checking the bower version failed: %s" % e)
exit(2)
print("\nBower %s" % bower_version)
print("Installing from %s\n" % bower_json_path)
# bower args
args = ['bower', 'install', bower_json_path, '--allow-root',
'--verbose', '--config.cwd={}'.format(dest_dir), '-p']
# run bower command
call(args)
def get_bower_info(self, bower_json_path):
if not bower_json_path in self.bower_info:
self.bower_info[bower_json_path] = json.load(open(bower_json_path))
def get_bower_main_list(self, bower_json_path, override):
"""
Returns the bower.json main list or empty list.
Applies overrides from the site-wide bower.json.
"""
self.get_bower_info(bower_json_path)
main_list = self.bower_info[bower_json_path].get('main')
component = self.bower_info[bower_json_path].get('name')
if (override in self.bower_info
and "overrides" in self.bower_info[override]
and component in self.bower_info[override].get("overrides")
and "main" in self.bower_info[override].get("overrides").get(component)):
main_list = self.bower_info[override].get("overrides").get(component).get("main")
if isinstance(main_list, list):
return main_list
if main_list:
return [main_list]
return []
def get_bower_version(self, bower_json_path):
"""Returns the bower.json main list or empty list.
"""
self.get_bower_info(bower_json_path)
return self.bower_info[bower_json_path].get("version")
def clean_components_to_static_dir(self, bower_dir, override):
print("\nMoving component files to %s\n" % (self.component_root,))
for directory in os.listdir(bower_dir):
print("Component: %s" % (directory, ))
src_root = os.path.join(bower_dir, directory)
for bower_json in ['bower.json', '.bower.json']:
bower_json_path = os.path.join(src_root, bower_json)
if os.path.exists(bower_json_path):
main_list = self.get_bower_main_list(bower_json_path, override) + ['bower.json']
version = self.get_bower_version(bower_json_path)
dst_root = os.path.join(self.component_root, directory)
if self.with_version:
assert not dst_root.endswith(os.sep)
dst_root += "-"+version
for pattern in filter(None, main_list):
src_pattern = os.path.join(src_root, pattern)
# main_list elements can be fileglob patterns
for src_path in glob.glob(src_pattern):
if not os.path.exists(src_path):
print("Could not find source path: %s" % (src_path, ))
# Build the destination path
src_part = src_path[len(src_root+'/'):]
if src_part.startswith('dist/'):
src_part = src_part[len('dist/'):]
dst_path = os.path.join(dst_root, src_part)
# Normalize the paths, for good looks
src_path = os.path.abspath(src_path)
dst_path = os.path.abspath(dst_path)
# Check if we need to copy the file at all.
if os.path.exists(dst_path):
with open(src_path, 'br') as src:
src_hash = hashlib.sha1(src.read()).hexdigest()
with open(dst_path, 'br') as dst:
dst_hash = hashlib.sha1(dst.read()).hexdigest()
if src_hash == dst_hash:
#print('{0} = {1}'.format(src_path, dst_path))
continue
# Make sure dest dir exists.
dst_dir = os.path.dirname(dst_path)
if not os.path.exists(dst_dir):
os.makedirs(dst_dir)
print(' {0} > {1}'.format(src_path, dst_path))
shutil.copy(src_path, dst_path)
break
def handle(self, *args, **options):
self.with_version = options.get("with_version")
self.keep_packages = options.get("keep_packages")
temp_dir = getattr(settings, 'BWR_APP_TMP_FOLDER', 'tmp')
temp_dir = os.path.abspath(temp_dir)
# finders
basefinder = BaseDirectoryFinder()
appfinder = AppDirectoriesFinder()
# Assume bower.json files are to be found in each app directory,
# rather than in the app's static/ subdirectory:
appfinder.source_dir = '.'
finders = (basefinder, appfinder, )
if os.path.exists(temp_dir):
if not self.keep_packages:
sys.stderr.write(
"\nWARNING:\n\n"
" The temporary package installation directory exists, but the --keep-packages\n"
" option has not been given. In order to not delete anything which should be\n"
" kept, %s will not be removed.\n\n"
" Please remove it manually, or use the --keep-packages option to avoid this\n"
" message.\n\n" % (temp_dir,))
self.keep_packages = True
else:
os.makedirs(temp_dir)
for finder in finders:
for path in finder.find('package.json', all=True):
self.npm_install(path)
for finder in finders:
for path in finder.find('Gruntfile.json', all=True):
self.grunt_default(path)
for finder in finders:
for path in finder.find('bower.json', all=True):
self.get_bower_info(path)
self.bower_install(path, temp_dir)
bower_dir = os.path.join(temp_dir, 'bower_components')
# nothing to clean
if not os.path.exists(bower_dir):
print('No components seems to have been found by bower, exiting.')
sys.exit(0)
self.clean_components_to_static_dir(bower_dir, path)
if not self.keep_packages:
shutil.rmtree(temp_dir)