2014-08-21 12:23:42 +02:00
package processing.app ;
2015-08-31 16:05:23 +02:00
import cc.arduino.Compiler ;
2015-07-09 15:16:19 +02:00
import cc.arduino.Constants ;
2015-08-31 16:05:23 +02:00
import cc.arduino.UploaderUtils ;
2015-07-03 16:00:57 +02:00
import cc.arduino.contributions.GPGDetachedSignatureVerifier ;
2015-04-30 11:17:27 +02:00
import cc.arduino.contributions.SignatureVerificationFailedException ;
2015-03-17 16:17:50 +01:00
import cc.arduino.contributions.libraries.LibrariesIndexer ;
2015-04-23 11:10:54 +02:00
import cc.arduino.contributions.packages.ContributedTool ;
import cc.arduino.contributions.packages.ContributionsIndexer ;
2015-04-15 10:19:39 +02:00
import cc.arduino.files.DeleteFilesOnShutdown ;
2014-08-22 16:49:39 +02:00
import cc.arduino.packages.DiscoveryManager ;
2014-09-10 18:48:34 +02:00
import cc.arduino.packages.Uploader ;
2015-05-04 17:44:16 +02:00
import com.fasterxml.jackson.core.JsonProcessingException ;
2015-09-18 10:47:23 +02:00
import org.apache.commons.codec.digest.DigestUtils ;
2015-05-21 16:47:50 +02:00
import org.apache.commons.compress.utils.IOUtils ;
2015-03-05 17:42:26 +01:00
import org.apache.commons.logging.impl.LogFactoryImpl ;
import org.apache.commons.logging.impl.NoOpLog ;
import processing.app.debug.* ;
import processing.app.helpers.* ;
2014-08-21 13:18:54 +02:00
import processing.app.helpers.filefilters.OnlyDirs ;
2014-08-21 14:06:25 +02:00
import processing.app.helpers.filefilters.OnlyFilesWithExtension ;
2014-08-21 13:43:10 +02:00
import processing.app.legacy.PApplet ;
2014-08-21 14:06:25 +02:00
import processing.app.packages.LibraryList ;
2014-10-17 00:05:36 +02:00
import processing.app.packages.UserLibrary ;
2014-08-21 12:35:01 +02:00
2015-07-03 16:00:57 +02:00
import java.io.File ;
import java.io.FileOutputStream ;
import java.io.FileWriter ;
import java.io.IOException ;
2015-09-18 10:47:23 +02:00
import java.nio.file.Files ;
2015-03-05 17:42:26 +01:00
import java.util.* ;
import java.util.logging.Level ;
import java.util.logging.Logger ;
2015-08-05 09:04:53 +02:00
import static processing.app.I18n.tr ;
2015-09-25 12:04:55 +02:00
import static processing.app.helpers.filefilters.OnlyDirs.ONLY_DIRS ;
2015-03-05 17:42:26 +01:00
2014-08-21 12:23:42 +02:00
public class BaseNoGui {
2014-11-18 14:04:14 +01:00
/** Version string to be used for build */
2015-12-21 12:05:04 +00:00
public static final int REVISION = 10608 ;
2014-11-18 14:04:14 +01:00
/** Extended version string displayed on GUI */
2015-12-21 12:05:04 +00:00
public static final String VERSION_NAME = " 1.6.8 " ;
2015-05-11 10:48:52 +02:00
public static final String VERSION_NAME_LONG ;
2015-06-29 15:10:42 +02:00
// Current directory to use for relative paths specified on the
// commandline
static String currentDirectory = System . getProperty ( " user.dir " ) ;
2015-05-11 10:48:52 +02:00
static {
String versionNameLong = VERSION_NAME ;
File hourlyBuildTxt = new File ( getContentFile ( " lib " ) , " hourlyBuild.txt " ) ;
if ( hourlyBuildTxt . exists ( ) & & hourlyBuildTxt . canRead ( ) ) {
versionNameLong + = " Hourly Build " ;
try {
versionNameLong + = " " + FileUtils . readFileToString ( hourlyBuildTxt ) . trim ( ) ;
} catch ( IOException e ) {
//noop
}
}
VERSION_NAME_LONG = versionNameLong ;
}
2014-08-21 12:23:42 +02:00
2014-08-22 16:49:39 +02:00
private static DiscoveryManager discoveryManager = new DiscoveryManager ( ) ;
2014-08-25 18:57:18 +02:00
// these are static because they're used by Sketch
static private File examplesFolder ;
static private File toolsFolder ;
2014-08-21 14:06:25 +02:00
// maps #included files to their library folder
2015-03-30 10:24:18 -07:00
public static Map < String , LibraryList > importToLibraryTable ;
2014-08-21 14:06:25 +02:00
2014-05-16 01:11:47 +02:00
// XXX: Remove this field
2014-08-25 18:57:18 +02:00
static private List < File > librariesFolders ;
2014-08-21 20:13:05 +02:00
static UserNotifier notifier = new BasicUserNotifier ( ) ;
2014-08-21 19:47:33 +02:00
2014-08-21 13:18:54 +02:00
static public Map < String , TargetPackage > packages ;
2014-08-21 13:33:46 +02:00
static Platform platform ;
2014-08-21 13:18:54 +02:00
static File portableFolder = null ;
2014-08-26 11:48:25 +02:00
static final String portableSketchbookFolder = " sketchbook " ;
2015-05-05 13:03:28 +02:00
public static ContributionsIndexer indexer ;
2015-11-17 12:24:28 +01:00
public static LibrariesIndexer librariesIndexer ;
2014-05-16 00:56:22 +02:00
2014-08-21 13:18:54 +02:00
// Returns a File object for the given pathname. If the pathname
// is not absolute, it is interpreted relative to the current
// directory when starting the IDE (which is not the same as the
// current working directory!).
static public File absoluteFile ( String path ) {
if ( path = = null ) return null ;
File file = new File ( path ) ;
if ( ! file . isAbsolute ( ) ) {
file = new File ( currentDirectory , path ) ;
}
return file ;
}
2014-08-22 18:35:15 +02:00
/ * *
* Get the number of lines in a file by counting the number of newline
* characters inside a String ( and adding 1 ) .
* /
static public int countLines ( String what ) {
int count = 1 ;
for ( char c : what . toCharArray ( ) ) {
if ( c = = '\n' ) count + + ;
}
return count ;
}
2014-08-21 12:35:01 +02:00
static public String getAvrBasePath ( ) {
String path = getHardwarePath ( ) + File . separator + " tools " +
File . separator + " avr " + File . separator + " bin " + File . separator ;
if ( OSUtils . isLinux ( ) & & ! ( new File ( path ) ) . exists ( ) ) {
return " " ; // use distribution provided avr tools if bundled tools missing
}
return path ;
}
2015-09-18 10:47:23 +02:00
static public File getBuildFolder ( SketchData data ) throws IOException {
File buildFolder ;
if ( PreferencesData . get ( " build.path " ) ! = null ) {
buildFolder = absoluteFile ( PreferencesData . get ( " build.path " ) ) ;
Files . createDirectories ( buildFolder . toPath ( ) ) ;
} else {
buildFolder = FileUtils . createTempFolder ( " build " , DigestUtils . md5Hex ( data . getMainFilePath ( ) ) + " .tmp " ) ;
DeleteFilesOnShutdown . add ( buildFolder ) ;
2014-08-26 19:14:45 +02:00
}
return buildFolder ;
}
2014-08-21 13:38:28 +02:00
static public PreferencesMap getBoardPreferences ( ) {
TargetBoard board = getTargetBoard ( ) ;
2014-05-01 16:17:43 +02:00
if ( board = = null )
return null ;
2015-01-27 20:22:22 +01:00
String boardId = board . getId ( ) ;
2014-08-21 13:38:28 +02:00
PreferencesMap prefs = new PreferencesMap ( board . getPreferences ( ) ) ;
2015-01-27 20:22:22 +01:00
String extendedName = prefs . get ( " name " ) ;
2014-08-21 13:38:28 +02:00
for ( String menuId : board . getMenuIds ( ) ) {
2015-01-27 20:22:22 +01:00
if ( ! board . hasMenu ( menuId ) )
continue ;
// Get "custom_[MENU_ID]" preference (for example "custom_cpu")
2014-08-22 12:47:43 +02:00
String entry = PreferencesData . get ( " custom_ " + menuId ) ;
2015-01-27 20:22:22 +01:00
if ( entry ! = null & & entry . startsWith ( boardId ) ) {
String selectionId = entry . substring ( boardId . length ( ) + 1 ) ;
2014-08-21 13:38:28 +02:00
prefs . putAll ( board . getMenuPreferences ( menuId , selectionId ) ) ;
2015-01-27 20:22:22 +01:00
// Update the name with the extended configuration
extendedName + = " , " + board . getMenuLabel ( menuId , selectionId ) ;
2014-08-21 13:38:28 +02:00
}
}
2015-01-27 20:22:22 +01:00
prefs . put ( " name " , extendedName ) ;
2014-08-21 13:38:28 +02:00
return prefs ;
}
2014-08-21 12:35:01 +02:00
static public File getContentFile ( String name ) {
2015-06-29 14:45:51 +02:00
String appDir = System . getProperty ( " APP_DIR " ) ;
if ( appDir = = null | | appDir . length ( ) = = 0 ) {
appDir = currentDirectory ;
}
File installationFolder = new File ( appDir ) ;
2015-06-26 08:57:51 +02:00
return new File ( installationFolder , name ) ;
2014-08-21 12:35:01 +02:00
}
2014-08-21 19:00:29 +02:00
static public TargetPlatform getCurrentTargetPlatformFromPackage ( String pack ) {
2014-08-22 12:47:43 +02:00
return getTargetPlatform ( pack , PreferencesData . get ( " target_platform " ) ) ;
2014-08-21 19:00:29 +02:00
}
2014-08-26 12:19:53 +02:00
static public File getDefaultSketchbookFolder ( ) {
if ( getPortableFolder ( ) ! = null )
return new File ( getPortableFolder ( ) , getPortableSketchbookFolder ( ) ) ;
File sketchbookFolder = null ;
try {
sketchbookFolder = getPlatform ( ) . getDefaultSketchbookFolder ( ) ;
} catch ( Exception e ) { }
return sketchbookFolder ;
}
2014-08-22 16:49:39 +02:00
public static DiscoveryManager getDiscoveryManager ( ) {
return discoveryManager ;
}
2014-08-25 18:57:18 +02:00
static public File getExamplesFolder ( ) {
return examplesFolder ;
}
static public String getExamplesPath ( ) {
return examplesFolder . getAbsolutePath ( ) ;
}
2014-08-21 12:35:01 +02:00
static public File getHardwareFolder ( ) {
// calculate on the fly because it's needed by Preferences.init() to find
// the boards.txt and programmers.txt preferences files (which happens
// before the other folders / paths get cached).
return getContentFile ( " hardware " ) ;
}
static public String getHardwarePath ( ) {
return getHardwareFolder ( ) . getAbsolutePath ( ) ;
}
2014-08-21 14:06:25 +02:00
2014-08-25 18:57:18 +02:00
static public List < File > getLibrariesPath ( ) {
return librariesFolders ;
}
2014-08-21 13:33:46 +02:00
static public Platform getPlatform ( ) {
return platform ;
}
2014-08-21 13:18:54 +02:00
static public File getPortableFolder ( ) {
return portableFolder ;
}
2014-08-26 11:48:25 +02:00
static public String getPortableSketchbookFolder ( ) {
return portableSketchbookFolder ;
}
2014-08-21 19:47:33 +02:00
/ * *
* Convenience method to get a File object for the specified filename inside
* the settings folder .
* For now , only used by Preferences to get the preferences . txt file .
* @param filename A file inside the settings folder .
* @return filename wrapped as a File object inside the settings folder
* /
static public File getSettingsFile ( String filename ) {
return new File ( getSettingsFolder ( ) , filename ) ;
}
static public File getSettingsFolder ( ) {
2014-08-22 13:41:41 +02:00
if ( getPortableFolder ( ) ! = null )
return getPortableFolder ( ) ;
2014-08-21 19:47:33 +02:00
File settingsFolder = null ;
2014-08-22 12:47:43 +02:00
String preferencesPath = PreferencesData . get ( " settings.path " ) ;
2014-08-21 19:47:33 +02:00
if ( preferencesPath ! = null ) {
settingsFolder = absoluteFile ( preferencesPath ) ;
} else {
try {
settingsFolder = getPlatform ( ) . getSettingsFolder ( ) ;
} catch ( Exception e ) {
2015-08-05 09:04:53 +02:00
showError ( tr ( " Problem getting data folder " ) ,
tr ( " Error getting the Arduino data folder. " ) , e ) ;
2014-08-21 19:47:33 +02:00
}
}
// create the folder if it doesn't exist already
if ( ! settingsFolder . exists ( ) ) {
if ( ! settingsFolder . mkdirs ( ) ) {
2015-08-05 09:04:53 +02:00
showError ( tr ( " Settings issues " ) ,
tr ( " Arduino cannot run because it could not \ n " +
2014-08-21 19:47:33 +02:00
" create a folder to store your settings. " ) , null ) ;
}
}
return settingsFolder ;
}
2014-08-21 13:18:54 +02:00
static public File getSketchbookFolder ( ) {
2015-11-19 13:43:49 +01:00
String sketchBookPath = PreferencesData . get ( " sketchbook.path " ) ;
if ( getPortableFolder ( ) ! = null & & ! new File ( sketchBookPath ) . isAbsolute ( ) ) {
return new File ( getPortableFolder ( ) , sketchBookPath ) ;
}
return absoluteFile ( sketchBookPath ) ;
2014-08-21 13:18:54 +02:00
}
static public File getSketchbookHardwareFolder ( ) {
return new File ( getSketchbookFolder ( ) , " hardware " ) ;
}
2014-08-25 18:57:18 +02:00
static public File getSketchbookLibrariesFolder ( ) {
File libdir = new File ( getSketchbookFolder ( ) , " libraries " ) ;
if ( ! libdir . exists ( ) ) {
2015-05-21 16:47:50 +02:00
FileWriter freadme = null ;
2014-08-25 18:57:18 +02:00
try {
libdir . mkdirs ( ) ;
2015-05-21 16:47:50 +02:00
freadme = new FileWriter ( new File ( libdir , " readme.txt " ) ) ;
2015-08-05 09:04:53 +02:00
freadme . write ( tr ( " For information on installing libraries, see: " +
2015-05-20 17:10:06 +02:00
" http://www.arduino.cc/en/Guide/Libraries \ n " ) ) ;
2014-08-25 18:57:18 +02:00
} catch ( Exception e ) {
2015-05-21 16:47:50 +02:00
} finally {
IOUtils . closeQuietly ( freadme ) ;
2014-08-25 18:57:18 +02:00
}
}
return libdir ;
}
2014-08-26 11:27:08 +02:00
static public String getSketchbookPath ( ) {
// Get the sketchbook path, and make sure it's set properly
2014-08-26 12:19:53 +02:00
String sketchbookPath = PreferencesData . get ( " sketchbook.path " ) ;
2014-08-26 11:27:08 +02:00
// If a value is at least set, first check to see if the folder exists.
// If it doesn't, warn the user that the sketchbook folder is being reset.
if ( sketchbookPath ! = null ) {
File sketchbookFolder ;
2015-11-19 13:43:49 +01:00
if ( getPortableFolder ( ) ! = null & & ! new File ( sketchbookPath ) . isAbsolute ( ) ) {
2014-08-26 12:19:53 +02:00
sketchbookFolder = new File ( getPortableFolder ( ) , sketchbookPath ) ;
2015-11-19 13:43:49 +01:00
} else {
2014-08-26 11:27:08 +02:00
sketchbookFolder = absoluteFile ( sketchbookPath ) ;
2015-11-19 13:43:49 +01:00
}
2014-08-26 11:27:08 +02:00
if ( ! sketchbookFolder . exists ( ) ) {
2015-08-05 09:04:53 +02:00
showWarning ( tr ( " Sketchbook folder disappeared " ) ,
tr ( " The sketchbook folder no longer exists. \ n " +
2014-08-26 11:27:08 +02:00
" Arduino will switch to the default sketchbook \ n " +
" location, and create a new sketchbook folder if \ n " +
" necessary. Arduino will then stop talking about \ n " +
" himself in the third person. " ) , null ) ;
sketchbookPath = null ;
}
}
return sketchbookPath ;
}
2014-08-21 13:38:28 +02:00
public static TargetBoard getTargetBoard ( ) {
2014-05-01 16:17:43 +02:00
TargetPlatform targetPlatform = getTargetPlatform ( ) ;
if ( targetPlatform = = null )
return null ;
2014-08-22 12:47:43 +02:00
String boardId = PreferencesData . get ( " board " ) ;
2014-05-01 16:17:43 +02:00
return targetPlatform . getBoard ( boardId ) ;
2014-08-21 13:38:28 +02:00
}
2014-08-25 19:57:54 +02:00
/ * *
* Returns a specific TargetPackage
*
* @param packageName
* @return
* /
static public TargetPackage getTargetPackage ( String packageName ) {
return packages . get ( packageName ) ;
}
2014-08-21 13:18:54 +02:00
/ * *
* Returns the currently selected TargetPlatform .
*
* @return
* /
static public TargetPlatform getTargetPlatform ( ) {
2014-08-22 12:47:43 +02:00
String packageName = PreferencesData . get ( " target_package " ) ;
String platformName = PreferencesData . get ( " target_platform " ) ;
2014-08-21 13:18:54 +02:00
return getTargetPlatform ( packageName , platformName ) ;
}
/ * *
* Returns a specific TargetPlatform searching Package / Platform
*
* @param packageName
* @param platformName
* @return
* /
static public TargetPlatform getTargetPlatform ( String packageName ,
String platformName ) {
TargetPackage p = packages . get ( packageName ) ;
if ( p = = null )
return null ;
return p . get ( platformName ) ;
}
2014-08-25 18:57:18 +02:00
static public File getToolsFolder ( ) {
return toolsFolder ;
}
static public String getToolsPath ( ) {
return toolsFolder . getAbsolutePath ( ) ;
}
2014-08-21 14:06:25 +02:00
static public LibraryList getUserLibs ( ) {
2014-05-16 01:11:47 +02:00
LibraryList libs = BaseNoGui . librariesIndexer . getInstalledLibraries ( ) ;
return libs . filterLibrariesInSubfolder ( getSketchbookFolder ( ) ) ;
2014-08-21 14:06:25 +02:00
}
/ * *
* Given a folder , return a list of the header files in that folder ( but not
* the header files in its sub - folders , as those should be included from
* within the header files at the top - level ) .
* /
static public String [ ] headerListFromIncludePath ( File path ) throws IOException {
2015-05-20 01:36:11 +10:00
String [ ] list = path . list ( new OnlyFilesWithExtension ( " .h " , " .hh " , " .hpp " ) ) ;
2014-08-21 14:06:25 +02:00
if ( list = = null ) {
throw new IOException ( ) ;
}
return list ;
}
2014-05-16 00:53:57 +02:00
static public void init ( String [ ] args ) throws Exception {
2015-06-05 17:18:50 +02:00
CommandlineParser parser = new CommandlineParser ( args ) ;
parser . parseArgumentsPhase1 ( ) ;
2014-09-10 18:48:34 +02:00
String sketchbookPath = getSketchbookPath ( ) ;
// If no path is set, get the default sketchbook folder for this platform
if ( sketchbookPath = = null ) {
if ( BaseNoGui . getPortableFolder ( ) ! = null )
PreferencesData . set ( " sketchbook.path " , getPortableSketchbookFolder ( ) ) ;
else
2015-08-05 09:04:53 +02:00
showError ( tr ( " No sketchbook " ) , tr ( " Sketchbook path not defined " ) , null ) ;
2014-09-10 18:48:34 +02:00
}
2015-06-05 17:18:50 +02:00
2014-09-10 18:48:34 +02:00
BaseNoGui . initPackages ( ) ;
// Setup board-dependent variables.
onBoardOrPortChange ( ) ;
2015-06-05 17:18:50 +02:00
parser . parseArgumentsPhase2 ( ) ;
2014-09-10 18:48:34 +02:00
for ( String path : parser . getFilenames ( ) ) {
// Correctly resolve relative paths
File file = absoluteFile ( path ) ;
// Fix a problem with systems that use a non-ASCII languages. Paths are
// being passed in with 8.3 syntax, which makes the sketch loader code
// unhappy, since the sketch folder naming doesn't match up correctly.
// http://dev.processing.org/bugs/show_bug.cgi?id=1089
if ( OSUtils . isWindows ( ) ) {
try {
file = file . getCanonicalFile ( ) ;
} catch ( IOException e ) {
e . printStackTrace ( ) ;
}
}
if ( ! parser . isVerifyOrUploadMode ( ) & & ! parser . isGetPrefMode ( ) )
2015-08-05 09:04:53 +02:00
showError ( tr ( " Mode not supported " ) , tr ( " Only --verify, --upload or --get-pref are supported " ) , null ) ;
2014-09-10 18:48:34 +02:00
if ( ! parser . isForceSavePrefs ( ) )
PreferencesData . setDoSave ( false ) ;
if ( ! file . exists ( ) ) {
2015-08-05 09:04:53 +02:00
String mess = I18n . format ( tr ( " Failed to open sketch: \" {0} \" " ) , path ) ;
2014-09-10 18:48:34 +02:00
// Open failure is fatal in upload/verify mode
showError ( null , mess , 2 ) ;
}
}
// Save the preferences. For GUI mode, this happens in the quit
// handler, but for other modes we should also make sure to save
// them.
PreferencesData . save ( ) ;
if ( parser . isVerifyOrUploadMode ( ) ) {
// Set verbosity for command line build
PreferencesData . set ( " build.verbose " , " " + parser . isDoVerboseBuild ( ) ) ;
PreferencesData . set ( " upload.verbose " , " " + parser . isDoVerboseUpload ( ) ) ;
// Make sure these verbosity preferences are only for the
// current session
PreferencesData . setDoSave ( false ) ;
if ( parser . isUploadMode ( ) ) {
if ( parser . getFilenames ( ) . size ( ) ! = 1 )
{
2015-08-05 09:04:53 +02:00
showError ( tr ( " Multiple files not supported " ) , tr ( " The --upload option supports only one file at a time " ) , null ) ;
2014-09-10 18:48:34 +02:00
}
List < String > warningsAccumulator = new LinkedList < String > ( ) ;
boolean success = false ;
try {
2015-01-14 18:05:00 +01:00
// Editor constructor loads the sketch with handleOpenInternal() that
// creates a new Sketch that, in trun, calls load() inside its constructor
// This translates here as:
2014-09-10 18:48:34 +02:00
// SketchData data = new SketchData(file);
// File tempBuildFolder = getBuildFolder();
// data.load();
SketchData data = new SketchData ( absoluteFile ( parser . getFilenames ( ) . get ( 0 ) ) ) ;
2015-09-18 10:47:23 +02:00
File tempBuildFolder = getBuildFolder ( data ) ;
2014-09-10 18:48:34 +02:00
data . load ( ) ;
// Sketch.exportApplet()
2015-01-14 18:05:00 +01:00
// - calls Sketch.prepare() that calls Sketch.ensureExistence()
// - calls Sketch.build(verbose=false) that calls Sketch.ensureExistence(), set progressListener and calls Compiler.build()
// - calls Sketch.upload() (see later...)
2015-06-19 10:37:21 +02:00
if ( ! data . getFolder ( ) . exists ( ) ) {
2015-08-05 09:04:53 +02:00
showError ( tr ( " No sketch " ) , tr ( " Can't find the sketch in the specified path " ) , null ) ;
2015-06-19 10:37:21 +02:00
}
2015-08-31 16:05:23 +02:00
String suggestedClassName = new Compiler ( data , tempBuildFolder . getAbsolutePath ( ) ) . build ( null , false ) ;
2015-06-19 10:37:21 +02:00
if ( suggestedClassName = = null ) {
2015-08-05 09:04:53 +02:00
showError ( tr ( " Error while verifying " ) , tr ( " An error occurred while verifying the sketch " ) , null ) ;
2015-06-19 10:37:21 +02:00
}
2015-08-05 09:04:53 +02:00
showMessage ( tr ( " Done compiling " ) , tr ( " Done compiling " ) ) ;
2014-09-19 16:51:47 +02:00
2015-08-31 16:05:23 +02:00
Uploader uploader = new UploaderUtils ( ) . getUploaderByPreferences ( parser . isNoUploadPort ( ) ) ;
2015-01-14 18:05:00 +01:00
if ( uploader . requiresAuthorization ( ) & & ! PreferencesData . has ( uploader . getAuthorizationKey ( ) ) ) showError ( " ... " , " ... " , null ) ;
2014-09-10 18:48:34 +02:00
try {
2015-08-31 16:05:23 +02:00
success = new UploaderUtils ( ) . upload ( data , uploader , tempBuildFolder . getAbsolutePath ( ) , suggestedClassName , parser . isDoUseProgrammer ( ) , parser . isNoUploadPort ( ) , warningsAccumulator ) ;
2015-08-05 09:04:53 +02:00
showMessage ( tr ( " Done uploading " ) , tr ( " Done uploading " ) ) ;
2014-09-10 18:48:34 +02:00
} finally {
if ( uploader . requiresAuthorization ( ) & & ! success ) {
PreferencesData . remove ( uploader . getAuthorizationKey ( ) ) ;
}
}
} catch ( Exception e ) {
2015-08-05 09:04:53 +02:00
showError ( tr ( " Error while verifying/uploading " ) , tr ( " An error occurred while verifying/uploading the sketch " ) , e ) ;
2014-09-10 18:48:34 +02:00
}
for ( String warning : warningsAccumulator ) {
2015-08-05 09:04:53 +02:00
System . out . print ( tr ( " Warning " ) ) ;
2014-09-10 18:48:34 +02:00
System . out . print ( " : " ) ;
System . out . println ( warning ) ;
}
2015-08-05 09:04:53 +02:00
if ( ! success ) showError ( tr ( " Error while uploading " ) , tr ( " An error occurred while uploading the sketch " ) , null ) ;
2014-09-10 18:48:34 +02:00
} else {
for ( String path : parser . getFilenames ( ) )
{
try {
2015-01-14 18:05:00 +01:00
// Editor constructor loads sketch with handleOpenInternal() that
// creates a new Sketch that calls load() in its constructor
// This translates here as:
2014-09-10 18:48:34 +02:00
// SketchData data = new SketchData(file);
// File tempBuildFolder = getBuildFolder();
// data.load();
SketchData data = new SketchData ( absoluteFile ( path ) ) ;
2015-09-18 10:47:23 +02:00
File tempBuildFolder = getBuildFolder ( data ) ;
2014-09-10 18:48:34 +02:00
data . load ( ) ;
2015-01-14 18:05:00 +01:00
// Sketch.prepare() calls Sketch.ensureExistence()
// Sketch.build(verbose) calls Sketch.ensureExistence() and set progressListener and, finally, calls Compiler.build()
// This translates here as:
2014-09-10 18:48:34 +02:00
// if (!data.getFolder().exists()) showError(...);
// String ... = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, verbose);
2015-08-05 09:04:53 +02:00
if ( ! data . getFolder ( ) . exists ( ) ) showError ( tr ( " No sketch " ) , tr ( " Can't find the sketch in the specified path " ) , null ) ;
2015-08-31 16:05:23 +02:00
String suggestedClassName = new Compiler ( data , tempBuildFolder . getAbsolutePath ( ) ) . build ( null , false ) ;
2015-08-05 09:04:53 +02:00
if ( suggestedClassName = = null ) showError ( tr ( " Error while verifying " ) , tr ( " An error occurred while verifying the sketch " ) , null ) ;
showMessage ( tr ( " Done compiling " ) , tr ( " Done compiling " ) ) ;
2014-09-10 18:48:34 +02:00
} catch ( Exception e ) {
2015-08-05 09:04:53 +02:00
showError ( tr ( " Error while verifying " ) , tr ( " An error occurred while verifying the sketch " ) , e ) ;
2014-09-10 18:48:34 +02:00
}
}
}
// No errors exit gracefully
System . exit ( 0 ) ;
}
else if ( parser . isGetPrefMode ( ) ) {
2015-05-29 15:15:08 +02:00
dumpPrefs ( parser ) ;
}
}
protected static void dumpPrefs ( CommandlineParser parser ) {
if ( parser . getGetPref ( ) ! = null ) {
2014-09-10 18:48:34 +02:00
String value = PreferencesData . get ( parser . getGetPref ( ) , null ) ;
if ( value ! = null ) {
System . out . println ( value ) ;
System . exit ( 0 ) ;
} else {
System . exit ( 4 ) ;
}
2015-05-29 15:15:08 +02:00
} else {
System . out . println ( " #PREFDUMP# " ) ;
PreferencesMap prefs = PreferencesData . getMap ( ) ;
for ( Map . Entry < String , String > entry : prefs . entrySet ( ) ) {
System . out . println ( entry . getKey ( ) + " = " + entry . getValue ( ) ) ;
}
System . exit ( 0 ) ;
2014-09-10 18:48:34 +02:00
}
}
2014-08-21 18:43:13 +02:00
static public void initLogger ( ) {
System . setProperty ( LogFactoryImpl . LOG_PROPERTY , NoOpLog . class . getCanonicalName ( ) ) ;
Logger . getLogger ( " javax.jmdns " ) . setLevel ( Level . OFF ) ;
}
2014-05-16 00:53:57 +02:00
static public void initPackages ( ) throws Exception {
2015-07-03 16:00:57 +02:00
indexer = new ContributionsIndexer ( BaseNoGui . getSettingsFolder ( ) , BaseNoGui . getPlatform ( ) , new GPGDetachedSignatureVerifier ( ) ) ;
2015-04-29 15:11:58 +02:00
File indexFile = indexer . getIndexFile ( " package_index.json " ) ;
2015-04-23 11:10:54 +02:00
File defaultPackageJsonFile = new File ( getContentFile ( " dist " ) , " package_index.json " ) ;
if ( ! indexFile . isFile ( ) | | ( defaultPackageJsonFile . isFile ( ) & & defaultPackageJsonFile . lastModified ( ) > indexFile . lastModified ( ) ) ) {
FileUtils . copyFile ( defaultPackageJsonFile , indexFile ) ;
} else if ( ! indexFile . isFile ( ) ) {
// Otherwise create an empty packages index
FileOutputStream out = null ;
try {
out = new FileOutputStream ( indexFile ) ;
out . write ( " { \" packages \" : [ ] } " . getBytes ( ) ) ;
} finally {
2015-05-21 16:47:50 +02:00
IOUtils . closeQuietly ( out ) ;
2014-05-16 01:08:05 +02:00
}
}
2015-04-30 11:17:27 +02:00
2015-04-30 11:23:01 +02:00
File indexSignatureFile = indexer . getIndexFile ( " package_index.json.sig " ) ;
File defaultPackageJsonSignatureFile = new File ( getContentFile ( " dist " ) , " package_index.json.sig " ) ;
if ( ! indexSignatureFile . isFile ( ) | | ( defaultPackageJsonSignatureFile . isFile ( ) & & defaultPackageJsonSignatureFile . lastModified ( ) > indexSignatureFile . lastModified ( ) ) ) {
FileUtils . copyFile ( defaultPackageJsonSignatureFile , indexSignatureFile ) ;
}
2015-04-30 11:17:27 +02:00
try {
indexer . parseIndex ( ) ;
2015-09-25 12:54:50 +02:00
} catch ( JsonProcessingException | SignatureVerificationFailedException e ) {
2015-05-04 17:44:16 +02:00
FileUtils . deleteIfExists ( indexFile ) ;
FileUtils . deleteIfExists ( indexSignatureFile ) ;
2015-04-30 11:17:27 +02:00
throw e ;
}
2015-03-31 17:00:01 +02:00
indexer . syncWithFilesystem ( getHardwareFolder ( ) ) ;
2014-05-16 01:08:05 +02:00
2015-05-29 14:19:15 +02:00
packages = new LinkedHashMap < String , TargetPackage > ( ) ;
2014-08-21 13:18:54 +02:00
loadHardware ( getHardwareFolder ( ) ) ;
2014-05-16 00:53:57 +02:00
loadContributedHardware ( indexer ) ;
2015-05-29 14:19:15 +02:00
loadHardware ( getSketchbookHardwareFolder ( ) ) ;
2015-07-01 16:19:41 +02:00
createToolPreferences ( indexer . getInstalledTools ( ) , true ) ;
2014-10-17 00:05:36 +02:00
2015-11-24 16:14:16 +01:00
librariesIndexer = new LibrariesIndexer ( BaseNoGui . getSettingsFolder ( ) ) ;
2014-05-16 18:44:33 +02:00
File librariesIndexFile = librariesIndexer . getIndexFile ( ) ;
2015-09-25 12:54:50 +02:00
copyStockLibraryIndexIfUpstreamIsMissing ( librariesIndexFile ) ;
try {
librariesIndexer . parseIndex ( ) ;
} catch ( JsonProcessingException e ) {
FileUtils . deleteIfExists ( librariesIndexFile ) ;
copyStockLibraryIndexIfUpstreamIsMissing ( librariesIndexFile ) ;
librariesIndexer . parseIndex ( ) ;
}
}
private static void copyStockLibraryIndexIfUpstreamIsMissing ( File librariesIndexFile ) throws IOException {
2015-10-28 16:29:05 +01:00
File defaultLibraryJsonFile = new File ( getContentFile ( " dist " ) , " library_index.json " ) ;
if ( ! librariesIndexFile . isFile ( ) | | ( defaultLibraryJsonFile . isFile ( ) & & defaultLibraryJsonFile . lastModified ( ) > librariesIndexFile . lastModified ( ) ) ) {
2015-03-26 16:02:33 +01:00
if ( defaultLibraryJsonFile . isFile ( ) ) {
FileUtils . copyFile ( defaultLibraryJsonFile , librariesIndexFile ) ;
} else {
2015-05-04 15:44:34 +02:00
FileOutputStream out = null ;
2015-03-26 16:02:33 +01:00
try {
// Otherwise create an empty packages index
2015-05-04 15:44:34 +02:00
out = new FileOutputStream ( librariesIndexFile ) ;
2015-03-26 16:02:33 +01:00
out . write ( " { \" libraries \" : [ ] } " . getBytes ( ) ) ;
} catch ( IOException e ) {
e . printStackTrace ( ) ;
2015-05-04 15:44:34 +02:00
} finally {
2015-05-21 16:47:50 +02:00
IOUtils . closeQuietly ( out ) ;
2015-03-26 16:02:33 +01:00
}
2014-05-16 18:44:33 +02:00
}
}
2014-08-21 13:18:54 +02:00
}
2014-08-21 13:33:46 +02:00
static protected void initPlatform ( ) {
try {
Class < ? > platformClass = Class . forName ( " processing.app.Platform " ) ;
if ( OSUtils . isMacOS ( ) ) {
platformClass = Class . forName ( " processing.app.macosx.Platform " ) ;
} else if ( OSUtils . isWindows ( ) ) {
platformClass = Class . forName ( " processing.app.windows.Platform " ) ;
} else if ( OSUtils . isLinux ( ) ) {
platformClass = Class . forName ( " processing.app.linux.Platform " ) ;
}
platform = ( Platform ) platformClass . newInstance ( ) ;
} catch ( Exception e ) {
2015-08-05 09:04:53 +02:00
showError ( tr ( " Problem Setting the Platform " ) ,
tr ( " An unknown error occurred while trying to load \ n " +
2014-08-21 19:55:50 +02:00
" platform-specific code for your machine. " ) , e ) ;
2014-08-21 13:33:46 +02:00
}
}
2014-08-21 13:18:54 +02:00
static public void initPortableFolder ( ) {
// Portable folder
portableFolder = getContentFile ( " portable " ) ;
2015-11-19 13:43:49 +01:00
if ( ! portableFolder . exists ( ) ) {
2014-08-21 13:18:54 +02:00
portableFolder = null ;
2015-11-19 13:43:49 +01:00
}
2014-08-21 13:18:54 +02:00
}
2014-08-21 18:43:13 +02:00
static public void initVersion ( ) {
// help 3rd party installers find the correct hardware path
2014-08-22 12:47:43 +02:00
PreferencesData . set ( " last.ide. " + VERSION_NAME + " .hardwarepath " , getHardwarePath ( ) ) ;
PreferencesData . set ( " last.ide. " + VERSION_NAME + " .daterun " , " " + ( new Date ( ) ) . getTime ( ) / 1000 ) ;
2014-08-21 18:43:13 +02:00
}
2014-08-22 18:27:50 +02:00
/ * *
* Return true if the name is valid for a Processing sketch .
* /
static public boolean isSanitaryName ( String name ) {
return sanitizeName ( name ) . equals ( name ) ;
}
2014-08-21 13:18:54 +02:00
static protected void loadHardware ( File folder ) {
2015-09-25 12:04:55 +02:00
if ( ! folder . isDirectory ( ) ) {
return ;
}
2014-08-21 13:18:54 +02:00
String list [ ] = folder . list ( new OnlyDirs ( ) ) ;
// if a bad folder or something like that, this might come back null
2015-09-25 12:04:55 +02:00
if ( list = = null ) {
return ;
}
2014-08-21 13:18:54 +02:00
// alphabetize list, since it's not always alpha order
// replaced hella slow bubble sort with this feller for 0093
Arrays . sort ( list , String . CASE_INSENSITIVE_ORDER ) ;
for ( String target : list ) {
// Skip reserved 'tools' folder.
2015-09-25 12:04:55 +02:00
if ( target . equals ( " tools " ) ) {
2014-08-21 13:18:54 +02:00
continue ;
2015-09-25 12:04:55 +02:00
}
2014-08-21 13:18:54 +02:00
File subfolder = new File ( folder , target ) ;
2015-09-25 12:04:55 +02:00
TargetPackage targetPackage ;
if ( packages . containsKey ( target ) ) {
targetPackage = packages . get ( target ) ;
} else {
targetPackage = new LegacyTargetPackage ( target ) ;
2015-09-25 12:28:57 +02:00
packages . put ( target , targetPackage ) ;
2015-09-25 12:04:55 +02:00
}
2014-08-21 13:18:54 +02:00
try {
2015-09-25 12:04:55 +02:00
loadTargetPackage ( targetPackage , subfolder ) ;
2014-08-21 13:18:54 +02:00
} catch ( TargetPlatformException e ) {
2015-03-31 17:00:01 +02:00
System . out . println ( " WARNING: Error loading hardware folder " + new File ( folder , target ) ) ;
2014-08-21 13:18:54 +02:00
System . out . println ( " " + e . getMessage ( ) ) ;
}
}
}
2015-09-25 12:04:55 +02:00
private static void loadTargetPackage ( TargetPackage targetPackage , File _folder ) throws TargetPlatformException {
File [ ] folders = _folder . listFiles ( ONLY_DIRS ) ;
if ( folders = = null ) {
return ;
}
for ( File subFolder : folders ) {
if ( ! subFolder . exists ( ) | | ! subFolder . canRead ( ) ) {
continue ;
}
String arch = subFolder . getName ( ) ;
try {
TargetPlatform platform = new LegacyTargetPlatform ( arch , subFolder , targetPackage ) ;
targetPackage . getPlatforms ( ) . put ( arch , platform ) ;
} catch ( TargetPlatformException e ) {
System . err . println ( e . getMessage ( ) ) ;
}
}
if ( targetPackage . getPlatforms ( ) . size ( ) = = 0 ) {
throw new TargetPlatformException ( I18n . format ( tr ( " No valid hardware definitions found in folder {0}. " ) , _folder . getName ( ) ) ) ;
}
}
2014-08-22 18:35:15 +02:00
/ * *
* Grab the contents of a file as a string .
* /
static public String loadFile ( File file ) throws IOException {
String [ ] contents = PApplet . loadStrings ( file ) ;
if ( contents = = null ) return null ;
return PApplet . join ( contents , " \ n " ) ;
}
2014-09-10 18:48:34 +02:00
static public void main ( String args [ ] ) throws Exception {
2015-06-03 10:24:07 +02:00
if ( args . length = = 0 ) {
2015-08-05 09:04:53 +02:00
showError ( tr ( " No parameters " ) , tr ( " No command line parameters found " ) , null ) ;
2015-06-03 10:24:07 +02:00
}
System . setProperty ( " java.net.useSystemProxies " , " true " ) ;
2014-09-19 16:51:47 +02:00
2015-11-27 15:06:40 +01:00
Thread deleteFilesOnShutdownThread = new Thread ( DeleteFilesOnShutdown . INSTANCE ) ;
deleteFilesOnShutdownThread . setName ( " DeleteFilesOnShutdown " ) ;
Runtime . getRuntime ( ) . addShutdownHook ( deleteFilesOnShutdownThread ) ;
2015-04-15 10:19:39 +02:00
2014-09-10 18:48:34 +02:00
initPlatform ( ) ;
2015-05-20 16:13:48 +02:00
getPlatform ( ) . init ( ) ;
2014-09-10 18:48:34 +02:00
initPortableFolder ( ) ;
2014-09-23 10:55:47 +02:00
initParameters ( args ) ;
2015-06-03 17:27:57 +02:00
checkInstallationFolder ( ) ;
2014-09-10 18:48:34 +02:00
init ( args ) ;
}
2015-06-03 17:27:57 +02:00
public static void checkInstallationFolder ( ) {
if ( isIDEInstalledIntoSettingsFolder ( ) ) {
2015-08-05 09:04:53 +02:00
showError ( tr ( " Incorrect IDE installation folder " ) , tr ( " Your copy of the IDE is installed in a subfolder of your settings folder. \ nPlease move the IDE to another folder. " ) , 10 ) ;
2015-06-03 17:27:57 +02:00
}
if ( isIDEInstalledIntoSketchbookFolder ( ) ) {
2015-08-05 09:04:53 +02:00
showError ( tr ( " Incorrect IDE installation folder " ) , tr ( " Your copy of the IDE is installed in a subfolder of your sketchbook. \ nPlease move the IDE to another folder. " ) , 10 ) ;
2015-06-03 17:27:57 +02:00
}
}
public static boolean isIDEInstalledIntoSketchbookFolder ( ) {
return PreferencesData . has ( " sketchbook.path " ) & & FileUtils . isSubDirectory ( new File ( PreferencesData . get ( " sketchbook.path " ) ) , new File ( PreferencesData . get ( " runtime.ide.path " ) ) ) ;
}
public static boolean isIDEInstalledIntoSettingsFolder ( ) {
try {
return FileUtils . isSubDirectory ( BaseNoGui . getPlatform ( ) . getSettingsFolder ( ) , new File ( PreferencesData . get ( " runtime.ide.path " ) ) ) ;
} catch ( Exception e ) {
return false ;
}
}
2014-08-25 18:57:18 +02:00
static public void onBoardOrPortChange ( ) {
examplesFolder = getContentFile ( " examples " ) ;
toolsFolder = getContentFile ( " tools " ) ;
librariesFolders = new ArrayList < File > ( ) ;
2014-10-17 00:05:36 +02:00
// Add IDE libraries folder
2014-08-25 18:57:18 +02:00
librariesFolders . add ( getContentFile ( " libraries " ) ) ;
2014-05-01 16:17:43 +02:00
TargetPlatform targetPlatform = getTargetPlatform ( ) ;
if ( targetPlatform ! = null ) {
2015-02-12 17:27:58 +01:00
String core = getBoardPreferences ( ) . get ( " build.core " , " arduino " ) ;
2014-05-01 16:17:43 +02:00
if ( core . contains ( " : " ) ) {
String referencedCore = core . split ( " : " ) [ 0 ] ;
TargetPlatform referencedPlatform = getTargetPlatform ( referencedCore , targetPlatform . getId ( ) ) ;
if ( referencedPlatform ! = null ) {
File referencedPlatformFolder = referencedPlatform . getFolder ( ) ;
2014-10-17 00:05:36 +02:00
// Add libraries folder for the referenced platform
2014-05-16 01:11:47 +02:00
File folder = new File ( referencedPlatformFolder , " libraries " ) ;
librariesFolders . add ( folder ) ;
2014-05-01 16:17:43 +02:00
}
2014-08-25 18:57:18 +02:00
}
2014-05-01 16:17:43 +02:00
File platformFolder = targetPlatform . getFolder ( ) ;
2014-10-17 00:05:36 +02:00
// Add libraries folder for the selected platform
2014-05-16 01:11:47 +02:00
File folder = new File ( platformFolder , " libraries " ) ;
librariesFolders . add ( folder ) ;
2014-08-25 18:57:18 +02:00
}
2014-10-17 00:05:36 +02:00
// Add libraries folder for the sketchbook
librariesFolders . add ( getSketchbookLibrariesFolder ( ) ) ;
2014-08-25 18:57:18 +02:00
// Scan for libraries in each library folder.
// Libraries located in the latest folders on the list can override
// other libraries with the same name.
2015-03-24 10:54:06 +01:00
BaseNoGui . librariesIndexer . setSketchbookLibrariesFolder ( getSketchbookLibrariesFolder ( ) ) ;
BaseNoGui . librariesIndexer . setLibrariesFolders ( librariesFolders ) ;
BaseNoGui . librariesIndexer . rescanLibraries ( ) ;
2014-08-25 18:57:18 +02:00
populateImportToLibraryTable ( ) ;
}
2015-06-10 15:42:47 +02:00
static protected void loadContributedHardware ( ContributionsIndexer indexer ) {
2014-05-16 00:53:57 +02:00
for ( TargetPackage pack : indexer . createTargetPackages ( ) ) {
packages . put ( pack . getId ( ) , pack ) ;
}
}
2015-03-05 17:42:26 +01:00
2015-07-01 16:19:41 +02:00
public static void createToolPreferences ( Collection < ContributedTool > installedTools , boolean removeOldKeys ) {
String prefix = " runtime.tools. " ;
if ( removeOldKeys ) {
PreferencesData . removeAllKeysWithPrefix ( prefix ) ;
}
2015-02-16 12:42:48 +01:00
2015-07-01 16:19:41 +02:00
for ( ContributedTool tool : installedTools ) {
2015-05-22 15:42:05 +02:00
File installedFolder = tool . getDownloadableContribution ( getPlatform ( ) ) . getInstalledFolder ( ) ;
2015-07-09 15:16:19 +02:00
String absolutePath ;
2015-05-04 17:28:39 +02:00
if ( installedFolder ! = null ) {
2015-07-09 15:16:19 +02:00
absolutePath = installedFolder . getAbsolutePath ( ) ;
} else {
absolutePath = Constants . PREF_REMOVE_PLACEHOLDER ;
2015-05-04 17:28:39 +02:00
}
2015-07-09 15:16:19 +02:00
PreferencesData . set ( prefix + tool . getName ( ) + " .path " , absolutePath ) ;
PreferencesData . set ( prefix + tool . getName ( ) + " - " + tool . getVersion ( ) + " .path " , absolutePath ) ;
2015-02-16 12:42:48 +01:00
}
}
2014-08-22 13:41:41 +02:00
static public void populateImportToLibraryTable ( ) {
2015-03-30 10:24:18 -07:00
// Populate importToLibraryTable. Each header filename maps to
// a list of libraries. Compiler.java will use only the first
// library on each list. The others are used only to advise
// user of ambiguously matched and duplicate libraries.
importToLibraryTable = new HashMap < String , LibraryList > ( ) ;
2014-05-16 01:11:47 +02:00
for ( UserLibrary lib : librariesIndexer . getInstalledLibraries ( ) ) {
2014-08-22 13:41:41 +02:00
try {
String headers [ ] = headerListFromIncludePath ( lib . getSrcFolder ( ) ) ;
for ( String header : headers ) {
2015-03-30 10:24:18 -07:00
LibraryList list = importToLibraryTable . get ( header ) ;
if ( list = = null ) {
// This is the first library found with this header
list = new LibraryList ( ) ;
list . addFirst ( lib ) ;
importToLibraryTable . put ( header , list ) ;
} else {
UserLibrary old = list . peekFirst ( ) ;
boolean useThisLib = true ;
2015-02-23 03:26:07 -08:00
// This is the case where 2 libraries have a .h header
// with the same name. We must decide which library to
// use when a sketch has #include "name.h"
//
// When all other factors are equal, "libName" is
// used in preference to "oldName", because getLibraries()
// gives the library list in order from less specific to
// more specific locations.
//
// But often one library is more clearly the user's
// intention to use. Many cases are tested, always first
// for "libName", then for "oldName".
//
String name = header . substring ( 0 , header . length ( ) - 2 ) ; // name without ".h"
2014-10-17 00:05:36 +02:00
String oldName = old . getInstalledFolder ( ) . getName ( ) ; // just the library folder name
String libName = lib . getInstalledFolder ( ) . getName ( ) ; // just the library folder name
2015-02-23 03:26:07 -08:00
//System.out.println("name conflict: " + name);
2015-03-30 10:24:18 -07:00
//System.out.println(" old = " + oldName + " -> " + old.getInstalledFolder().getPath());
//System.out.println(" new = " + libName + " -> " + lib.getInstalledFolder().getPath());
2015-02-23 03:26:07 -08:00
String name_lc = name . toLowerCase ( ) ;
String oldName_lc = oldName . toLowerCase ( ) ;
String libName_lc = libName . toLowerCase ( ) ;
// always favor a perfect name match
if ( libName . equals ( name ) ) {
} else if ( oldName . equals ( name ) ) {
2015-03-30 10:24:18 -07:00
useThisLib = false ;
2015-02-23 03:26:07 -08:00
// check for "-master" appended (zip file from github)
} else if ( libName . equals ( name + " -master " ) ) {
} else if ( oldName . equals ( name + " -master " ) ) {
2015-03-30 10:24:18 -07:00
useThisLib = false ;
2015-02-23 03:26:07 -08:00
// next, favor a match with other stuff appended
} else if ( libName . startsWith ( name ) ) {
} else if ( oldName . startsWith ( name ) ) {
2015-03-30 10:24:18 -07:00
useThisLib = false ;
2015-02-23 03:26:07 -08:00
// otherwise, favor a match with stuff prepended
} else if ( libName . endsWith ( name ) ) {
} else if ( oldName . endsWith ( name ) ) {
2015-03-30 10:24:18 -07:00
useThisLib = false ;
2015-02-23 03:26:07 -08:00
// as a last resort, match if stuff prepended and appended
} else if ( libName . contains ( name ) ) {
} else if ( oldName . contains ( name ) ) {
2015-03-30 10:24:18 -07:00
useThisLib = false ;
2015-02-23 03:26:07 -08:00
// repeat all the above tests, with case insensitive matching
} else if ( libName_lc . equals ( name_lc ) ) {
} else if ( oldName_lc . equals ( name_lc ) ) {
2015-03-30 10:24:18 -07:00
useThisLib = false ;
2015-02-23 03:26:07 -08:00
} else if ( libName_lc . equals ( name_lc + " -master " ) ) {
} else if ( oldName_lc . equals ( name_lc + " -master " ) ) {
2015-03-30 10:24:18 -07:00
useThisLib = false ;
2015-02-23 03:26:07 -08:00
} else if ( libName_lc . startsWith ( name_lc ) ) {
} else if ( oldName_lc . startsWith ( name_lc ) ) {
2015-03-30 10:24:18 -07:00
useThisLib = false ;
2015-02-23 03:26:07 -08:00
} else if ( libName_lc . endsWith ( name_lc ) ) {
} else if ( oldName_lc . endsWith ( name_lc ) ) {
2015-03-30 10:24:18 -07:00
useThisLib = false ;
2015-02-23 03:26:07 -08:00
} else if ( libName_lc . contains ( name_lc ) ) {
} else if ( oldName_lc . contains ( name_lc ) ) {
2015-03-30 10:24:18 -07:00
useThisLib = false ;
2015-02-23 03:26:07 -08:00
} else {
// none of these tests matched, so just default to "libName".
}
2015-03-30 10:24:18 -07:00
if ( useThisLib ) {
list . addFirst ( lib ) ;
} else {
list . addLast ( lib ) ;
}
2014-08-22 13:41:41 +02:00
}
}
} catch ( IOException e ) {
2015-08-05 09:04:53 +02:00
showWarning ( tr ( " Error " ) , I18n
2014-08-22 13:41:41 +02:00
. format ( " Unable to list header files in {0} " , lib . getSrcFolder ( ) ) , e ) ;
}
}
2015-03-30 10:24:18 -07:00
// repeat for ALL libraries, to pick up duplicates not visible normally.
// any new libraries found here are NEVER used, but they are added to the
// end of already-found headers, to allow Compiler to report them if
// the sketch tries to use them.
for ( UserLibrary lib : librariesIndexer . getInstalledLibrariesWithDuplicates ( ) ) {
try {
String headers [ ] = headerListFromIncludePath ( lib . getSrcFolder ( ) ) ;
for ( String header : headers ) {
LibraryList list = importToLibraryTable . get ( header ) ;
if ( list ! = null ) {
if ( ! ( list . hasLibrary ( lib ) ) ) {
list . addLast ( lib ) ;
//System.out.println(" duplicate lib: " + lib.getInstalledFolder().getPath());
}
}
}
} catch ( IOException e ) {
}
}
2014-08-21 14:06:25 +02:00
}
2015-12-01 11:36:45 +01:00
static public void initParameters ( String args [ ] ) throws Exception {
2014-08-21 18:43:13 +02:00
String preferencesFile = null ;
// Do a first pass over the commandline arguments, the rest of them
// will be processed by the Base constructor. Note that this loop
// does not look at the last element of args, to prevent crashing
// when no parameter was specified to an option. Later, Base() will
// then show an error for these.
for ( int i = 0 ; i < args . length - 1 ; i + + ) {
if ( args [ i ] . equals ( " --preferences-file " ) ) {
+ + i ;
preferencesFile = args [ i ] ;
continue ;
}
}
// run static initialization that grabs all the prefs
2014-08-22 12:47:43 +02:00
PreferencesData . init ( absoluteFile ( preferencesFile ) ) ;
2014-08-21 18:43:13 +02:00
}
2014-08-22 18:12:34 +02:00
/ * *
* Recursively remove all files within a directory ,
* used with removeDir ( ) , or when the contents of a dir
* should be removed , but not the directory itself .
* ( i . e . when cleaning temp files from lib / build )
* /
static public void removeDescendants ( File dir ) {
if ( ! dir . exists ( ) ) return ;
String files [ ] = dir . list ( ) ;
2015-05-20 16:32:27 +02:00
if ( files = = null ) {
return ;
}
for ( String file : files ) {
if ( file . equals ( " . " ) | | file . equals ( " .. " ) ) continue ;
File dead = new File ( dir , file ) ;
2014-08-22 18:12:34 +02:00
if ( ! dead . isDirectory ( ) ) {
2014-08-22 18:27:50 +02:00
if ( ! PreferencesData . getBoolean ( " compiler.save_build_files " ) ) {
2014-08-22 18:12:34 +02:00
if ( ! dead . delete ( ) ) {
// temporarily disabled
2015-08-05 09:04:53 +02:00
System . err . println ( I18n . format ( tr ( " Could not delete {0} " ) , dead ) ) ;
2014-08-22 18:12:34 +02:00
}
}
} else {
removeDir ( dead ) ;
//dead.delete();
}
}
}
/ * *
* Remove all files in a directory and the directory itself .
* /
static public void removeDir ( File dir ) {
if ( dir . exists ( ) ) {
removeDescendants ( dir ) ;
if ( ! dir . delete ( ) ) {
2015-08-05 09:04:53 +02:00
System . err . println ( I18n . format ( tr ( " Could not delete {0} " ) , dir ) ) ;
2014-08-22 18:12:34 +02:00
}
}
}
2014-08-22 18:27:50 +02:00
/ * *
* Produce a sanitized name that fits our standards for likely to work .
* < p / >
* Java classes have a wider range of names that are technically allowed
* ( supposedly any Unicode name ) than what we support . The reason for
* going more narrow is to avoid situations with text encodings and
* converting during the process of moving files between operating
* systems , i . e . uploading from a Windows machine to a Linux server ,
* or reading a FAT32 partition in OS X and using a thumb drive .
* < p / >
* This helper function replaces everything but A - Z , a - z , and 0 - 9 with
* underscores . Also disallows starting the sketch name with a digit .
* /
static public String sanitizeName ( String origName ) {
char c [ ] = origName . toCharArray ( ) ;
StringBuffer buffer = new StringBuffer ( ) ;
// can't lead with a digit, so start with an underscore
if ( ( c [ 0 ] > = '0' ) & & ( c [ 0 ] < = '9' ) ) {
buffer . append ( '_' ) ;
}
for ( int i = 0 ; i < c . length ; i + + ) {
if ( ( ( c [ i ] > = '0' ) & & ( c [ i ] < = '9' ) ) | |
( ( c [ i ] > = 'a' ) & & ( c [ i ] < = 'z' ) ) | |
( ( c [ i ] > = 'A' ) & & ( c [ i ] < = 'Z' ) ) | |
( ( i > 0 ) & & ( c [ i ] = = '-' ) ) | |
( ( i > 0 ) & & ( c [ i ] = = '.' ) ) ) {
buffer . append ( c [ i ] ) ;
} else {
buffer . append ( '_' ) ;
}
}
// let's not be ridiculous about the length of filenames.
// in fact, Mac OS 9 can handle 255 chars, though it can't really
// deal with filenames longer than 31 chars in the Finder.
// but limiting to that for sketches would mean setting the
// upper-bound on the character limit here to 25 characters
// (to handle the base name + ".class")
if ( buffer . length ( ) > 63 ) {
buffer . setLength ( 63 ) ;
}
return buffer . toString ( ) ;
}
2014-08-21 13:43:10 +02:00
/ * *
* Spew the contents of a String object out to a file .
* /
static public void saveFile ( String str , File file ) throws IOException {
File temp = File . createTempFile ( file . getName ( ) , null , file . getParentFile ( ) ) ;
PApplet . saveStrings ( temp , new String [ ] { str } ) ;
if ( file . exists ( ) ) {
boolean result = file . delete ( ) ;
if ( ! result ) {
throw new IOException (
I18n . format (
2015-08-05 09:04:53 +02:00
tr ( " Could not remove old version of {0} " ) ,
2014-08-21 13:43:10 +02:00
file . getAbsolutePath ( ) ) ) ;
}
}
boolean result = temp . renameTo ( file ) ;
if ( ! result ) {
throw new IOException (
I18n . format (
2015-08-05 09:04:53 +02:00
tr ( " Could not replace {0} " ) ,
2014-08-21 13:43:10 +02:00
file . getAbsolutePath ( ) ) ) ;
}
}
2014-08-26 14:03:17 +02:00
static public void selectBoard ( TargetBoard targetBoard ) {
2014-08-25 19:57:54 +02:00
TargetPlatform targetPlatform = targetBoard . getContainerPlatform ( ) ;
TargetPackage targetPackage = targetPlatform . getContainerPackage ( ) ;
PreferencesData . set ( " target_package " , targetPackage . getId ( ) ) ;
PreferencesData . set ( " target_platform " , targetPlatform . getId ( ) ) ;
PreferencesData . set ( " board " , targetBoard . getId ( ) ) ;
File platformFolder = targetPlatform . getFolder ( ) ;
PreferencesData . set ( " runtime.platform.path " , platformFolder . getAbsolutePath ( ) ) ;
PreferencesData . set ( " runtime.hardware.path " , platformFolder . getParentFile ( ) . getAbsolutePath ( ) ) ;
}
public static void selectSerialPort ( String port ) {
PreferencesData . set ( " serial.port " , port ) ;
2015-06-01 11:27:52 +02:00
String portFile = port ;
if ( port . startsWith ( " /dev/ " ) ) {
portFile = portFile . substring ( 5 ) ;
}
PreferencesData . set ( " serial.port.file " , portFile ) ;
2014-08-25 19:57:54 +02:00
}
2014-08-25 12:34:50 +02:00
static public void showError ( String title , String message , int exit_code ) {
showError ( title , message , null , exit_code ) ;
}
2014-08-21 19:47:33 +02:00
static public void showError ( String title , String message , Throwable e ) {
notifier . showError ( title , message , e , 1 ) ;
}
/ * *
* Show an error message that ' s actually fatal to the program .
* This is an error that can ' t be recovered . Use showWarning ( )
* for errors that allow P5 to continue running .
* /
static public void showError ( String title , String message , Throwable e , int exit_code ) {
notifier . showError ( title , message , e , exit_code ) ;
}
2014-08-21 19:55:50 +02:00
/ * *
* " No cookie for you " type messages . Nothing fatal or all that
* much of a bummer , but something to notify the user about .
* /
static public void showMessage ( String title , String message ) {
notifier . showMessage ( title , message ) ;
}
2014-08-21 20:25:23 +02:00
/ * *
* Non - fatal error message with optional stack trace side dish .
* /
static public void showWarning ( String title , String message , Exception e ) {
notifier . showWarning ( title , message , e ) ;
}
2014-08-21 12:23:42 +02:00
}