OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <iostream> | 5 #include <iostream> |
6 #include <sstream> | 6 #include <sstream> |
7 | 7 |
8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
9 #include "base/strings/string_split.h" | 9 #include "base/strings/string_split.h" |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
12 #include "tools/gn/err.h" | 12 #include "tools/gn/err.h" |
13 #include "tools/gn/filesystem_utils.h" | 13 #include "tools/gn/filesystem_utils.h" |
14 #include "tools/gn/functions.h" | 14 #include "tools/gn/functions.h" |
15 #include "tools/gn/input_file.h" | 15 #include "tools/gn/input_file.h" |
16 #include "tools/gn/parse_tree.h" | 16 #include "tools/gn/parse_tree.h" |
17 #include "tools/gn/scheduler.h" | 17 #include "tools/gn/scheduler.h" |
18 | 18 |
19 namespace functions { | 19 namespace functions { |
20 | 20 |
21 namespace { | 21 namespace { |
22 | 22 |
23 // On Windows, provide a custom implementation of base::WriteFile. Sometimes | 23 // On Windows, provide a custom implementation of base::WriteFile. Sometimes |
24 // the base version would fail, and this alternate implementation provides | 24 // the base version fails, especially on the bots. The guess is that Windows |
25 // additional logging. See http://crbug.com/468437 | 25 // Defender or other antivirus programs still have the file open (after |
| 26 // checking for the read) when the write happens immediately after. This |
| 27 // version opens with FILE_SHARE_READ (normally not what you want when |
| 28 // replacing the entire contents of the file) which lets us continue even if |
| 29 // another program has the file open for reading. See http://crbug.com/468437 |
26 #if defined(OS_WIN) | 30 #if defined(OS_WIN) |
27 int DoWriteFile(const base::FilePath& filename, const char* data, int size) { | 31 int DoWriteFile(const base::FilePath& filename, const char* data, int size) { |
28 base::win::ScopedHandle file(::CreateFile( | 32 base::win::ScopedHandle file(::CreateFile( |
29 filename.value().c_str(), | 33 filename.value().c_str(), |
30 GENERIC_WRITE, | 34 GENERIC_WRITE, |
31 FILE_SHARE_READ, // Not present in the base version, speculative fix. | 35 FILE_SHARE_READ, |
32 NULL, | 36 NULL, |
33 CREATE_ALWAYS, | 37 CREATE_ALWAYS, |
34 0, | 38 0, |
35 NULL)); | 39 NULL)); |
36 if (!file.IsValid()) { | 40 if (!file.IsValid()) { |
37 PLOG(ERROR) << "CreateFile failed for path " | 41 PLOG(ERROR) << "CreateFile failed for path " |
38 << base::UTF16ToUTF8(filename.value()); | 42 << base::UTF16ToUTF8(filename.value()); |
39 return -1; | 43 return -1; |
40 } | 44 } |
41 | 45 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 // Compute the file name and make sure it's in the output dir. | 106 // Compute the file name and make sure it's in the output dir. |
103 const SourceDir& cur_dir = scope->GetSourceDir(); | 107 const SourceDir& cur_dir = scope->GetSourceDir(); |
104 SourceFile source_file = cur_dir.ResolveRelativeFile(args[0], err, | 108 SourceFile source_file = cur_dir.ResolveRelativeFile(args[0], err, |
105 scope->settings()->build_settings()->root_path_utf8()); | 109 scope->settings()->build_settings()->root_path_utf8()); |
106 if (err->has_error()) | 110 if (err->has_error()) |
107 return Value(); | 111 return Value(); |
108 if (!EnsureStringIsInOutputDir( | 112 if (!EnsureStringIsInOutputDir( |
109 scope->settings()->build_settings()->build_dir(), | 113 scope->settings()->build_settings()->build_dir(), |
110 source_file.value(), args[0].origin(), err)) | 114 source_file.value(), args[0].origin(), err)) |
111 return Value(); | 115 return Value(); |
| 116 g_scheduler->AddWrittenFile(source_file); // Track that we wrote this file. |
112 | 117 |
113 // Compute output. | 118 // Compute output. |
114 std::ostringstream contents; | 119 std::ostringstream contents; |
115 if (args[1].type() == Value::LIST) { | 120 if (args[1].type() == Value::LIST) { |
116 const std::vector<Value>& list = args[1].list_value(); | 121 const std::vector<Value>& list = args[1].list_value(); |
117 for (const auto& cur : list) | 122 for (const auto& cur : list) |
118 contents << cur.ToString(false) << std::endl; | 123 contents << cur.ToString(false) << std::endl; |
119 } else { | 124 } else { |
120 contents << args[1].ToString(false); | 125 contents << args[1].ToString(false); |
121 } | 126 } |
(...skipping 18 matching lines...) Expand all Loading... |
140 if (DoWriteFile(file_path, new_contents.c_str(), int_size) | 145 if (DoWriteFile(file_path, new_contents.c_str(), int_size) |
141 != int_size) { | 146 != int_size) { |
142 *err = Err(function->function(), "Unable to write file.", | 147 *err = Err(function->function(), "Unable to write file.", |
143 "I was writing \"" + FilePathToUTF8(file_path) + "\"."); | 148 "I was writing \"" + FilePathToUTF8(file_path) + "\"."); |
144 return Value(); | 149 return Value(); |
145 } | 150 } |
146 return Value(); | 151 return Value(); |
147 } | 152 } |
148 | 153 |
149 } // namespace functions | 154 } // namespace functions |
OLD | NEW |