Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[vcpkg-artifacts] Find git using vcpkg fetch git. #569

Merged
merged 11 commits into from
Jun 6, 2022
8 changes: 4 additions & 4 deletions ce/ce/archivers/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class Git {
* @param events The events that may need to be updated in order to track progress.
* @param options The options that will modify how the clone will be called.
* @returns Boolean representing whether the execution was completed without error, this is not necessarily
* a gaurantee that the clone did what we expected.
* a guarantee that the clone did what we expected.
*/
async clone(repo: Uri, events: Partial<InstallEvents>, options: { recursive?: boolean, depth?: number } = {}) {
const remote = await isFilePath(repo) ? repo.fsPath : repo.toString();
Expand Down Expand Up @@ -72,7 +72,7 @@ export class Git {
* @param events Events that may be called in order to present progress.
* @param options Options to modify how fetch is called.
* @returns Boolean representing whether the execution was completed without error, this is not necessarily
* a gaurantee that the fetch did what we expected.
* a guarantee that the fetch did what we expected.
*/
async fetch(remoteName: string, events: Partial<InstallEvents>, options: { commit?: string, recursive?: boolean, depth?: number } = {}) {
const result = await execute(this.#toolPath, [
Expand Down Expand Up @@ -100,7 +100,7 @@ export class Git {
* @param events Events to possibly track progress.
* @param options Passing along a commit or branch to checkout, optionally.
* @returns Boolean representing whether the execution was completed without error, this is not necessarily
* a gaurantee that the checkout did what we expected.
* a guarantee that the checkout did what we expected.
*/
async checkout(events: Partial<InstallEvents>, options: { commit?: string } = {}) {
const result = await execute(this.#toolPath, [
Expand All @@ -124,7 +124,7 @@ export class Git {
* @param events Events to possibly track progress.
* @param options Options to control how the reset is called.
* @returns Boolean representing whether the execution was completed without error, this is not necessarily
* a gaurantee that the reset did what we expected.
* a guarantee that the reset did what we expected.
*/
async reset(events: Partial<InstallEvents>, options: { commit?: string, recurse?: boolean, hard?: boolean } = {}) {
const result = await execute(this.#toolPath, [
Expand Down
4 changes: 2 additions & 2 deletions ce/ce/artifacts/activation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ export class Activation {
return `$${obj}.${member}`;
}

this.#session.channels.debug(i`Unresolved varible reference found ($${obj}.${member}) during variable substitution.`);
this.#session.channels.debug(i`Unresolved variable reference found ($${obj}.${member}) during variable substitution.`);
return `$${obj}.${member}`;
}

Expand Down Expand Up @@ -764,4 +764,4 @@ async function toArrayAsync<T>(iterable: AsyncIterable<T>) {
result.push(item);
}
return result;
}
}
11 changes: 7 additions & 4 deletions ce/ce/cli/command-line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ export class CommandLine {
join(process.env['HOME'] || process.env['USERPROFILE'] || tmpdir(), '.vcpkg')));
}

#vcpkgCommand?: string;
get vcpkgCommand() {
return this.#vcpkgCommand || (this.#vcpkgCommand = resolvePath(
this.switches['vcpkg-command']?.[0] ||
process.env['VCPKG_COMMAND']));
}

get force() {
return !!this.switches['force'];
}
Expand All @@ -108,10 +115,6 @@ export class CommandLine {
return !!this.switches['verbose'];
}

get fromVCPKG() {
return !!this.switches['from-vcpkg'];
}

get language() {
const l = this.switches['language'] || [];
strict.ok((l?.length || 0) < 2, i`Expected a single value for ${cmdSwitch('language')} - found multiple`);
Expand Down
2 changes: 1 addition & 1 deletion ce/ce/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Licensed under the MIT License.

export const undo = 'Z_VCPKG_UNDO';
export const postscriptVarible = 'Z_VCPKG_POSTSCRIPT';
export const postscriptVariable = 'Z_VCPKG_POSTSCRIPT';
export const blank = '\n';
export const latestVersion = '*';
export const vcpkgDownloadFolder = 'VCPKG_DOWNLOADS';
Expand Down
5 changes: 3 additions & 2 deletions ce/ce/installers/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import { InstallEvents, InstallOptions } from '../interfaces/events';
import { CloneSettings, GitInstaller } from '../interfaces/metadata/installers/git';
import { Session } from '../session';
import { Uri } from '../util/uri';
import { Vcpkg } from '../vcpkg';

export async function installGit(session: Session, name: string, targetLocation: Uri, install: GitInstaller, events: Partial<InstallEvents>, options: Partial<InstallOptions & CloneOptions & CloneSettings>): Promise<void> {
// const gitPath = await session.activation.getAlias('git');
const gitPath = '';
const vcpkg = new Vcpkg(session);

const gitPath = await vcpkg.fetch('git');

if (!gitPath) {
throw new Error(i`Git is not installed`);
Expand Down
2 changes: 1 addition & 1 deletion ce/ce/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const commandline = new CommandLine(argv.slice(2));
setLocale(commandline.language, `${__dirname}/i18n/`);

function header() {
if (!commandline.fromVCPKG) {
if (!commandline.vcpkgCommand) {
if (commandline.debug) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
log(`${green.bold(`${product} command line utility`)} ${white.bold(cliVersion)} [node: ${white.bold(process.version)}; max-memory: ${white.bold(Math.round((require('v8').getHeapStatistics().heap_size_limit) / (1024 * 1024)) & 0xffffffff00)} gb]`);
Expand Down
7 changes: 5 additions & 2 deletions ce/ce/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { MetadataFile } from './amf/metadata-file';
import { Activation, deactivate } from './artifacts/activation';
import { Artifact, InstalledArtifact } from './artifacts/artifact';
import { Registry } from './artifacts/registry';
import { defaultConfig, globalConfigurationFile, postscriptVarible, profileNames, registryIndexFile, undo, vcpkgDownloadFolder } from './constants';
import { defaultConfig, globalConfigurationFile, postscriptVariable, profileNames, registryIndexFile, undo, vcpkgDownloadFolder } from './constants';
import { FileSystem, FileType } from './fs/filesystem';
import { HttpsFileSystem } from './fs/http-filesystem';
import { LocalFileSystem } from './fs/local-filesystem';
Expand Down Expand Up @@ -71,6 +71,7 @@ export class Session {
readonly tmpFolder: Uri;
readonly installFolder: Uri;
readonly registryFolder: Uri;
readonly vcpkgCommand?: string;
readonly activation: Activation = new Activation(this);

readonly globalConfig: Uri;
Expand Down Expand Up @@ -106,6 +107,8 @@ export class Session {
this.cache = this.environment[vcpkgDownloadFolder] ? this.parseUri(this.environment[vcpkgDownloadFolder]!) : this.homeFolder.join('downloads');
this.globalConfig = this.homeFolder.join(globalConfigurationFile);

this.vcpkgCommand = settings['vcpkgCommand'];

this.tmpFolder = this.homeFolder.join('tmp');
this.installFolder = this.homeFolder.join('artifacts');

Expand Down Expand Up @@ -250,7 +253,7 @@ export class Session {

#postscriptFile?: Uri;
get postscriptFile() {
return this.#postscriptFile || (this.#postscriptFile = this.environment[postscriptVarible] ? this.fileSystem.file(this.environment[postscriptVarible]!) : undefined);
return this.#postscriptFile || (this.#postscriptFile = this.environment[postscriptVariable] ? this.fileSystem.file(this.environment[postscriptVariable]!) : undefined);
}

async init() {
Expand Down
41 changes: 41 additions & 0 deletions ce/ce/vcpkg.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { spawn } from "child_process";
import { Session } from "./session";

/** @internal */
export class Vcpkg {
constructor(private readonly session: Session) {}

fetch(fetchKey: string): Promise<string | undefined> {
return this.runVcpkg(['fetch', fetchKey, '--x-stderr-status']).then((results) => {
if (results === undefined) {
if (fetchKey === 'git') {
this.session.channels.warning('failed to fetch git, falling back to attempting to use git from the PATH');
return 'git';
}

return results;
}

return results.trimEnd();
});
}

private runVcpkg(args: string[]): Promise<string | undefined> {
return new Promise((accept, reject) => {
if (!this.session.vcpkgCommand) {
accept(undefined);
return;
}

const subproc = spawn(this.session.vcpkgCommand, args, {stdio: ['ignore', 'pipe', 'pipe']});
let result = '';
subproc.stdout.on('data', (chunk) => { result += chunk; });
subproc.stderr.pipe(process.stdout);
subproc.on('error', (err) => { reject(err); });
subproc.on('close', (code, signal) => {
if (code === 0) { accept(result); }
accept(undefined);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be

Suggested change
accept(undefined);
reject("vcpkg returned nonzero exit code: " + result)

or just reject(result)?

});
});
}
}
14 changes: 10 additions & 4 deletions include/vcpkg/archives.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,26 @@ namespace vcpkg
// Extract `archive` to `to_path` using `cmake_tool`. (CMake's built in tar)
void extract_tar_cmake(const Path& cmake_tool, const Path& archive, const Path& to_path);
// Extract `archive` to `to_path`, deleting `to_path` first.
void extract_archive(Filesystem& fs, const ToolCache& tools, const Path& archive, const Path& to_path);
void extract_archive(
Filesystem& fs, const ToolCache& tools, MessageSink& status_sink, const Path& archive, const Path& to_path);

#ifdef _WIN32
// Extract the 7z archive part of a self extracting 7z installer
void win32_extract_self_extracting_7z(Filesystem& fs, const Path& archive, const Path& to_path);
// Extract `archive` to `to_path`, deleting `to_path` first. `archive` must be a zip file.
// This function will use potentially less performant tools that are reliably available on any machine.
void win32_extract_bootstrap_zip(Filesystem& fs, const ToolCache& tools, const Path& archive, const Path& to_path);
void win32_extract_bootstrap_zip(
Filesystem& fs, const ToolCache& tools, MessageSink& status_sink, const Path& archive, const Path& to_path);
#endif

// Compress the source directory into the destination file.
int compress_directory_to_zip(Filesystem& fs, const ToolCache& tools, const Path& source, const Path& destination);
int compress_directory_to_zip(
Filesystem& fs, const ToolCache& tools, MessageSink& status_sink, const Path& source, const Path& destination);

Command decompress_zip_archive_cmd(const ToolCache& tools, const Path& dst, const Path& archive_path);
Command decompress_zip_archive_cmd(const ToolCache& tools,
MessageSink& status_sink,
const Path& dst,
const Path& archive_path);

std::vector<ExitCodeAndOutput> decompress_in_parallel(View<Command> jobs);
}
2 changes: 2 additions & 0 deletions include/vcpkg/base/fwd/messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ namespace vcpkg
#endif

struct LocalizedString;
struct MessageSink;
}

namespace vcpkg::msg
{
void write_unlocalized_text_to_stdout(Color c, vcpkg::StringView sv);
void write_unlocalized_text_to_stderr(Color c, vcpkg::StringView sv);
}
64 changes: 60 additions & 4 deletions include/vcpkg/base/messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,23 +205,23 @@ namespace vcpkg::msg
}

template<class Message, class... Ts>
void print(Message m, Ts... args)
typename Message::is_message_type print(Message m, Ts... args)
{
print(format(m, args...));
}
template<class Message, class... Ts>
void println(Message m, Ts... args)
typename Message::is_message_type println(Message m, Ts... args)
{
print(format(m, args...).append_raw('\n'));
}

template<class Message, class... Ts>
void print(Color c, Message m, Ts... args)
typename Message::is_message_type print(Color c, Message m, Ts... args)
{
print(c, format(m, args...));
}
template<class Message, class... Ts>
void println(Color c, Message m, Ts... args)
typename Message::is_message_type println(Color c, Message m, Ts... args)
{
print(c, format(m, args...).append_raw('\n'));
}
Expand Down Expand Up @@ -340,4 +340,60 @@ namespace vcpkg::msg
{
return format(msgErrorMessage).append(m, args...);
}

}

namespace vcpkg
{
struct MessageSink
{
virtual void print(Color c, StringView sv) = 0;

void println() { this->print(Color::none, "\n"); }
void print(const LocalizedString& s) { this->print(Color::none, s); }
void println(Color c, const LocalizedString& s)
{
this->print(c, s);
this->print(Color::none, "\n");
}
inline void println(const LocalizedString& s)
{
this->print(Color::none, s);
this->print(Color::none, "\n");
}

template<class Message, class... Ts>
typename Message::is_message_type print(Message m, Ts... args)
{
this->print(Color::none, msg::format(m, args...));
}

template<class Message, class... Ts>
typename Message::is_message_type println(Message m, Ts... args)
{
this->print(Color::none, msg::format(m, args...).append_raw('\n'));
}

template<class Message, class... Ts>
typename Message::is_message_type print(Color c, Message m, Ts... args)
{
this->print(c, msg::format(m, args...));
}

template<class Message, class... Ts>
typename Message::is_message_type println(Color c, Message m, Ts... args)
{
this->print(c, msg::format(m, args...).append_raw('\n'));
}

MessageSink(const MessageSink&) = delete;
MessageSink& operator=(const MessageSink&) = delete;

protected:
MessageSink() = default;
~MessageSink() = default;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
~MessageSink() = default;
virtual ~MessageSink() = default;

Agreed nobody should ever be deleting it through the interface, but it seems good practice anyway.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Being protected already gives it the right behavior here.

};

extern MessageSink& stdout_sink;
extern MessageSink& stderr_sink;
}
4 changes: 2 additions & 2 deletions include/vcpkg/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ namespace vcpkg
{
virtual ~ToolCache() = default;

virtual const Path& get_tool_path(StringView tool) const = 0;
virtual const std::string& get_tool_version(StringView tool) const = 0;
virtual const Path& get_tool_path(StringView tool, MessageSink& status_sink) const = 0;
virtual const std::string& get_tool_version(StringView tool, MessageSink& status_sink) const = 0;
};

ExpectedS<std::string> extract_prefixed_nonwhitespace(StringLiteral prefix,
Expand Down
4 changes: 2 additions & 2 deletions include/vcpkg/vcpkgpaths.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ namespace vcpkg
std::string get_toolver_diagnostics() const;

const ToolCache& get_tool_cache() const;
const Path& get_tool_exe(StringView tool) const;
const std::string& get_tool_version(StringView tool) const;
const Path& get_tool_exe(StringView tool, MessageSink& status_messages) const;
const std::string& get_tool_version(StringView tool, MessageSink& status_messages) const;

GitConfig git_builtin_config() const;
Command git_cmd_builder(const Path& dot_git_dir, const Path& work_tree) const;
Expand Down
Loading