Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: tools/gn/function_write_file.cc

Issue 1704383002: [GN] Don't rewrite files with the same contents (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/gn/filesystem_utils_unittest.cc ('k') | tools/gn/ninja_target_writer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "build/build_config.h" 12 #include "build/build_config.h"
13 #include "tools/gn/err.h" 13 #include "tools/gn/err.h"
14 #include "tools/gn/filesystem_utils.h" 14 #include "tools/gn/filesystem_utils.h"
15 #include "tools/gn/functions.h" 15 #include "tools/gn/functions.h"
16 #include "tools/gn/input_file.h" 16 #include "tools/gn/input_file.h"
17 #include "tools/gn/parse_tree.h" 17 #include "tools/gn/parse_tree.h"
18 #include "tools/gn/scheduler.h" 18 #include "tools/gn/scheduler.h"
19 19
20 namespace functions { 20 namespace functions {
21 21
22 namespace {
23
24 // On Windows, provide a custom implementation of base::WriteFile. Sometimes
25 // the base version fails, especially on the bots. The guess is that Windows
26 // Defender or other antivirus programs still have the file open (after
27 // checking for the read) when the write happens immediately after. This
28 // version opens with FILE_SHARE_READ (normally not what you want when
29 // replacing the entire contents of the file) which lets us continue even if
30 // another program has the file open for reading. See http://crbug.com/468437
31 #if defined(OS_WIN)
32 int DoWriteFile(const base::FilePath& filename, const char* data, int size) {
33 base::win::ScopedHandle file(::CreateFile(
34 filename.value().c_str(),
35 GENERIC_WRITE,
36 FILE_SHARE_READ,
37 NULL,
38 CREATE_ALWAYS,
39 0,
40 NULL));
41 if (!file.IsValid()) {
42 PLOG(ERROR) << "CreateFile failed for path "
43 << base::UTF16ToUTF8(filename.value());
44 return -1;
45 }
46
47 DWORD written;
48 BOOL result = ::WriteFile(file.Get(), data, size, &written, NULL);
49 if (result && static_cast<int>(written) == size)
50 return written;
51
52 if (!result) {
53 // WriteFile failed.
54 PLOG(ERROR) << "writing file " << base::UTF16ToUTF8(filename.value())
55 << " failed";
56 } else {
57 // Didn't write all the bytes.
58 LOG(ERROR) << "wrote" << written << " bytes to "
59 << base::UTF16ToUTF8(filename.value()) << " expected " << size;
60 }
61 return -1;
62 }
63 #else
64 int DoWriteFile(const base::FilePath& filename, const char* data, int size) {
65 return base::WriteFile(filename, data, size);
66 }
67 #endif
68
69 } // namespace
70
71 const char kWriteFile[] = "write_file"; 22 const char kWriteFile[] = "write_file";
72 const char kWriteFile_HelpShort[] = 23 const char kWriteFile_HelpShort[] =
73 "write_file: Write a file to disk."; 24 "write_file: Write a file to disk.";
74 const char kWriteFile_Help[] = 25 const char kWriteFile_Help[] =
75 "write_file: Write a file to disk.\n" 26 "write_file: Write a file to disk.\n"
76 "\n" 27 "\n"
77 " write_file(filename, data)\n" 28 " write_file(filename, data)\n"
78 "\n" 29 "\n"
79 " If data is a list, the list will be written one-item-per-line with no\n" 30 " If data is a list, the list will be written one-item-per-line with no\n"
80 " quoting or brackets.\n" 31 " quoting or brackets.\n"
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 82
132 // Compute output. 83 // Compute output.
133 std::ostringstream contents; 84 std::ostringstream contents;
134 if (args[1].type() == Value::LIST) { 85 if (args[1].type() == Value::LIST) {
135 const std::vector<Value>& list = args[1].list_value(); 86 const std::vector<Value>& list = args[1].list_value();
136 for (const auto& cur : list) 87 for (const auto& cur : list)
137 contents << cur.ToString(false) << std::endl; 88 contents << cur.ToString(false) << std::endl;
138 } else { 89 } else {
139 contents << args[1].ToString(false); 90 contents << args[1].ToString(false);
140 } 91 }
141 const std::string& new_contents = contents.str(); 92
142 base::FilePath file_path = 93 base::FilePath file_path =
143 scope->settings()->build_settings()->GetFullPath(source_file); 94 scope->settings()->build_settings()->GetFullPath(source_file);
144 95
145 // Make sure we're not replacing the same contents. 96 // Make sure we're not replacing the same contents.
146 std::string existing_contents; 97 if (!WriteFileIfChanged(file_path, contents.str(), err))
147 if (base::ReadFileToString(file_path, &existing_contents) && 98 *err = Err(function->function(), err->message(), err->help_text());
148 existing_contents == new_contents)
149 return Value(); // Nothing to do.
150 99
151 // Write file, creating the directory if necessary.
152 if (!base::CreateDirectory(file_path.DirName())) {
153 *err = Err(function->function(), "Unable to create directory.",
154 "I was using \"" + FilePathToUTF8(file_path.DirName()) + "\".");
155 return Value();
156 }
157
158 int int_size = static_cast<int>(new_contents.size());
159 if (DoWriteFile(file_path, new_contents.c_str(), int_size)
160 != int_size) {
161 *err = Err(function->function(), "Unable to write file.",
162 "I was writing \"" + FilePathToUTF8(file_path) + "\".");
163 return Value();
164 }
165 return Value(); 100 return Value();
166 } 101 }
167 102
168 } // namespace functions 103 } // namespace functions
OLDNEW
« no previous file with comments | « tools/gn/filesystem_utils_unittest.cc ('k') | tools/gn/ninja_target_writer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698