Home | History | Annotate | Download | only in test
      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/files/file_path.h"
     15 #include "base/files/file_util.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