cc: For debugging, show checkerboards with the tile border color
[chromium-blink-merge.git] / chrome / installer / setup / archive_patch_helper.cc
blob959be3afd817f30edb79d2ede2a3df4ec2fd7523
1 // Copyright 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.
5 #include "chrome/installer/setup/archive_patch_helper.h"
7 #include "base/files/file_util.h"
8 #include "base/logging.h"
9 #include "chrome/installer/util/lzma_util.h"
10 #include "courgette/courgette.h"
11 #include "third_party/bspatch/mbspatch.h"
13 namespace installer {
15 ArchivePatchHelper::ArchivePatchHelper(const base::FilePath& working_directory,
16 const base::FilePath& compressed_archive,
17 const base::FilePath& patch_source,
18 const base::FilePath& target)
19 : working_directory_(working_directory),
20 compressed_archive_(compressed_archive),
21 patch_source_(patch_source),
22 target_(target) {}
24 ArchivePatchHelper::~ArchivePatchHelper() {}
26 // static
27 bool ArchivePatchHelper::UncompressAndPatch(
28 const base::FilePath& working_directory,
29 const base::FilePath& compressed_archive,
30 const base::FilePath& patch_source,
31 const base::FilePath& target) {
32 ArchivePatchHelper instance(working_directory, compressed_archive,
33 patch_source, target);
34 return (instance.Uncompress(NULL) &&
35 (instance.EnsemblePatch() || instance.BinaryPatch()));
38 bool ArchivePatchHelper::Uncompress(base::FilePath* last_uncompressed_file) {
39 // The target shouldn't already exist.
40 DCHECK(!base::PathExists(target_));
42 // UnPackArchive takes care of logging.
43 base::string16 output_file;
44 int32 lzma_result = LzmaUtil::UnPackArchive(compressed_archive_.value(),
45 working_directory_.value(),
46 &output_file);
47 if (lzma_result != NO_ERROR)
48 return false;
50 last_uncompressed_file_ = base::FilePath(output_file);
51 if (last_uncompressed_file)
52 *last_uncompressed_file = last_uncompressed_file_;
53 return true;
56 bool ArchivePatchHelper::EnsemblePatch() {
57 if (last_uncompressed_file_.empty()) {
58 LOG(ERROR) << "No patch file found in compressed archive.";
59 return false;
62 courgette::Status result =
63 courgette::ApplyEnsemblePatch(patch_source_.value().c_str(),
64 last_uncompressed_file_.value().c_str(),
65 target_.value().c_str());
66 if (result == courgette::C_OK)
67 return true;
69 LOG(ERROR)
70 << "Failed to apply patch " << last_uncompressed_file_.value()
71 << " to file " << patch_source_.value()
72 << " and generating file " << target_.value()
73 << " using courgette. err=" << result;
75 // Ensure a partial output is not left behind.
76 base::DeleteFile(target_, false);
78 return false;
81 bool ArchivePatchHelper::BinaryPatch() {
82 if (last_uncompressed_file_.empty()) {
83 LOG(ERROR) << "No patch file found in compressed archive.";
84 return false;
87 int result = ApplyBinaryPatch(patch_source_.value().c_str(),
88 last_uncompressed_file_.value().c_str(),
89 target_.value().c_str());
90 if (result == OK)
91 return true;
93 LOG(ERROR)
94 << "Failed to apply patch " << last_uncompressed_file_.value()
95 << " to file " << patch_source_.value()
96 << " and generating file " << target_.value()
97 << " using bsdiff. err=" << result;
99 // Ensure a partial output is not left behind.
100 base::DeleteFile(target_, false);
102 return false;
105 } // namespace installer