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 "tools/gn/filesystem_utils.h" | 5 #include "tools/gn/filesystem_utils.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
680 std::string GetOutputSubdirName(const Label& toolchain_label, bool is_default) { | 680 std::string GetOutputSubdirName(const Label& toolchain_label, bool is_default) { |
681 // The default toolchain has no subdir. | 681 // The default toolchain has no subdir. |
682 if (is_default) | 682 if (is_default) |
683 return std::string(); | 683 return std::string(); |
684 | 684 |
685 // For now just assume the toolchain name is always a valid dir name. We may | 685 // For now just assume the toolchain name is always a valid dir name. We may |
686 // want to clean up the in the future. | 686 // want to clean up the in the future. |
687 return toolchain_label.name() + "/"; | 687 return toolchain_label.name() + "/"; |
688 } | 688 } |
689 | 689 |
| 690 bool ContentsEqual(const base::FilePath& file_path, const std::string& data) { |
| 691 // Compare file and stream sizes first. Quick and will save us some time if |
| 692 // they are different sizes. |
| 693 int64_t file_size; |
| 694 if (!base::GetFileSize(file_path, &file_size) || |
| 695 static_cast<size_t>(file_size) != data.size()) { |
| 696 return false; |
| 697 } |
| 698 |
| 699 std::string file_data; |
| 700 file_data.resize(file_size); |
| 701 if (!base::ReadFileToString(file_path, &file_data)) |
| 702 return false; |
| 703 |
| 704 return file_data == data; |
| 705 } |
| 706 |
| 707 bool WriteFileIfChanged(const base::FilePath& file_path, |
| 708 const std::string& data, |
| 709 Err* err) { |
| 710 if (ContentsEqual(file_path, data)) |
| 711 return true; |
| 712 |
| 713 // Create the directory if necessary. |
| 714 if (!base::CreateDirectory(file_path.DirName())) { |
| 715 if (err) { |
| 716 *err = |
| 717 Err(Location(), "Unable to create directory.", |
| 718 "I was using \"" + FilePathToUTF8(file_path.DirName()) + "\"."); |
| 719 } |
| 720 return false; |
| 721 } |
| 722 |
| 723 int size = static_cast<int>(data.size()); |
| 724 bool write_success = false; |
| 725 |
| 726 #if defined(OS_WIN) |
| 727 // On Windows, provide a custom implementation of base::WriteFile. Sometimes |
| 728 // the base version fails, especially on the bots. The guess is that Windows |
| 729 // Defender or other antivirus programs still have the file open (after |
| 730 // checking for the read) when the write happens immediately after. This |
| 731 // version opens with FILE_SHARE_READ (normally not what you want when |
| 732 // replacing the entire contents of the file) which lets us continue even if |
| 733 // another program has the file open for reading. See http://crbug.com/468437 |
| 734 base::win::ScopedHandle file(::CreateFile(file_path.value().c_str(), |
| 735 GENERIC_WRITE, FILE_SHARE_READ, |
| 736 NULL, CREATE_ALWAYS, 0, NULL)); |
| 737 if (file.IsValid()) { |
| 738 DWORD written; |
| 739 BOOL result = ::WriteFile(file.Get(), data.c_str(), size, &written, NULL); |
| 740 if (result) { |
| 741 if (static_cast<int>(written) == size) { |
| 742 write_success = true; |
| 743 } else { |
| 744 // Didn't write all the bytes. |
| 745 LOG(ERROR) << "wrote" << written << " bytes to " |
| 746 << base::UTF16ToUTF8(file_path.value()) << " expected " |
| 747 << size; |
| 748 } |
| 749 } else { |
| 750 // WriteFile failed. |
| 751 PLOG(ERROR) << "writing file " << base::UTF16ToUTF8(file_path.value()) |
| 752 << " failed"; |
| 753 } |
| 754 } else { |
| 755 PLOG(ERROR) << "CreateFile failed for path " |
| 756 << base::UTF16ToUTF8(file_path.value()); |
| 757 } |
| 758 #else |
| 759 write_success = base::WriteFile(file_path, data.c_str(), size) == size; |
| 760 #endif |
| 761 |
| 762 if (!write_success && err) { |
| 763 *err = Err(Location(), "Unable to write file.", |
| 764 "I was writing \"" + FilePathToUTF8(file_path) + "\"."); |
| 765 } |
| 766 |
| 767 return write_success; |
| 768 } |
| 769 |
690 SourceDir GetToolchainOutputDir(const Settings* settings) { | 770 SourceDir GetToolchainOutputDir(const Settings* settings) { |
691 return settings->toolchain_output_subdir().AsSourceDir( | 771 return settings->toolchain_output_subdir().AsSourceDir( |
692 settings->build_settings()); | 772 settings->build_settings()); |
693 } | 773 } |
694 | 774 |
695 SourceDir GetToolchainOutputDir(const BuildSettings* build_settings, | 775 SourceDir GetToolchainOutputDir(const BuildSettings* build_settings, |
696 const Label& toolchain_label, bool is_default) { | 776 const Label& toolchain_label, bool is_default) { |
697 std::string result = build_settings->build_dir().value(); | 777 std::string result = build_settings->build_dir().value(); |
698 result.append(GetOutputSubdirName(toolchain_label, is_default)); | 778 result.append(GetOutputSubdirName(toolchain_label, is_default)); |
699 return SourceDir(SourceDir::SWAP_IN, &result); | 779 return SourceDir(SourceDir::SWAP_IN, &result); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
835 | 915 |
836 SourceDir GetCurrentOutputDir(const Scope* scope) { | 916 SourceDir GetCurrentOutputDir(const Scope* scope) { |
837 return GetOutputDirForSourceDirAsOutputFile( | 917 return GetOutputDirForSourceDirAsOutputFile( |
838 scope->settings(), scope->GetSourceDir()).AsSourceDir( | 918 scope->settings(), scope->GetSourceDir()).AsSourceDir( |
839 scope->settings()->build_settings()); | 919 scope->settings()->build_settings()); |
840 } | 920 } |
841 | 921 |
842 SourceDir GetCurrentGenDir(const Scope* scope) { | 922 SourceDir GetCurrentGenDir(const Scope* scope) { |
843 return GetGenDirForSourceDir(scope->settings(), scope->GetSourceDir()); | 923 return GetGenDirForSourceDir(scope->settings(), scope->GetSourceDir()); |
844 } | 924 } |
OLD | NEW |