Skip to content

Commit c7c1525

Browse files
committed
Add check_library_structure() and check_sketch_structure()
Resolves #23 Resolves #22
1 parent 8895100 commit c7c1525

File tree

3 files changed

+196
-0
lines changed

3 files changed

+196
-0
lines changed

.travis.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ before_install:
120120

121121

122122
script:
123+
- check_sketch_structure "${SKETCHBOOK_FOLDER}/libraries/NewPing/examples"
124+
125+
- check_library_structure "${SKETCHBOOK_FOLDER}/libraries/CapacitiveSensor"
126+
123127
# Test library installed from .zip with rename
124128
# Test library installed from .zip with dot in the folder name
125129
# Test board from hardware package manually installed from compressed file download

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,14 @@ Install a library by cloning a Git repository). The library is installed to the
109109
Turn on/off arduino verbose output during compilation (same as the IDE's **File > Preferences > Show verbose output during: > compilation**). This will show all the commands arduino runs during the process rather than just the compiler output. This is usually not very useful output and only clutters up the log. This feature is off by default.
110110
- Parameter: **verboseOutputDuringCompilation** - `true`/`false`
111111

112+
##### `check_sketch_structure searchPath'
113+
Check sketches to ensure they have the correct structure.
114+
- Parameter: **searchPath** - Path containing sketches. The path will be searched recursively and all sketches found under it will be checked.
115+
116+
##### `check_library_structure libraryPath'
117+
Check a library to ensure they have the correct structure. This will also run `check_sketch_structure` on all sketches bundled with the library.
118+
- Parameter: **libraryPath** - Path containing a library.
119+
112120
##### `build_sketch sketchPath boardID allowFail IDEversion`
113121
##### `build_sketch sketchPath boardID allowFail [IDEversionList]`
114122
##### `build_sketch sketchPath boardID allowFail startIDEversion endIDEversion`

arduino-ci-script.sh

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,6 +1206,190 @@ function check_success()
12061206
}
12071207

12081208

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+
12091393
# Set default verbosity (must be called after the function definitions
12101394
set_script_verbosity 0
12111395

0 commit comments

Comments
 (0)