Skip to content

Commit

Permalink
Merge branch 'main' into fix_#699-#700
Browse files Browse the repository at this point in the history
  • Loading branch information
leoafarias authored Oct 1, 2024
2 parents 962d5e0 + 11c998a commit 9e25e27
Show file tree
Hide file tree
Showing 29 changed files with 1,032 additions and 173 deletions.
1 change: 1 addition & 0 deletions .github/workflows/deploy_docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ jobs:
with:
file: ./.docker/Dockerfile
push: true
tags: leoafarias/fvm:latest

14 changes: 13 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,18 @@ jobs:
- name: Set up QEMU
uses: docker/setup-qemu-action@v1

- name: Get and modify tag name
id: get_tag_name
run: |
# Extract the tag name from the GitHub ref
TAG_NAME=${{ github.ref_name }}
# Remove leading 'v' from the tag name, if present
MODIFIED_TAG_NAME=$(echo "$TAG_NAME" | sed 's/^v//')
# Set the modified tag name as an environment variable
echo "MODIFIED_TAG_NAME=$MODIFIED_TAG_NAME" >> $GITHUB_ENV
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1

Expand All @@ -112,4 +124,4 @@ jobs:
with:
file: ./.docker/Dockerfile
push: true
tags: leoafarias/fvm:{{ github.event.release.tag_name }}
tags: leoafarias/fvm:{{ steps.get_tag_name.outputs.modified_tag_name}}
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
## 3.2.1

* fix: `--fvm-skip-input` flag not applying to context
* add: `fvm list` now displays the cache path even if no version is installed

## 3.2.0

* add: support for skipping input requests by @Rexios80. Input requests are skipped when the `--fvm-skip-input` flag is passed.
* add: documentation for command rerouting by @humblerookie
* fix(cosmetics): fvm has one newline too much by @jonasbadstuebner
* fix: unsupported architecture on arm64 by @MrCyjaneK
* add: tags for Docker deployment by @CodeRedDev
* add: Validate if git is installed by @leoafarias
* add: Disable local mirror on exception by @leoafarias

## 3.1.7

* Display the configured version in the `fvm list` command by @digoreis
Expand Down
2 changes: 1 addition & 1 deletion bin/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Future<void> main(List<String> args) async {
final scope = Scope()..value(contextKey, FVMContext.create(args: args));

await _flushThenExit(
await scope.run(() => FvmCommandRunner().run((args))),
await scope.run(() async => FvmCommandRunner().run((ctx.args))),
);
}

Expand Down
99 changes: 94 additions & 5 deletions docs/pages/documentation/advanced/custom-version.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,105 @@ import { Callout } from "nextra/components";

# Custom Flutter Version (Forks)

You can use custom Flutter versions (forks) within the FVM cache.
In case you need to have a custom version of the Flutter SDK (a fork), referenced within a project, and you want to continue to use FVM, you can do so by following the steps below.

To do that, you have to prefix the version with `custom_` and then add the name of the version. For example, if you want to use a custom version of Flutter, you can do the following:
There are two ways to use a custom version of the Flutter SDK:

## **Clone the fork within the FVM cache**

This method is useful if you want to use a fork of the Flutter SDK within a project and reference that "custom" version like you would releases or channels.

**1. Look for the path where FVM caches the versions. You can find this path by running the following command:**

```bash
fvm use [custom_name]
fvm list
```

Output:
```ansi terminal
Cache directory: /Users/{user}/fvm/versions
Directory Size: 6.47 GB
┌────────────────┬─────────┬────────────────────┬─────────────────┬──────────────┬────────┬───────┐
│ Version  │ Channel │ Flutter Version  │ Dart Version  │ Release Date │ Global │ Local │
├────────────────┼─────────┼────────────────────┼─────────────────┼──────────────┼────────┼───────┤
│ stable  │ stable  │ 3.24.1  │ 3.5.1  │ Aug 21, 2024 │   │   │
├────────────────┼─────────┼────────────────────┼─────────────────┼──────────────┼────────┼───────┤
│ 3.19.0  │ stable  │ 3.19.0  │ 3.3.0  │ Feb 15, 2024 │   │   │
└────────────────┴─────────┴────────────────────┴─────────────────┴──────────────┴────────┴───────┘
```
**2. Clone the fork of the Flutter SDK into the cache directory.**

When cloning, make sure to prefix the version with `custom_` and then add the name of the version. For example, if you want to fork a version called `special`, you will have to clone it into the cache directory as `custom_special`.

The prefix `custom_` is used to differentiate the custom versions from the official Flutter versions and allows FVM to not apply the same level of validation as it does with the official versions.

Now, when you run `fvm list`, you should see the custom version in the list.
<Callout type="warning">
Make sure you always clone the whole repository using the command `git clone url-to-repository.git`.
Do not use `--depth` or `--single-branch` as it might cause issues with the Flutter SDK.
Flutter Tools depends on repository references to determine its version correct version.
</Callout>

Output:

```ansi
Cache directory: /Users/{user}/fvm/versions
Directory Size: 6.47 GB
┌────────────────┬─────────┬────────────────────┬─────────────────┬──────────────┬────────┬───────┐
│ Version  │ Channel │ Flutter Version  │ Dart Version  │ Release Date │ Global │ Local │
├────────────────┼─────────┼────────────────────┼─────────────────┼──────────────┼────────┼───────┤
│ custom_special │   │ 3.24.0-1.0.pre.575 │ 3.6.0-146.0.dev │   │   │   │
├────────────────┼─────────┼────────────────────┼─────────────────┼──────────────┼────────┼───────┤
│ stable  │ stable  │ 3.24.1  │ 3.5.1  │ Aug 21, 2024 │   │   │
├────────────────┼─────────┼────────────────────┼─────────────────┼──────────────┼────────┼───────┤
│ 3.19.0  │ stable  │ 3.19.0  │ 3.3.0  │ Feb 15, 2024 │   │   │
└────────────────┴─────────┴────────────────────┴─────────────────┴──────────────┴────────┴───────┘
```
**3. Use the custom version within your project.**

You can now use the custom version within your project by running the following command, but referencing it as `custom_special`:

```bash
fvm use custom_special
```

## **Change the repository URL to the fork**

With FVM, you can also change the repository URL to the fork you want to use. This method is useful if you want to use a fork of the Flutter SDK globally and want to continue to reference releases and channels from the fork version.

There are a few ways you can do this:

**Option 1. Change the repository URL globally used by FVM**
```bash
fvm config --flutter-url https://github.com/org/custom-flutter.git
```

Now, when you run `fvm install` or `fvm use`, it will use the custom repository URL.

<Callout type="info">
If you already have versions installed, you will have to reinstall them to use the custom repository URL version of them.
</Callout>

Run `fvm list` to view the cache directory and the current cached versions.
**Option 2. Change the environment variable**

</Callout>
You can also change the repository URL by setting the environment variable `FVM_FLUTTER_URL`:

```bash
# Change the env var in your shell profile
export FVM_FLUTTER_URL="https://github.com/org/custom-flutter.git"
```
### **Setting the custom repository URL per project**

You can also set the custom repository URL per project by creating a `.fvmrc` file in the root of your project and adding the following:

<Callout type="warning">
Keep in mind that for each project, the releases and channels need to be different from the ones used in other projects; otherwise, there might be some conflict. A good idea would be to reserve certain versions like `master`, for example.
</Callout>

```json filename=".fvmrc"
{
"flutterUrl": "https://github.com/org/custom-flutter.git"
}
```
2 changes: 2 additions & 0 deletions docs/pages/documentation/guides/basic-commands.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ Sets a specific Flutter SDK version for a project, ensuring environment consiste
- `-s, --skip-setup`: Omits Flutter setup post-installation for expedited process.
- `--skip-pub-get`: Skips resolving dependencies (`flutter pub get`) after switching Flutter SDK.

- `--fvm-skip-input`: Skips requests for user input and uses default values.

### Examples

**Setting a Specific Version**:
Expand Down
2 changes: 1 addition & 1 deletion lib/src/commands/install_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class InstallCommand extends BaseCommand {
..addFlag(
'setup',
abbr: 's',
help: 'Builds SDK after install after install',
help: 'Builds SDK after install',
defaultsTo: false,
negatable: false,
)
Expand Down
30 changes: 20 additions & 10 deletions lib/src/commands/list_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import 'package:mason_logger/mason_logger.dart';

import '../services/cache_service.dart';
import '../services/global_version_service.dart';
import '../services/project_service.dart';
import '../services/logger_service.dart';
import '../services/project_service.dart';
import '../services/releases_service/models/version_model.dart';
import '../services/releases_service/releases_client.dart';
import '../utils/context.dart';
Expand All @@ -27,14 +27,6 @@ class ListCommand extends BaseCommand {
Future<int> run() async {
final cacheVersions = await CacheService.fromContext.getAllVersions();

if (cacheVersions.isEmpty) {
logger
..info('No SDKs have been installed yet. Flutter. SDKs')
..info('installed outside of fvm will not be displayed.');

return ExitCode.success.code;
}

final directorySize = await getFullDirectorySize(cacheVersions);

// Print where versions are stored
Expand All @@ -43,6 +35,24 @@ class ListCommand extends BaseCommand {
..info('Directory Size: ${formatBytes(directorySize)}')
..spacer;

if (cacheVersions.any((e) => e.isNotSetup)) {
logger
..warn(
'Some versions might still require finishing setup - SDKs have been cloned, but they have not downloaded their dependencies.',
)
..info(
'This will complete the first time you run any command with the SDK.',
)
..spacer;
}
if (cacheVersions.isEmpty) {
logger
..info('No SDKs have been installed yet. Flutter. SDKs')
..info('installed outside of fvm will not be displayed.');

return ExitCode.success.code;
}

final releases = await FlutterReleasesClient.getReleases();
final globalVersion = GlobalVersionService.fromContext.getGlobal();
final localVersion = ProjectService.fromContext.findVersion();
Expand Down Expand Up @@ -79,7 +89,7 @@ class ListCommand extends BaseCommand {

String getVersionOutput() {
if (version.isNotSetup) {
return flutterSdkVersion = '${yellow.wrap('Need setup')}';
return flutterSdkVersion = '${yellow.wrap('Need setup*')}';
}
if (latestRelease != null && version.isChannel) {
// If its not the latest version
Expand Down
3 changes: 3 additions & 0 deletions lib/src/models/flutter_version_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,7 @@ class FlutterVersion with FlutterVersionMappable {

return compareSemver(versionWeight, otherVersion);
}

@override
String toString() => name;
}
4 changes: 3 additions & 1 deletion lib/src/services/config_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ class ConfigRepository {
final isRootDir = path.rootPrefix(directory.path) == directory.path;

// Gets project from directory
final projectConfig = ProjectConfig.loadFromPath(directory.path);
final projectConfig = ProjectConfig.loadFromPath(
path.join(directory.path, kFvmConfigFileName),
);

// If project has a config return it
if (projectConfig != null) return projectConfig;
Expand Down
15 changes: 11 additions & 4 deletions lib/src/services/flutter_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ class FlutterService extends ContextService {
}

/// Clones Flutter SDK from Version Number or Channel
Future<void> install(FlutterVersion version) async {
Future<void> install(
FlutterVersion version, {
required bool useGitCache,
}) async {
final versionDir = CacheService(context).getVersionCacheDir(version.name);

// Check if its git commit
Expand Down Expand Up @@ -75,7 +78,7 @@ class FlutterService extends ContextService {
final cloneArgs = [
//if its a git hash
if (!version.isCommit) ...versionCloneParams,
if (context.gitCache) ...useMirrorParams,
if (useGitCache) ...useMirrorParams,
];

try {
Expand Down Expand Up @@ -215,13 +218,17 @@ class FlutterServiveMock extends FlutterService {
FlutterServiveMock(FVMContext context) : super(context);

@override
Future<void> install(FlutterVersion version) async {
Future<void> install(
FlutterVersion version, {
required bool useGitCache,
}) async {
/// Moves directory from main context HOME/fvm/versions to test context
final mainContext = FVMContext.main;
var cachedVersion = CacheService(mainContext).getVersion(version);
if (cachedVersion == null) {
await FlutterService(mainContext).install(version);
await FlutterService(mainContext)
.install(version, useGitCache: useGitCache);
cachedVersion = CacheService(mainContext).getVersion(version);
}
final versionDir = CacheService(mainContext).getVersionCacheDir(
Expand Down
29 changes: 24 additions & 5 deletions lib/src/services/logger_service.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:io';

import 'package:dart_console/dart_console.dart';
import 'package:interact/interact.dart' as interact;
Expand Down Expand Up @@ -63,19 +64,39 @@ class LoggerService extends ContextService {
return progress;
}

bool confirm(String? message, {bool? defaultValue}) {
bool confirm(String? message, {required bool defaultValue}) {
// When running tests, always return true.
if (context.isTest) return true;

if (context.isCI || context.skipInput) {
logger.info(message ?? '');
logger
..warn('Skipping input confirmation')
..warn('Using default value of $defaultValue');

return defaultValue;
}

return interact.Confirm(prompt: message ?? '', defaultValue: defaultValue)
.interact();
}

String select(String? message, {required List<String> options}) {
String select(
String? message, {
required List<String> options,
int? defaultSelection,
}) {
if (context.skipInput) {
if (defaultSelection != null) {
return options[defaultSelection];
}
exit(ExitCode.usage.code);
}

final selection = interact.Select(
prompt: message ?? '',
options: options,
initialIndex: 0,
initialIndex: defaultSelection ?? 0,
).interact();

return options[selection];
Expand Down Expand Up @@ -113,8 +134,6 @@ class LoggerService extends ContextService {
final dot = '\u{25CF}'; // ●
final rightArrow = '\u{2192}'; // →

/// Logger for FVM
/// Console controller instance
final consoleController = ConsoleController();

/// Console Controller
Expand Down
Loading

0 comments on commit 9e25e27

Please sign in to comment.