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 20namespace { 21 22const wchar_t kDefaultMiniInstallerFile[] = L"mini_installer.exe"; 23const wchar_t kDefaultOutPath[] = L"mini_installer_new.exe"; 24 25namespace switches { 26 27const char kForce[] = "force"; 28const char kHelp[] = "help"; 29const char kMiniInstaller[] = "mini_installer"; 30const char kOut[] = "out"; 31const char kPrevious[] = "previous"; 32 33} // namespace switches 34 35namespace errors { 36 37enum ErrorCode { 38 SHOW_HELP, 39 MINI_INSTALLER_NOT_FOUND, 40 OUT_FILE_EXISTS, 41 GENERATION_FAILED 42}; 43 44const 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 51const 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. 61void 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, 75L"Usage: %s [ OPTIONS ]\n" 76L" Where OPTIONS is one or more of:\n" 77L" --help Display this help message.\n" 78L" --force Overwrite any existing output files.\n" 79L" --mini_installer=SRC_PATH Path to mini_installer.exe. Default value is\n" 80L" \"mini_installer.exe\" in the same directory as\n" 81L" this program.\n" 82L" --out=OUT_PATH Path to output file. Default value is\n" 83L" \"mini_installer_new.exe\" in the current\n" 84L" directory.\n" 85L" --previous OUT_PATH will have a lower version than\n" 86L" SRC_PATH. By default, OUT_PATH will have a\n" 87L" higher version.\n" 88L" --7za_path=7ZA_PATH Path to the directory holding 7za.exe. Defaults\n" 89L" to ..\\..\\third_party\\lzma_sdk\\Executable\n" 90L" 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. 96bool 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|. 109void 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. 119upgrade_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. 127int 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