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.

320 lines
11KB

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