Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / CPack / cmCPackDragNDropGenerator.cxx
blob5c58b0490923c507889304f57cd513aabee6e6c5
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmCPackDragNDropGenerator.cxx,v $
5 Language: C++
6 Date: $Date: 2009-02-24 14:34:03 $
7 Version: $Revision: 1.5 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
18 #include "cmCPackDragNDropGenerator.h"
19 #include "cmCPackLog.h"
20 #include "cmSystemTools.h"
21 #include "cmGeneratedFileStream.h"
23 #include <cmsys/RegularExpression.hxx>
25 static const char* SLAHeader =
26 "data 'LPic' (5000) {\n"
27 " $\"0002 0011 0003 0001 0000 0000 0002 0000\"\n"
28 " $\"0008 0003 0000 0001 0004 0000 0004 0005\"\n"
29 " $\"0000 000E 0006 0001 0005 0007 0000 0007\"\n"
30 " $\"0008 0000 0047 0009 0000 0034 000A 0001\"\n"
31 " $\"0035 000B 0001 0020 000C 0000 0011 000D\"\n"
32 " $\"0000 005B 0004 0000 0033 000F 0001 000C\"\n"
33 " $\"0010 0000 000B 000E 0000\"\n"
34 "};\n"
35 "\n";
37 static const char* SLASTREnglish =
38 "resource 'STR#' (5002, \"English\") {\n"
39 " {\n"
40 " \"English\",\n"
41 " \"Agree\",\n"
42 " \"Disagree\",\n"
43 " \"Print\",\n"
44 " \"Save...\",\n"
45 " \"You agree to the License Agreement terms when you click \"\n"
46 " \"the \\\"Agree\\\" button.\",\n"
47 " \"Software License Agreement\",\n"
48 " \"This text cannot be saved. This disk may be full or locked, "
49 "or the \"\n"
50 " \"file may be locked.\",\n"
51 " \"Unable to print. Make sure you have selected a printer.\"\n"
52 " }\n"
53 "};\n"
54 "\n";
56 //----------------------------------------------------------------------
57 cmCPackDragNDropGenerator::cmCPackDragNDropGenerator()
61 //----------------------------------------------------------------------
62 cmCPackDragNDropGenerator::~cmCPackDragNDropGenerator()
66 //----------------------------------------------------------------------
67 int cmCPackDragNDropGenerator::InitializeInternal()
69 const std::string hdiutil_path = cmSystemTools::FindProgram("hdiutil",
70 std::vector<std::string>(), false);
71 if(hdiutil_path.empty())
73 cmCPackLogger(cmCPackLog::LOG_ERROR,
74 "Cannot locate hdiutil command"
75 << std::endl);
76 return 0;
78 this->SetOptionIfNotSet("CPACK_COMMAND_HDIUTIL", hdiutil_path.c_str());
80 const std::string setfile_path = cmSystemTools::FindProgram("SetFile",
81 std::vector<std::string>(1, "/Developer/Tools"), false);
82 if(setfile_path.empty())
84 cmCPackLogger(cmCPackLog::LOG_ERROR,
85 "Cannot locate SetFile command"
86 << std::endl);
87 return 0;
89 this->SetOptionIfNotSet("CPACK_COMMAND_SETFILE", setfile_path.c_str());
91 const std::string rez_path = cmSystemTools::FindProgram("Rez",
92 std::vector<std::string>(1, "/Developer/Tools"), false);
93 if(rez_path.empty())
95 cmCPackLogger(cmCPackLog::LOG_ERROR,
96 "Cannot locate Rez command"
97 << std::endl);
98 return 0;
100 this->SetOptionIfNotSet("CPACK_COMMAND_REZ", rez_path.c_str());
102 return this->Superclass::InitializeInternal();
105 //----------------------------------------------------------------------
106 const char* cmCPackDragNDropGenerator::GetOutputExtension()
108 return ".dmg";
111 //----------------------------------------------------------------------
112 int cmCPackDragNDropGenerator::CompressFiles(const char* outFileName,
113 const char* toplevel, const std::vector<std::string>& files)
115 (void) files;
117 return this->CreateDMG(toplevel, outFileName);
120 //----------------------------------------------------------------------
121 bool cmCPackDragNDropGenerator::CopyFile(cmOStringStream& source,
122 cmOStringStream& target)
124 if(!cmSystemTools::CopyFileIfDifferent(
125 source.str().c_str(),
126 target.str().c_str()))
128 cmCPackLogger(cmCPackLog::LOG_ERROR,
129 "Error copying "
130 << source.str()
131 << " to "
132 << target.str()
133 << std::endl);
135 return false;
138 return true;
141 //----------------------------------------------------------------------
142 bool cmCPackDragNDropGenerator::RunCommand(cmOStringStream& command,
143 std::string* output)
145 int exit_code = 1;
147 bool result = cmSystemTools::RunSingleCommand(
148 command.str().c_str(),
149 output,
150 &exit_code,
152 this->GeneratorVerbose,
155 if(!result || exit_code)
157 cmCPackLogger(cmCPackLog::LOG_ERROR,
158 "Error executing: "
159 << command.str()
160 << std::endl);
162 return false;
165 return true;
168 //----------------------------------------------------------------------
169 int cmCPackDragNDropGenerator::CreateDMG(const std::string& toplevel,
170 const std::string& outFileName)
172 // Get optional arguments ...
173 const std::string cpack_package_icon = this->GetOption("CPACK_PACKAGE_ICON")
174 ? this->GetOption("CPACK_PACKAGE_ICON") : "";
176 // Get optional arguments ...
177 std::string cpack_license_file =
178 this->GetOption("CPACK_RESOURCE_FILE_LICENSE") ?
179 this->GetOption("CPACK_RESOURCE_FILE_LICENSE") : "";
180 // only put license on dmg if is user provided
181 if(!cpack_license_file.empty() &&
182 cpack_license_file.find("CPack.GenericLicense.txt") != std::string::npos)
184 cpack_license_file = "";
187 // The staging directory contains everything that will end-up inside the
188 // final disk image ...
189 cmOStringStream staging;
190 staging << toplevel;
192 // Add a symlink to /Applications so users can drag-and-drop the bundle
193 // into it
194 cmOStringStream application_link;
195 application_link << staging.str() << "/Applications";
196 cmSystemTools::CreateSymlink("/Applications",
197 application_link.str().c_str());
199 // Optionally add a custom volume icon ...
200 if(!cpack_package_icon.empty())
202 cmOStringStream package_icon_source;
203 package_icon_source << cpack_package_icon;
205 cmOStringStream package_icon_destination;
206 package_icon_destination << staging.str() << "/.VolumeIcon.icns";
208 if(!this->CopyFile(package_icon_source, package_icon_destination))
210 cmCPackLogger(cmCPackLog::LOG_ERROR,
211 "Error copying disk volume icon. "
212 "Check the value of CPACK_PACKAGE_ICON."
213 << std::endl);
215 return 0;
219 // Create a temporary read-write disk image ...
220 std::string temp_image = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
221 temp_image += "/temp.dmg";
223 cmOStringStream temp_image_command;
224 temp_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
225 temp_image_command << " create";
226 temp_image_command << " -ov";
227 temp_image_command << " -srcfolder \"" << staging.str() << "\"";
228 temp_image_command << " -volname \""
229 << this->GetOption("CPACK_PACKAGE_FILE_NAME") << "\"";
230 temp_image_command << " -format UDRW";
231 temp_image_command << " \"" << temp_image << "\"";
233 if(!this->RunCommand(temp_image_command))
235 cmCPackLogger(cmCPackLog::LOG_ERROR,
236 "Error generating temporary disk image."
237 << std::endl);
239 return 0;
242 // Optionally set the custom icon flag for the image ...
243 if(!cpack_package_icon.empty())
245 cmOStringStream temp_mount;
247 cmOStringStream attach_command;
248 attach_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
249 attach_command << " attach";
250 attach_command << " \"" << temp_image << "\"";
252 std::string attach_output;
253 if(!this->RunCommand(attach_command, &attach_output))
255 cmCPackLogger(cmCPackLog::LOG_ERROR,
256 "Error attaching temporary disk image."
257 << std::endl);
259 return 0;
262 cmsys::RegularExpression mountpoint_regex(".*(/Volumes/[^\n]+)\n.*");
263 mountpoint_regex.find(attach_output.c_str());
264 temp_mount << mountpoint_regex.match(1);
266 cmOStringStream setfile_command;
267 setfile_command << this->GetOption("CPACK_COMMAND_SETFILE");
268 setfile_command << " -a C";
269 setfile_command << " \"" << temp_mount.str() << "\"";
271 if(!this->RunCommand(setfile_command))
273 cmCPackLogger(cmCPackLog::LOG_ERROR,
274 "Error assigning custom icon to temporary disk image."
275 << std::endl);
277 return 0;
280 cmOStringStream detach_command;
281 detach_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
282 detach_command << " detach";
283 detach_command << " \"" << temp_mount.str() << "\"";
285 if(!this->RunCommand(detach_command))
287 cmCPackLogger(cmCPackLog::LOG_ERROR,
288 "Error detaching temporary disk image."
289 << std::endl);
291 return 0;
295 if(!cpack_license_file.empty())
297 std::string sla_r = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
298 sla_r += "/sla.r";
300 std::ifstream ifs;
301 ifs.open(cpack_license_file.c_str());
302 if(ifs.is_open())
304 cmGeneratedFileStream osf(sla_r.c_str());
305 osf << SLAHeader;
306 osf << "\n";
307 osf << "data 'TEXT' (5002, \"English\") {\n";
308 while(ifs.good())
310 std::string line;
311 std::getline(ifs, line);
312 osf << " \"" << line << "\\n\"\n";
314 osf << "};\n";
315 osf << "\n";
316 osf << SLASTREnglish;
317 ifs.close();
318 osf.close();
321 // convert to UDCO
322 std::string temp_udco = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
323 temp_udco += "/temp-udco.dmg";
325 cmOStringStream udco_image_command;
326 udco_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
327 udco_image_command << " convert \"" << temp_image << "\"";
328 udco_image_command << " -format UDCO";
329 udco_image_command << " -o \"" << temp_udco << "\"";
331 std::string error;
332 if(!this->RunCommand(udco_image_command, &error))
334 cmCPackLogger(cmCPackLog::LOG_ERROR,
335 "Error converting to UDCO dmg for adding SLA." << std::endl
336 << error
337 << std::endl);
338 return 0;
341 // unflatten dmg
342 cmOStringStream unflatten_command;
343 unflatten_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
344 unflatten_command << " unflatten ";
345 unflatten_command << "\"" << temp_udco << "\"";
347 if(!this->RunCommand(unflatten_command, &error))
349 cmCPackLogger(cmCPackLog::LOG_ERROR,
350 "Error unflattening dmg for adding SLA." << std::endl
351 << error
352 << std::endl);
353 return 0;
356 // Rez the SLA
357 cmOStringStream embed_sla_command;
358 embed_sla_command << "/bin/bash -c \""; // need expansion of "*.r"
359 embed_sla_command << this->GetOption("CPACK_COMMAND_REZ");
360 embed_sla_command << " /Developer/Headers/FlatCarbon/*.r ";
361 embed_sla_command << "'" << sla_r << "'";
362 embed_sla_command << " -a -o ";
363 embed_sla_command << "'" << temp_udco << "'\"";
365 if(!this->RunCommand(embed_sla_command, &error))
367 cmCPackLogger(cmCPackLog::LOG_ERROR,
368 "Error adding SLA." << std::endl
369 << error
370 << std::endl);
371 return 0;
374 // flatten dmg
375 cmOStringStream flatten_command;
376 flatten_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
377 flatten_command << " flatten ";
378 flatten_command << "\"" << temp_udco << "\"";
380 if(!this->RunCommand(flatten_command, &error))
382 cmCPackLogger(cmCPackLog::LOG_ERROR,
383 "Error flattening dmg for adding SLA." << std::endl
384 << error
385 << std::endl);
386 return 0;
389 temp_image = temp_udco;
393 // Create the final compressed read-only disk image ...
394 cmOStringStream final_image_command;
395 final_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
396 final_image_command << " convert \"" << temp_image << "\"";
397 final_image_command << " -format UDZO";
398 final_image_command << " -imagekey";
399 final_image_command << " zlib-level=9";
400 final_image_command << " -o \"" << outFileName << "\"";
402 if(!this->RunCommand(final_image_command))
404 cmCPackLogger(cmCPackLog::LOG_ERROR,
405 "Error compressing disk image."
406 << std::endl);
408 return 0;
411 return 1;