The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

319 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. #include "../Project/jucer_Project.h"
  18. #include "../Project/jucer_Module.h"
  19. #include "jucer_CommandLine.h"
  20. //==============================================================================
  21. namespace
  22. {
  23. void hideDockIcon()
  24. {
  25. #if JUCE_MAC
  26. Process::setDockIconVisible (false);
  27. #endif
  28. }
  29. File getFile (const String& filename)
  30. {
  31. return File::getCurrentWorkingDirectory().getChildFile (filename.unquoted());
  32. }
  33. bool checkArgumentCount (const StringArray& args, int minNumArgs)
  34. {
  35. if (args.size() < minNumArgs)
  36. {
  37. std::cout << "Not enough arguments!" << std::endl;
  38. return false;
  39. }
  40. return true;
  41. }
  42. //==============================================================================
  43. /* Running a command-line of the form "introjucer --resave foobar.jucer" will try to load
  44. that project and re-export all of its targets.
  45. */
  46. int resaveProject (const StringArray& args, bool justSaveResources)
  47. {
  48. hideDockIcon();
  49. if (! checkArgumentCount (args, 2))
  50. return 1;
  51. const File projectFile (getFile (args[1]));
  52. if (! projectFile.exists())
  53. {
  54. std::cout << "The file " << projectFile.getFullPathName() << " doesn't exist!" << std::endl;
  55. return 1;
  56. }
  57. if (! projectFile.hasFileExtension (Project::projectFileExtension))
  58. {
  59. std::cout << projectFile.getFullPathName() << " isn't a valid jucer project file!" << std::endl;
  60. return 1;
  61. }
  62. Project proj (projectFile);
  63. if (! proj.loadFrom (projectFile, true))
  64. {
  65. std::cout << "Failed to load the project file: " << projectFile.getFullPathName() << std::endl;
  66. return 1;
  67. }
  68. std::cout << (justSaveResources ? "The Introjucer - Re-saving project resources: "
  69. : "The Introjucer - Re-saving file: ")
  70. << projectFile.getFullPathName() << std::endl;
  71. Result error (justSaveResources ? proj.saveResourcesOnly (projectFile)
  72. : proj.saveProject (projectFile, true));
  73. if (error.failed())
  74. {
  75. std::cout << "Error when saving: " << error.getErrorMessage() << std::endl;
  76. return 1;
  77. }
  78. return 0;
  79. }
  80. //==============================================================================
  81. String getModulePackageName (const LibraryModule& module)
  82. {
  83. return module.getID() + ".jucemodule";
  84. }
  85. int zipModule (const File& targetFolder, const File& moduleFolder)
  86. {
  87. jassert (targetFolder.isDirectory());
  88. const File moduleFolderParent (moduleFolder.getParentDirectory());
  89. LibraryModule module (moduleFolder.getChildFile (LibraryModule::getInfoFileName()));
  90. if (! module.isValid())
  91. {
  92. std::cout << moduleFolder.getFullPathName() << " is not a valid module folder!" << std::endl;
  93. return 1;
  94. }
  95. const File targetFile (targetFolder.getChildFile (getModulePackageName (module)));
  96. ZipFile::Builder zip;
  97. {
  98. DirectoryIterator i (moduleFolder, true, "*", File::findFiles);
  99. while (i.next())
  100. if (! i.getFile().isHidden())
  101. zip.addFile (i.getFile(), 9, i.getFile().getRelativePathFrom (moduleFolderParent));
  102. }
  103. std::cout << "Writing: " << targetFile.getFullPathName() << std::endl;
  104. TemporaryFile temp (targetFile);
  105. ScopedPointer<FileOutputStream> out (temp.getFile().createOutputStream());
  106. bool ok = out != nullptr && zip.writeToStream (*out, nullptr);
  107. out = nullptr;
  108. ok = ok && temp.overwriteTargetFileWithTemporary();
  109. if (! ok)
  110. {
  111. std::cout << "Failed to write to the target file: " << targetFile.getFullPathName() << std::endl;
  112. return 1;
  113. }
  114. return 0;
  115. }
  116. int buildModules (const StringArray& args, const bool buildAllWithIndex)
  117. {
  118. hideDockIcon();
  119. if (! checkArgumentCount (args, 3))
  120. return 1;
  121. const File targetFolder (getFile (args[1]));
  122. if (! targetFolder.isDirectory())
  123. {
  124. std::cout << "The first argument must be the directory to put the result." << std::endl;
  125. return 1;
  126. }
  127. if (buildAllWithIndex)
  128. {
  129. const File folderToSearch (getFile (args[2]));
  130. DirectoryIterator i (folderToSearch, false, "*", File::findDirectories);
  131. var infoList;
  132. while (i.next())
  133. {
  134. LibraryModule module (i.getFile().getChildFile (LibraryModule::getInfoFileName()));
  135. if (module.isValid())
  136. {
  137. const int result = zipModule (targetFolder, i.getFile());
  138. if (result != 0)
  139. return result;
  140. var moduleInfo (new DynamicObject());
  141. moduleInfo.getDynamicObject()->setProperty ("file", getModulePackageName (module));
  142. moduleInfo.getDynamicObject()->setProperty ("info", module.moduleInfo);
  143. infoList.append (moduleInfo);
  144. }
  145. }
  146. const File indexFile (targetFolder.getChildFile ("modulelist"));
  147. std::cout << "Writing: " << indexFile.getFullPathName() << std::endl;
  148. indexFile.replaceWithText (JSON::toString (infoList), false, false);
  149. }
  150. else
  151. {
  152. for (int i = 2; i < args.size(); ++i)
  153. {
  154. const int result = zipModule (targetFolder, getFile (args[i]));
  155. if (result != 0)
  156. return result;
  157. }
  158. }
  159. return 0;
  160. }
  161. int listModules()
  162. {
  163. hideDockIcon();
  164. std::cout << "Downloading list of available modules..." << std::endl;
  165. ModuleList list;
  166. list.loadFromWebsite();
  167. for (int i = 0; i < list.modules.size(); ++i)
  168. {
  169. const ModuleList::Module* m = list.modules.getUnchecked(i);
  170. std::cout << m->uid << ": " << m->version << std::endl;
  171. }
  172. return 0;
  173. }
  174. int showStatus (const StringArray& args)
  175. {
  176. hideDockIcon();
  177. if (! checkArgumentCount (args, 2))
  178. return 1;
  179. const File projectFile (getFile (args[1]));
  180. Project proj (projectFile);
  181. const Result result (proj.loadDocument (projectFile));
  182. if (result.failed())
  183. {
  184. std::cout << "Failed to load project: " << projectFile.getFullPathName() << std::endl;
  185. return 1;
  186. }
  187. std::cout << "Project file: " << projectFile.getFullPathName() << std::endl
  188. << "Name: " << proj.getTitle() << std::endl
  189. << "UID: " << proj.getProjectUID() << std::endl;
  190. const int numModules = proj.getNumModules();
  191. if (numModules > 0)
  192. {
  193. std::cout << "Modules:" << std::endl;
  194. for (int i = 0; i < numModules; ++i)
  195. std::cout << " " << proj.getModuleID (i) << std::endl;
  196. }
  197. return 0;
  198. }
  199. bool matchArgument (const String& arg, const String& possible)
  200. {
  201. return arg == possible
  202. || arg == "-" + possible
  203. || arg == "--" + possible;
  204. }
  205. //==============================================================================
  206. int showHelp()
  207. {
  208. hideDockIcon();
  209. std::cout << "The Introjucer!" << std::endl
  210. << std::endl
  211. << "Usage: " << std::endl
  212. << std::endl
  213. << " introjucer --resave project_file" << std::endl
  214. << " Resaves all files and resources in a project." << std::endl
  215. << std::endl
  216. << " introjucer --resave-resources project_file" << std::endl
  217. << " Resaves just the binary resources for a project." << std::endl
  218. << std::endl
  219. << " introjucer --listmodules" << std::endl
  220. << " Displays a list of modules available from the website." << std::endl
  221. << std::endl
  222. << " introjucer --status project_file" << std::endl
  223. << " Displays information about a project." << std::endl
  224. << std::endl
  225. << " introjucer --buildmodule target_folder module_folder" << std::endl
  226. << " Zips a module into a downloadable file format." << std::endl
  227. << std::endl
  228. << " introjucer --buildallmodules target_folder module_folder" << std::endl
  229. << " Zips all modules in a given folder and creates an index for them." << std::endl
  230. << std::endl;
  231. return 0;
  232. }
  233. }
  234. //==============================================================================
  235. int performCommandLine (const String& commandLine)
  236. {
  237. StringArray args;
  238. args.addTokens (commandLine, true);
  239. args.trim();
  240. if (matchArgument (args[0], "help")) return showHelp();
  241. if (matchArgument (args[0], "resave")) return resaveProject (args, false);
  242. if (matchArgument (args[0], "resave-resources")) return resaveProject (args, true);
  243. if (matchArgument (args[0], "buildmodule")) return buildModules (args, false);
  244. if (matchArgument (args[0], "buildallmodules")) return buildModules (args, true);
  245. if (matchArgument (args[0], "listmodules")) return listModules();
  246. if (matchArgument (args[0], "status")) return showStatus (args);
  247. return commandLineNotPerformed;
  248. }