1 // Copyright (c) 2011 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. 4 5 // This file provides a command-line interface to 6 // upgrade_test::GenerateAlternateVersion(). 7 8 #include <cstdio> 9 #include <cstdlib> 10 11 #include "base/at_exit.h" 12 #include "base/basictypes.h" 13 #include "base/command_line.h" 14 #include "base/file_util.h" 15 #include "base/files/file_path.h" 16 #include "base/logging.h" 17 #include "base/path_service.h" 18 #include "chrome/installer/test/alternate_version_generator.h" 19 20 namespace { 21 22 const wchar_t kDefaultMiniInstallerFile[] = L"mini_installer.exe"; 23 const wchar_t kDefaultOutPath[] = L"mini_installer_new.exe"; 24 25 namespace switches { 26 27 const char kForce[] = "force"; 28 const char kHelp[] = "help"; 29 const char kMiniInstaller[] = "mini_installer"; 30 const char kOut[] = "out"; 31 const char kPrevious[] = "previous"; 32 33 } // namespace switches 34 35 namespace errors { 36 37 enum ErrorCode { 38 SHOW_HELP, 39 MINI_INSTALLER_NOT_FOUND, 40 OUT_FILE_EXISTS, 41 GENERATION_FAILED 42 }; 43 44 const wchar_t* const Messages[] = { 45 NULL, 46 L"original mini_installer.exe not found", 47 L"output file already exists", 48 L"failed to generate a newly versioned mini_installer.exe" 49 }; 50 51 const wchar_t* GetErrorMessage(ErrorCode error_code) { 52 DCHECK_LE(0, error_code); 53 DCHECK_GT(arraysize(Messages), static_cast<size_t>(error_code)); 54 return Messages[error_code]; 55 } 56 57 } // namespace errors 58 59 // Display usage information to stderr along with an optional error message with 60 // details. 61 void DumpUsage(const CommandLine& cmd_line, 62 errors::ErrorCode error_code, 63 const std::wstring& detail) { 64 const wchar_t* error_message = errors::GetErrorMessage(error_code); 65 if (error_message != NULL) { 66 fwprintf(stderr, L"%s: %s", cmd_line.GetProgram().value().c_str(), 67 errors::GetErrorMessage(error_code)); 68 if (!detail.empty()) 69 fwprintf(stderr, L" (%s)\n", detail.c_str()); 70 else 71 fwprintf(stderr, L"\n"); 72 } 73 74 fwprintf(stderr, 75 L"Usage: %s [ OPTIONS ]\n" 76 L" Where OPTIONS is one or more of:\n" 77 L" --help Display this help message.\n" 78 L" --force Overwrite any existing output files.\n" 79 L" --mini_installer=SRC_PATH Path to mini_installer.exe. Default value is\n" 80 L" \"mini_installer.exe\" in the same directory as\n" 81 L" this program.\n" 82 L" --out=OUT_PATH Path to output file. Default value is\n" 83 L" \"mini_installer_new.exe\" in the current\n" 84 L" directory.\n" 85 L" --previous OUT_PATH will have a lower version than\n" 86 L" SRC_PATH. By default, OUT_PATH will have a\n" 87 L" higher version.\n" 88 L" --7za_path=7ZA_PATH Path to the directory holding 7za.exe. Defaults\n" 89 L" to ..\\..\\third_party\\lzma_sdk\\Executable\n" 90 L" relative to this program's location.\n", 91 cmd_line.GetProgram().value().c_str()); 92 } 93 94 // Gets the path to the source mini_installer.exe on which to operate, putting 95 // the result in |mini_installer|. Returns true on success. 96 bool GetMiniInstallerPath(const CommandLine& cmd_line, 97 base::FilePath* mini_installer) { 98 DCHECK(mini_installer); 99 base::FilePath result = cmd_line.GetSwitchValuePath(switches::kMiniInstaller); 100 if (result.empty() && PathService::Get(base::DIR_EXE, &result)) 101 result = result.Append(kDefaultMiniInstallerFile); 102 if (result.empty()) 103 return false; 104 *mini_installer = result; 105 return true; 106 } 107 108 // Gets the path to the output file, putting the result in |out|. 109 void GetOutPath(const CommandLine& cmd_line, base::FilePath* out) { 110 DCHECK(out); 111 base::FilePath result = cmd_line.GetSwitchValuePath(switches::kOut); 112 if (result.empty()) 113 *out = base::FilePath(kDefaultOutPath); 114 else 115 *out = result; 116 } 117 118 // Returns the direction in which the version should be adjusted. 119 upgrade_test::Direction GetDirection(const CommandLine& cmd_line) { 120 return cmd_line.HasSwitch(switches::kPrevious) ? 121 upgrade_test::PREVIOUS_VERSION : upgrade_test::NEXT_VERSION; 122 } 123 124 } // namespace 125 126 // The main program. 127 int wmain(int argc, wchar_t *argv[]) { 128 base::AtExitManager exit_manager; 129 CommandLine::Init(0, NULL); 130 CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 131 132 if (cmd_line->HasSwitch(switches::kHelp)) { 133 DumpUsage(*cmd_line, errors::SHOW_HELP, std::wstring()); 134 return EXIT_SUCCESS; 135 } 136 137 base::FilePath mini_installer; 138 if (!GetMiniInstallerPath(*cmd_line, &mini_installer)) { 139 DumpUsage(*cmd_line, errors::MINI_INSTALLER_NOT_FOUND, std::wstring()); 140 return EXIT_FAILURE; 141 } 142 143 if (!base::PathExists(mini_installer)) { 144 DumpUsage(*cmd_line, errors::MINI_INSTALLER_NOT_FOUND, 145 mini_installer.value()); 146 return EXIT_FAILURE; 147 } 148 149 base::FilePath out; 150 GetOutPath(*cmd_line, &out); 151 if (!cmd_line->HasSwitch(switches::kForce) && base::PathExists(out)) { 152 DumpUsage(*cmd_line, errors::OUT_FILE_EXISTS, out.value()); 153 return EXIT_FAILURE; 154 } 155 156 upgrade_test::Direction direction = GetDirection(*cmd_line); 157 158 std::wstring original_version; 159 std::wstring new_version; 160 161 if (upgrade_test::GenerateAlternateVersion(mini_installer, out, direction, 162 &original_version, &new_version)) { 163 fwprintf(stdout, L"Generated version %s from version %s\n", 164 new_version.c_str(), original_version.c_str()); 165 return EXIT_SUCCESS; 166 } 167 168 DumpUsage(*cmd_line, errors::GENERATION_FAILED, mini_installer.value()); 169 return EXIT_FAILURE; 170 } 171