@@ -1206,6 +1206,190 @@ function check_success()
1206
1206
}
1207
1207
1208
1208
1209
+ # https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification
1210
+ function check_library_structure()
1211
+ {
1212
+ local -r libraryPath=" $1 "
1213
+ # Replace backslashes with slashes
1214
+ local -r libraryPathWithSlashes=" ${libraryPath// \\ // } "
1215
+ # Remove trailing slash
1216
+ local -r normalizedLibraryPath=" ${libraryPathWithSlashes%/ } "
1217
+
1218
+ # Check whether folder exists
1219
+ if [[ ! -d " $normalizedLibraryPath " ]]; then
1220
+ echo " ERROR: Specified folder: $libraryPath doesn't exist."
1221
+ return 1
1222
+ fi
1223
+
1224
+ # Check for valid 1.0 or 1.5 format
1225
+ if [[ $( find " $normalizedLibraryPath " -maxdepth 1 -type f \( -name ' *.h' -or -name ' *.hh' -or -name ' *.hpp' \) ) ]]; then
1226
+ # 1.0 format library, do nothing (this if just makes the logic more simple)
1227
+ :
1228
+ elif [[ $( find " $normalizedLibraryPath " -maxdepth 1 \( -type f -and -name ' library.properties' \) ) && $( find " $normalizedLibraryPath " -maxdepth 1 -type d -and -regex ' ^.*[sS][rR][cC]$' ) ]]; then
1229
+ # 1.5 format library
1230
+ if [[ ! $( find " $normalizedLibraryPath " -maxdepth 1 -type d -and -name ' src' ) ]]; then
1231
+ echo ' ERROR: 1.5 format library with incorrect case in src subfolder name, which causes library to not be recognized on a filename case-sensitive OS such as Linux.'
1232
+ return 2
1233
+ elif [[ $( find " ${normalizedLibraryPath} /src" -maxdepth 1 -type f \( -name ' *.h' -or -name ' *.hh' -or -name ' *.hpp' \) ) ]]; then
1234
+ local -r onePointFiveFormat=true
1235
+ fi
1236
+ else
1237
+ echo " ERROR: No valid library found in $libraryPath "
1238
+ return 3
1239
+ fi
1240
+
1241
+ # Check if folder name is valid
1242
+ check_valid_folder_name " $normalizedLibraryPath "
1243
+ local -r checkValidFolderNameExitStatus=$?
1244
+ if [[ $checkValidFolderNameExitStatus -ne $ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS ]]; then
1245
+ return $(( 3 + checkValidFolderNameExitStatus))
1246
+ fi
1247
+
1248
+ # Check for incorrect spelling of examples folder
1249
+ if [[ $( find " $normalizedLibraryPath " -maxdepth 1 -type d -and -regex ' ^.*/[eE][xX][aA][mM][pP][lL][eE].?$' ) && ! $( find " $normalizedLibraryPath " -maxdepth 1 -type d -and -name ' examples' ) ]]; then
1250
+ echo ' ERROR: Incorrect examples folder name.'
1251
+ return 7
1252
+ fi
1253
+
1254
+ # Check for 1.5 format with src and utility folders in library root
1255
+ if [[ " $onePointFiveFormat " == true && $( find " $normalizedLibraryPath " -maxdepth 1 -type d -and -name ' utility' ) ]]; then
1256
+ echo ' ERROR: 1.5 format library with src and utility folders in library root.'
1257
+ return 8
1258
+ fi
1259
+
1260
+ # Check for sketch files outside of the src or extras folders
1261
+ if [[ $( find " $normalizedLibraryPath " -maxdepth 1 -path ' ./examples' -prune -or -path ' ./extras' -prune -or \( -type f -and \( -regex ' ^.*\.[iI][nN][oO]' -or -regex ' ^.*\.[pP][dD][eE]' \) \) ) ]]; then
1262
+ echo ' ERROR: Sketch files found outside of examples and extras folders.'
1263
+ return 9
1264
+ fi
1265
+
1266
+ # Run check_sketch_structure() on examples and extras folders
1267
+ if [[ -d " ${normalizedLibraryPath} /examples" ]]; then
1268
+ check_sketch_structure " ${normalizedLibraryPath} /examples"
1269
+ local -r checkExamplesSketchStructureExitStatus=$?
1270
+ if [[ $checkExamplesSketchStructureExitStatus -ne $ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS ]]; then
1271
+ return $(( 9 + checkExamplesSketchStructureExitStatus))
1272
+ fi
1273
+ fi
1274
+ if [[ -d " ${normalizedLibraryPath} /extras" ]]; then
1275
+ check_sketch_structure " ${normalizedLibraryPath} /extras"
1276
+ local -r checkExtrasSketchStructureExitStatus=$?
1277
+ if [[ $checkExtrasSketchStructureExitStatus -ne $ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS ]]; then
1278
+ return $(( 9 + checkExtrasSketchStructureExitStatus))
1279
+ fi
1280
+ fi
1281
+ }
1282
+
1283
+
1284
+ # The same folder name restrictions apply to libraries and sketches so this function may be used for both
1285
+ function check_valid_folder_name()
1286
+ {
1287
+ local -r path=" $1 "
1288
+ # Get the folder name from the path
1289
+ local -r folderName=" ${path##*/ } "
1290
+
1291
+ # Starting folder name with a number is only supported by Arduino IDE 1.8.4 and newer
1292
+ local -r startsWithNumberRegex=" ^[0-9]"
1293
+ if [[ " $folderName " =~ $startsWithNumberRegex ]]; then
1294
+ echo " WARNING: Folder name (${folderName} ) beginning with a number is only supported by Arduino IDE 1.8.4 and newer."
1295
+ fi
1296
+
1297
+ # Starting folder name with a - or . is not allowed
1298
+ local -r startsWithInvalidCharacterRegex=" ^[-.]"
1299
+ if [[ " $folderName " =~ $startsWithInvalidCharacterRegex ]]; then
1300
+ echo " ERROR: Folder name (${folderName} ) beginning with a - or . is not allowed."
1301
+ return 1
1302
+ fi
1303
+
1304
+ # Allowed characters: a-z, A-Z, 0-1, -._
1305
+ local -r disallowedCharactersRegex=" [^a-zA-Z0-9._-]"
1306
+ if [[ " $folderName " =~ $disallowedCharactersRegex ]]; then
1307
+ echo " ERROR: Folder name $folderName contains disallowed characters. Only letters, numbers, dots, dashes, and underscores are allowed."
1308
+ return 2
1309
+ fi
1310
+
1311
+ # <64 characters
1312
+ if [[ ${# folderName} -gt 63 ]]; then
1313
+ echo " ERROR: Folder name $folderName exceeds the maximum of 63 characters."
1314
+ return 3
1315
+ fi
1316
+ return 0
1317
+ }
1318
+
1319
+
1320
+ function check_sketch_structure()
1321
+ {
1322
+ local -r searchPath=" $1 "
1323
+ # Replace backslashes with slashes
1324
+ local -r searchPathWithSlashes=" ${searchPath// \\ // } "
1325
+ # Remove trailing slash
1326
+ local -r normalizedSearchPath=" ${searchPathWithSlashes%/ } "
1327
+
1328
+ # Check whether folder exists
1329
+ if [[ ! -d " $normalizedSearchPath " ]]; then
1330
+ echo " ERROR: Specified folder: $searchPath doesn't exist."
1331
+ return 1
1332
+ fi
1333
+
1334
+ # find all folders that contain a sketch file
1335
+ find " $normalizedSearchPath " -type f \( -regex ' ^.*\.[iI][nN][oO]' -or -regex ' ^.*\.[pP][dD][eE]' \) -printf ' %h\n' | sort --unique | while read -r sketchPath; do
1336
+
1337
+ # Check for sketches with incorrect extension case
1338
+ find " $sketchPath " -maxdepth 1 -type f \( -regex ' ^.*\.[iI][nN][oO]' -or -regex ' ^.*\.[pP][dD][eE]' \) -print | while read -r sketchName; do
1339
+ if [[ " ${sketchName: -4} " != " .ino" && " ${sketchName: -4} " != " .pde" ]]; then
1340
+ echo " ERROR: Sketch file $sketchName has incorrect extension case, which causes it to not be recognized on a filename case-sensitive OS such as Linux."
1341
+ # This only breaks out of the pipe, it does not return from the function
1342
+ return 1
1343
+ fi
1344
+ done
1345
+ if [[ $? -eq 1 ]]; then
1346
+ return 2
1347
+ fi
1348
+
1349
+ # Check if sketch name is valid
1350
+ check_valid_folder_name " $sketchPath "
1351
+ local checkValidFolderNameExitStatus=$?
1352
+ if [[ $checkValidFolderNameExitStatus -ne $ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS ]]; then
1353
+ return $(( 2 + checkValidFolderNameExitStatus))
1354
+ fi
1355
+
1356
+ # Check for folder name mismatch
1357
+ if
1358
+ find " $sketchPath " -maxdepth 1 -type f \( -name ' *.ino' -or -name ' *.pde' \) -print | while read -r sketchFilePath; do
1359
+ local sketchFileFolderName=" ${sketchPath##*/ } "
1360
+ local sketchFilenameWithExtension=" ${sketchFilePath##*/ } "
1361
+ local sketchFilenameWithoutExtension=" ${sketchFilenameWithExtension% .* } "
1362
+ if [[ " $sketchFileFolderName " == " $sketchFilenameWithoutExtension " ]]; then
1363
+ # Sketch file found that matches the folder name
1364
+ # I need to return 1 because the exit status when no matches are found is 0
1365
+ return 1
1366
+ fi
1367
+ done
1368
+ then
1369
+ echo " ERROR: Sketch folder name $sketchPath does not match the sketch filename."
1370
+ return 6
1371
+ fi
1372
+
1373
+ # Check for multiple sketches in folder
1374
+ if
1375
+ ! find " $sketchPath " -maxdepth 1 -type f \( -name ' *.ino' -or -name ' *.pde' \) -print | while read -r sketchFilePath; do
1376
+ if grep --quiet --regexp=' void *setup *( *)' " $sketchFilePath " ; then
1377
+ if [[ " $primarySketchFound " == true ]]; then
1378
+ # A primary sketch file was previously found in this folder
1379
+ return 1
1380
+ fi
1381
+ local primarySketchFound=true
1382
+ fi
1383
+ done
1384
+ then
1385
+ echo " ERROR: Multiple sketches found in the same folder (${sketchPath} )."
1386
+ return 7
1387
+ fi
1388
+
1389
+ done
1390
+ }
1391
+
1392
+
1209
1393
# Set default verbosity (must be called after the function definitions
1210
1394
set_script_verbosity 0
1211
1395
0 commit comments