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 | |
770 SourceDir GetToolchainOutputDir(const Settings* settings) { | 690 SourceDir GetToolchainOutputDir(const Settings* settings) { |
771 return settings->toolchain_output_subdir().AsSourceDir( | 691 return settings->toolchain_output_subdir().AsSourceDir( |
772 settings->build_settings()); | 692 settings->build_settings()); |
773 } | 693 } |
774 | 694 |
775 SourceDir GetToolchainOutputDir(const BuildSettings* build_settings, | 695 SourceDir GetToolchainOutputDir(const BuildSettings* build_settings, |
776 const Label& toolchain_label, bool is_default) { | 696 const Label& toolchain_label, bool is_default) { |
777 std::string result = build_settings->build_dir().value(); | 697 std::string result = build_settings->build_dir().value(); |
778 result.append(GetOutputSubdirName(toolchain_label, is_default)); | 698 result.append(GetOutputSubdirName(toolchain_label, is_default)); |
779 return SourceDir(SourceDir::SWAP_IN, &result); | 699 return SourceDir(SourceDir::SWAP_IN, &result); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
915 | 835 |
916 SourceDir GetCurrentOutputDir(const Scope* scope) { | 836 SourceDir GetCurrentOutputDir(const Scope* scope) { |
917 return GetOutputDirForSourceDirAsOutputFile( | 837 return GetOutputDirForSourceDirAsOutputFile( |
918 scope->settings(), scope->GetSourceDir()).AsSourceDir( | 838 scope->settings(), scope->GetSourceDir()).AsSourceDir( |
919 scope->settings()->build_settings()); | 839 scope->settings()->build_settings()); |
920 } | 840 } |
921 | 841 |
922 SourceDir GetCurrentGenDir(const Scope* scope) { | 842 SourceDir GetCurrentGenDir(const Scope* scope) { |
923 return GetGenDirForSourceDir(scope->settings(), scope->GetSourceDir()); | 843 return GetGenDirForSourceDir(scope->settings(), scope->GetSourceDir()); |
924 } | 844 } |
OLD | NEW |