1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <iostream> 6 #include <sstream> 7 8 #include "base/file_util.h" 9 #include "base/strings/string_split.h" 10 #include "base/strings/string_util.h" 11 #include "tools/gn/err.h" 12 #include "tools/gn/filesystem_utils.h" 13 #include "tools/gn/functions.h" 14 #include "tools/gn/input_file.h" 15 #include "tools/gn/parse_tree.h" 16 #include "tools/gn/scheduler.h" 17 18 namespace functions { 19 20 const char kWriteFile[] = "write_file"; 21 const char kWriteFile_Help[] = 22 "write_file: Write a file to disk.\n" 23 "\n" 24 " write_file(filename, data)\n" 25 "\n" 26 " If data is a list, the list will be written one-item-per-line with no\n" 27 " quoting or brackets.\n" 28 "\n" 29 " TODO(brettw) we probably need an optional third argument to control\n" 30 " list formatting.\n" 31 "\n" 32 "Arguments:\n" 33 "\n" 34 " filename\n" 35 " Filename to write. This must be within the output directory.\n" 36 "\n" 37 " data:\n" 38 " The list or string to write.\n"; 39 40 Value RunWriteFile(Scope* scope, 41 const FunctionCallNode* function, 42 const std::vector<Value>& args, 43 Err* err) { 44 if (args.size() != 2) { 45 *err = Err(function->function(), "Wrong number of args to write_file", 46 "I expected two arguments."); 47 return Value(); 48 } 49 50 // Compute the file name and make sure it's in the output dir. 51 if (!args[0].VerifyTypeIs(Value::STRING, err)) 52 return Value(); 53 const SourceDir& cur_dir = SourceDirForFunctionCall(function); 54 SourceFile source_file = cur_dir.ResolveRelativeFile(args[0].string_value()); 55 if (!EnsureStringIsInOutputDir( 56 scope->settings()->build_settings()->build_dir(), 57 source_file.value(), args[0], err)) 58 return Value(); 59 60 // Compute output. 61 std::ostringstream contents; 62 if (args[1].type() == Value::LIST) { 63 const std::vector<Value>& list = args[1].list_value(); 64 for (size_t i = 0; i < list.size(); i++) 65 contents << list[i].ToString() << std::endl; 66 } else { 67 contents << args[1].ToString(); 68 } 69 70 // Write file, creating the directory if necessary. 71 base::FilePath file_path = 72 scope->settings()->build_settings()->GetFullPath(source_file); 73 const std::string& contents_string = contents.str(); 74 if (!file_util::CreateDirectory(file_path.DirName())) { 75 *err = Err(function->function(), "Unable to create directory.", 76 "I was using \"" + FilePathToUTF8(file_path.DirName()) + "\"."); 77 return Value(); 78 } 79 if (file_util::WriteFile(file_path, 80 contents_string.c_str(), contents_string.size()) 81 != static_cast<int>(contents_string.size())) { 82 *err = Err(function->function(), "Unable to write file.", 83 "I was writing \"" + FilePathToUTF8(file_path) + "\"."); 84 return Value(); 85 } 86 return Value(); 87 } 88 89 } // namespace functions 90