Skip to content

Commit ccb24f3

Browse files
authored
feat: convert dart installer (#1197)
1 parent 13aa745 commit ccb24f3

File tree

6 files changed

+124
-62
lines changed

6 files changed

+124
-62
lines changed

README.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,12 @@ RUN install-tool docker 20.10.7
9494
### Url replacement
9595

9696
You can replace the default urls used to download the tools.
97-
This is currently only supported by the `docker` tool installer.
98-
Checkout #1067 for additional support.
97+
This is currently only supported by these tool installers:
98+
99+
- `docker`
100+
- `dart`
101+
102+
Checkout [#1067](https://github.com/containerbase/base/issues/1067) for additional support.
99103

100104
```Dockerfile
101105
FROM containerbase/base

src/cli/install-tool/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Container } from 'inversify';
22
import { rootContainer } from '../services';
3+
import { InstallDartService } from '../tools/dart';
34
import { InstallDockerService } from '../tools/docker';
45
import { logger } from '../utils';
56
import { InstallLegacyToolService } from './install-legacy-tool.service';
@@ -16,6 +17,7 @@ function prepareContainer(): Container {
1617

1718
// tool services
1819
container.bind(INSTALL_TOOL_TOKEN).to(InstallDockerService);
20+
container.bind(INSTALL_TOOL_TOKEN).to(InstallDartService);
1921

2022
logger.trace('preparing container done');
2123
return container;

src/cli/prepare-tool/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Container } from 'inversify';
22
import { rootContainer } from '../services';
3+
import { PrepareDartService } from '../tools/dart';
34
import { PrepareDockerService } from '../tools/docker';
45
import { logger } from '../utils';
56
import { PrepareLegacyToolsService } from './prepare-legacy-tools.service';
@@ -16,6 +17,7 @@ function prepareContainer(): Container {
1617

1718
// tool services
1819
container.bind(PREPARE_TOOL_TOKEN).to(PrepareDockerService);
20+
container.bind(PREPARE_TOOL_TOKEN).to(PrepareDartService);
1921

2022
logger.trace('preparing container done');
2123
return container;

src/cli/services/env.service.ts

+5
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ export class EnvService {
3030
return env.CONTAINERBASE_CACHE_DIR ?? null;
3131
}
3232

33+
get home(): string {
34+
// TODO: validate
35+
return env.HOME!;
36+
}
37+
3338
get isRoot(): boolean {
3439
return this.uid === 0;
3540
}

src/cli/tools/dart/index.ts

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import fs from 'node:fs/promises';
2+
import { join } from 'node:path';
3+
import { execa } from 'execa';
4+
import { inject, injectable } from 'inversify';
5+
import semver from 'semver';
6+
import { InstallToolBaseService } from '../../install-tool/install-tool-base.service';
7+
import { PrepareToolBaseService } from '../../prepare-tool/prepare-tool-base.service';
8+
import { EnvService, HttpService, PathService } from '../../services';
9+
import { logger } from '../../utils';
10+
11+
// Dart SDK sample urls
12+
// https://storage.googleapis.com/dart-archive/channels/stable/release/1.11.0/sdk/dartsdk-linux-x64-release.zip
13+
// https://storage.googleapis.com/dart-archive/channels/stable/release/2.18.0/sdk/dartsdk-linux-x64-release.zip
14+
// https://storage.googleapis.com/dart-archive/channels/stable/release/2.19.4/sdk/dartsdk-linux-x64-release.zip.sha256sum
15+
// https://storage.googleapis.com/dart-archive/channels/stable/release/2.19.4/sdk/dartsdk-linux-arm64-release.zip
16+
// https://storage.googleapis.com/dart-archive/channels/stable/release/2.19.4/sdk/dartsdk-linux-arm64-release.zip.sha256sum
17+
18+
@injectable()
19+
export class PrepareDartService extends PrepareToolBaseService {
20+
readonly name = 'dart';
21+
22+
constructor(@inject(EnvService) private envSvc: EnvService) {
23+
super();
24+
}
25+
26+
async execute(): Promise<void> {
27+
await fs.mkdir(`${this.envSvc.home}/.dart`);
28+
await fs.writeFile(
29+
`${this.envSvc.home}/.dart/dartdev.json`,
30+
'{ "firstRun": false, "enabled": false }'
31+
);
32+
await fs.mkdir(`${this.envSvc.userHome}/.dart`);
33+
await fs.writeFile(
34+
`${this.envSvc.userHome}/.dart/dartdev.json`,
35+
'{ "firstRun": false, "enabled": false }'
36+
);
37+
38+
// fs isn't recursive, so we use system binaries
39+
await execa('chown', [
40+
'-R',
41+
this.envSvc.userName,
42+
`${this.envSvc.userHome}/.dart`,
43+
]);
44+
await execa('chmod', ['-R', 'g=u', `${this.envSvc.userHome}/.dart`]);
45+
}
46+
}
47+
48+
@injectable()
49+
export class InstallDartService extends InstallToolBaseService {
50+
readonly name = 'dart';
51+
52+
private get arch(): string {
53+
switch (this.envSvc.arch) {
54+
case 'arm64':
55+
return 'arm64';
56+
case 'amd64':
57+
return 'x64';
58+
}
59+
}
60+
61+
constructor(
62+
@inject(EnvService) envSvc: EnvService,
63+
@inject(PathService) pathSvc: PathService,
64+
@inject(HttpService) private http: HttpService
65+
) {
66+
super(pathSvc, envSvc);
67+
}
68+
69+
override async install(version: string): Promise<void> {
70+
const ver = semver.parse(version);
71+
if (!ver) {
72+
throw new Error(`Invalid version: ${version}`);
73+
}
74+
if (ver.major < 2) {
75+
throw new Error(`Dart SDK version < v2 is not supported: ${version}`);
76+
}
77+
const channel = 'stable';
78+
const sdkUrl = `https://storage.googleapis.com/dart-archive/channels/${channel}/release/${version}/sdk`;
79+
const sdkFile = `dartsdk-linux-${this.arch}-release.zip`;
80+
const url = `${sdkUrl}/${sdkFile}`;
81+
82+
logger.debug({ url: `${url}.sha256sum` }, `download ${this.name} checksum`);
83+
const checksumFile = await this.http.download({ url: `${url}.sha256sum` });
84+
const expectedChecksum = (await fs.readFile(checksumFile, 'utf-8'))
85+
.split('\n')
86+
.find((l) => l.includes(sdkFile))
87+
?.split(' ')[0];
88+
89+
logger.debug({ url }, `download ${this.name}`);
90+
const file = await this.http.download({
91+
url,
92+
expectedChecksum,
93+
checksumType: 'sha256',
94+
});
95+
96+
const path = await this.pathSvc.createVersionedToolPath(this.name, version);
97+
await execa('bsdtar', ['-xf', file, '-C', path, '--strip', '1']);
98+
}
99+
100+
override async link(version: string): Promise<void> {
101+
const src = join(this.pathSvc.versionedToolPath(this.name, version), 'bin');
102+
103+
await this.shellwrapper({ name: 'dart', srcDir: src });
104+
}
105+
106+
override async test(_version: string): Promise<void> {
107+
await execa('dart', ['--version'], { stdio: 'inherit' });
108+
}
109+
}

src/usr/local/containerbase/tools/v2/dart.sh

-60
This file was deleted.

0 commit comments

Comments
 (0)