22
22
import sys
23
23
from copy import copy
24
24
from os import walk , remove , makedirs
25
- from os .path import join , abspath , dirname , relpath , exists , splitext
25
+ from os .path import join , abspath , dirname , relpath , exists , isfile
26
26
from shutil import copyfile
27
27
from optparse import OptionParser
28
+ import re
29
+ import string
28
30
29
31
ROOT = abspath (join (dirname (__file__ ), ".." ))
30
32
sys .path .append (ROOT )
33
35
from workspace_tools .paths import LIB_DIR
34
36
from workspace_tools .utils import cmd , run_cmd
35
37
36
-
37
38
MBED_URL = "mbed.org"
38
- # MBED_URL = "world2.dev.mbed.org"
39
39
40
- MBED_REPO_EXT = (".lib" , ".bld" )
40
+ changed = []
41
+ push_remote = True
42
+ quiet = False
43
+ commit_msg = ''
41
44
42
45
# mbed_official code that does have a mirror in the mbed SDK
43
46
OFFICIAL_CODE = (
88
91
"mbed-src-program" ,
89
92
)
90
93
94
+ # A list of regular expressions that will be checked against each directory
95
+ # name and skipped if they match.
96
+ IGNORE_DIRS = (
97
+ )
98
+
99
+ IGNORE_FILES = (
100
+ 'COPYING' ,
101
+ '\.md' ,
102
+ "\.lib" ,
103
+ "\.bld"
104
+ )
105
+
106
+ def ignore_path (name , reg_exps ):
107
+ for r in reg_exps :
108
+ if re .search (r , name ):
109
+ return True
110
+ return False
91
111
92
112
class MbedOfficialRepository :
93
113
URL = "http://" + MBED_URL + "/users/mbed_official/code/%s/"
@@ -114,30 +134,99 @@ def publish(self):
114
134
stdout , _ , _ = run_cmd (['hg' , 'status' ], wd = self .path )
115
135
if stdout == '' :
116
136
print "No changes"
117
- return
137
+ return False
118
138
119
139
print stdout
120
- commit = raw_input ("Do you want to commit and push? Y/N: " )
140
+ if quiet :
141
+ commit = 'Y'
142
+ else :
143
+ commit = raw_input (push_remote and "Do you want to commit and push? Y/N: " or "Do you want to commit? Y/N: " )
121
144
if commit == 'Y' :
122
- cmd (['hg' , 'commit' , '-u' , MBED_ORG_USER ], cwd = self .path )
123
- cmd (['hg' , 'push' ], cwd = self .path )
145
+ args = ['hg' , 'commit' , '-u' , MBED_ORG_USER ]
146
+ if commit_msg :
147
+ args = args + ['-m' , commit_msg ]
148
+ cmd (args , cwd = self .path )
149
+ if push_remote :
150
+ cmd (['hg' , 'push' ], cwd = self .path )
151
+ return True
124
152
153
+ # Check if a file is a text file or a binary file
154
+ # Taken from http://code.activestate.com/recipes/173220/
155
+ text_characters = "" .join (map (chr , range (32 , 127 )) + list ("\n \r \t \b " ))
156
+ _null_trans = string .maketrans ("" , "" )
157
+ def is_text_file (filename ):
158
+ block_size = 1024
159
+ def istext (s ):
160
+ if "\0 " in s :
161
+ return 0
125
162
126
- def visit_files (path , visit , ignore = None , select = None ):
163
+ if not s : # Empty files are considered text
164
+ return 1
165
+
166
+ # Get the non-text characters (maps a character to itself then
167
+ # use the 'remove' option to get rid of the text characters.)
168
+ t = s .translate (_null_trans , text_characters )
169
+
170
+ # If more than 30% non-text characters, then
171
+ # this is considered a binary file
172
+ if float (len (t ))/ len (s ) > 0.30 :
173
+ return 0
174
+ return 1
175
+ with open (filename ) as f :
176
+ res = istext (f .read (block_size ))
177
+ return res
178
+
179
+ # Return the line ending type for the given file ('cr' or 'crlf')
180
+ def get_line_endings (f ):
181
+ examine_size = 1024
182
+ try :
183
+ tf = open (f , "rb" )
184
+ lines , ncrlf = tf .readlines (examine_size ), 0
185
+ tf .close ()
186
+ for l in lines :
187
+ if l .endswith ("\r \n " ):
188
+ ncrlf = ncrlf + 1
189
+ return 'crlf' if ncrlf > len (lines ) >> 1 else 'cr'
190
+ except :
191
+ return 'cr'
192
+
193
+ # Copy file to destination, but preserve destination line endings if possible
194
+ # This prevents very annoying issues with huge diffs that appear because of
195
+ # differences in line endings
196
+ def copy_with_line_endings (sdk_file , repo_file ):
197
+ if not isfile (repo_file ):
198
+ copyfile (sdk_file , repo_file )
199
+ return
200
+ is_text = is_text_file (repo_file )
201
+ if is_text :
202
+ sdk_le = get_line_endings (sdk_file )
203
+ repo_le = get_line_endings (repo_file )
204
+ if not is_text or sdk_le == repo_le :
205
+ copyfile (sdk_file , repo_file )
206
+ else :
207
+ print "Converting line endings in '%s' to '%s'" % (abspath (repo_file ), repo_le )
208
+ f = open (sdk_file , "rb" )
209
+ data = f .read ()
210
+ f .close ()
211
+ f = open (repo_file , "wb" )
212
+ data = data .replace ("\r \n " , "\n " ) if repo_le == 'cr' else data .replace ('\n ' ,'\r \n ' )
213
+ f .write (data )
214
+ f .close ()
215
+
216
+ def visit_files (path , visit ):
127
217
for root , dirs , files in walk (path ):
128
218
# Ignore hidden directories
129
219
for d in copy (dirs ):
220
+ full = join (root , d )
130
221
if d .startswith ('.' ):
131
222
dirs .remove (d )
223
+ if ignore_path (full , IGNORE_DIRS ):
224
+ print "Skipping '%s'" % full
225
+ dirs .remove (d )
132
226
133
227
for file in files :
134
- ext = splitext (file )[1 ]
135
-
136
- if ignore is not None :
137
- if ext in ignore : continue
138
-
139
- if select is not None :
140
- if ext not in select : continue
228
+ if ignore_path (file , IGNORE_FILES ):
229
+ continue
141
230
142
231
visit (join (root , file ))
143
232
@@ -152,18 +241,19 @@ def visit_mbed_sdk(sdk_file):
152
241
if not exists (repo_dir ):
153
242
makedirs (repo_dir )
154
243
155
- copyfile (sdk_file , repo_file )
156
- visit_files (sdk_path , visit_mbed_sdk , [ '.json' ] )
244
+ copy_with_line_endings (sdk_file , repo_file )
245
+ visit_files (sdk_path , visit_mbed_sdk )
157
246
158
247
# remove repository files that do not exist in the mbed SDK
159
248
def visit_repo (repo_file ):
160
249
sdk_file = join (sdk_path , relpath (repo_file , repo .path ))
161
250
if not exists (sdk_file ):
162
251
remove (repo_file )
163
252
print "remove: %s" % repo_file
164
- visit_files (repo .path , visit_repo , MBED_REPO_EXT )
253
+ visit_files (repo .path , visit_repo )
165
254
166
- repo .publish ()
255
+ if repo .publish ():
256
+ changed .append (repo_name )
167
257
168
258
169
259
def update_code (repositories ):
@@ -186,7 +276,8 @@ def visit_repo(repo_file):
186
276
f .write (url [:(url .rindex ('/' )+ 1 )])
187
277
visit_files (repo .path , visit_repo , None , MBED_REPO_EXT )
188
278
189
- repo .publish ()
279
+ if repo .publish ():
280
+ changed .append (repo_name )
190
281
191
282
192
283
def update_mbed ():
@@ -208,8 +299,23 @@ def update_mbed():
208
299
action = "store_true" , default = False ,
209
300
help = "Release a build of the mbed library" )
210
301
302
+ parser .add_option ("-n" , "--nopush" ,
303
+ action = "store_true" , default = False ,
304
+ help = "Commit the changes locally only, don't push them" )
305
+
306
+ parser .add_option ("" , "--commit_message" ,
307
+ action = "store" , type = "string" , default = '' , dest = 'msg' ,
308
+ help = "Commit message to use for all the commits" )
309
+ parser .add_option ("-q" , "--quiet" ,
310
+ action = "store_true" , default = False ,
311
+ help = "Don't ask for confirmation before commiting or pushing" )
312
+
211
313
(options , args ) = parser .parse_args ()
212
314
315
+ push_remote = not options .nopush
316
+ quiet = options .quiet
317
+ commit_msg = options .msg
318
+
213
319
if options .code :
214
320
update_code (OFFICIAL_CODE )
215
321
@@ -219,3 +325,6 @@ def update_mbed():
219
325
if options .mbed :
220
326
update_mbed ()
221
327
328
+ if changed :
329
+ print "Repositories with changes:" , changed
330
+
0 commit comments