alternate_version_generator_main.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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