diff --git a/packages/katana_cli/lib/action/git/hook.dart b/packages/katana_cli/lib/action/git/hook.dart index e24e43ce7..afeb1e6d2 100644 --- a/packages/katana_cli/lib/action/git/hook.dart +++ b/packages/katana_cli/lib/action/git/hook.dart @@ -1,4 +1,6 @@ // Project imports: +import 'dart:io'; + import 'package:katana_cli/katana_cli.dart'; /// Add a Git hook for Flutter using Lefthook. @@ -40,13 +42,18 @@ class GitPreCommitCliAction extends CliCommand with CliActionMixin { ], ); label("Create lefthook.yaml"); - await const LefthookCliCode().generateFile("lefthook.yaml"); + final gitDir = await findGitDirectory(Directory.current); + final relativePath = Directory.current.difference(gitDir); + await const LefthookCliCode().generateFile( + "${relativePath.isEmpty ? "" : "$relativePath/"}lefthook.yaml", + ); await command( "Install lefthook.", [ lefthook, "install", ], + workingDirectory: gitDir?.path, ); } } diff --git a/packages/katana_cli/lib/action/git/platform/android.dart b/packages/katana_cli/lib/action/git/platform/android.dart index 69bdb9654..a3987be9c 100644 --- a/packages/katana_cli/lib/action/git/platform/android.dart +++ b/packages/katana_cli/lib/action/git/platform/android.dart @@ -82,7 +82,8 @@ Future buildAndroid( serviceAccount, ], ); - await const GithubActionsAndroidCliCode().generateFile( + final gitDir = await findGitDirectory(Directory.current); + await GithubActionsAndroidCliCode(workingDirectory: gitDir).generateFile( "build_android_${appName.toLowerCase()}.yaml", filter: (value) { return value @@ -144,7 +145,12 @@ class GithubActionsAndroidCliCode extends CliCode { /// Contents of buiod.yaml for Android in Github Actions. /// /// Github ActionsのAndroid用のbuiod.yamlの中身。 - const GithubActionsAndroidCliCode(); + const GithubActionsAndroidCliCode({this.workingDirectory}); + + /// Working Directory. + /// + /// ワーキングディレクトリ。 + final Directory? workingDirectory; @override String get name => "build_android"; @@ -154,16 +160,8 @@ class GithubActionsAndroidCliCode extends CliCode { @override String get directory { - int i = 0; - var current = Directory.current; - while (!Directory("${current.path}/.git").existsSync()) { - i++; - if (i > 5) { - return "${Directory.current.path}/.github/workflows"; - } - current = current.parent; - } - return "${current.path}/.github/workflows"; + final workingPath = Directory.current.difference(workingDirectory); + return "${workingPath.isEmpty ? "." : workingPath}/.github/workflows"; } @override @@ -182,7 +180,7 @@ class GithubActionsAndroidCliCode extends CliCode { @override String body(String path, String baseName, String className) { - const workingPath = ""; + final workingPath = workingDirectory?.difference(Directory.current); return """ # Build and upload your Flutter Android app. # diff --git a/packages/katana_cli/lib/action/git/platform/ios.dart b/packages/katana_cli/lib/action/git/platform/ios.dart index 8f6850a73..8a1c31af5 100644 --- a/packages/katana_cli/lib/action/git/platform/ios.dart +++ b/packages/katana_cli/lib/action/git/platform/ios.dart @@ -161,7 +161,8 @@ Future buildIOS( issuerId, ], ); - await const GithubActionsIOSCliCode().generateFile( + final gitDir = await findGitDirectory(Directory.current); + await GithubActionsIOSCliCode(workingDirectory: gitDir).generateFile( "build_ios_${appName.toLowerCase()}.yaml", filter: (value) { return value.replaceAll( @@ -276,7 +277,12 @@ class GithubActionsIOSCliCode extends CliCode { /// Contents of buiod.yaml for IOS in Github Actions. /// /// Github ActionsのIOS用のbuiod.yamlの中身。 - const GithubActionsIOSCliCode(); + const GithubActionsIOSCliCode({this.workingDirectory}); + + /// Working Directory. + /// + /// ワーキングディレクトリ。 + final Directory? workingDirectory; @override String get name => "build_ios"; @@ -286,16 +292,8 @@ class GithubActionsIOSCliCode extends CliCode { @override String get directory { - int i = 0; - var current = Directory.current; - while (!Directory("${current.path}/.git").existsSync()) { - i++; - if (i > 5) { - return "${Directory.current.path}/.github/workflows"; - } - current = current.parent; - } - return "${current.path}/.github/workflows"; + final workingPath = Directory.current.difference(workingDirectory); + return "${workingPath.isEmpty ? "." : workingPath}/.github/workflows"; } @override @@ -314,7 +312,7 @@ class GithubActionsIOSCliCode extends CliCode { @override String body(String path, String baseName, String className) { - const workingPath = ""; + final workingPath = workingDirectory?.difference(Directory.current); return """ # Build and upload a Flutter IOS app. # diff --git a/packages/katana_cli/lib/action/git/platform/web.dart b/packages/katana_cli/lib/action/git/platform/web.dart index ed69b057c..240561514 100644 --- a/packages/katana_cli/lib/action/git/platform/web.dart +++ b/packages/katana_cli/lib/action/git/platform/web.dart @@ -15,7 +15,8 @@ Future buildWeb( required String gh, required String appName, }) async { - const webCode = GithubActionsWebCliCode(); + final gitDir = await findGitDirectory(Directory.current); + final webCode = GithubActionsWebCliCode(workingDirectory: gitDir); var hostingYamlFile = File("${webCode.directory}/firebase-hosting-pull-request.yml"); @@ -53,7 +54,12 @@ class GithubActionsWebCliCode extends CliCode { /// Contents of buiod.yaml for Github Actions web. /// /// Github ActionsのWeb用のbuiod.yamlの中身。 - const GithubActionsWebCliCode(); + const GithubActionsWebCliCode({this.workingDirectory}); + + /// Working Directory. + /// + /// ワーキングディレクトリ。 + final Directory? workingDirectory; @override String get name => "build_web"; @@ -63,16 +69,8 @@ class GithubActionsWebCliCode extends CliCode { @override String get directory { - int i = 0; - var current = Directory.current; - while (!Directory("${current.path}/.git").existsSync()) { - i++; - if (i > 5) { - return "${Directory.current.path}/.github/workflows"; - } - current = current.parent; - } - return "${current.path}/.github/workflows"; + final workingPath = Directory.current.difference(workingDirectory); + return "${workingPath.isEmpty ? "." : workingPath}/.github/workflows"; } @override @@ -91,7 +89,7 @@ class GithubActionsWebCliCode extends CliCode { @override String body(String path, String baseName, String className) { - const workingPath = ""; + final workingPath = workingDirectory?.difference(Directory.current); return """ # Build and upload a Flutter web app. # @@ -182,6 +180,7 @@ jobs: final jobs = yaml.getAsMap("jobs"); final buildAndPreview = jobs.getAsMap("build_and_preview"); final steps = buildAndPreview.getAsList("steps"); + final workingPath = workingDirectory?.difference(Directory.current); var repoToken = ""; var firebaseServiceAccount = ""; var projectId = ""; @@ -203,9 +202,6 @@ jobs: projectId.isEmpty) { return source; } - final workingPath = Directory.current.path - .replaceAll(directory.replaceAll(".github/workflows", ""), "") - .trimString("/"); source += """ # A copy of the generated file. @@ -219,7 +215,7 @@ jobs: - name: Deploy to Firebase Hosting uses: FirebaseExtended/action-hosting-deploy@v0 with: - entryPoint: ${workingPath.isEmpty ? "firebase" : "$workingPath/firebase"} + entryPoint: ${workingPath.isEmpty ? "." : workingPath}/firebase repoToken: $repoToken firebaseServiceAccount: $firebaseServiceAccount channelId: live diff --git a/packages/katana_cli/lib/command/create.dart b/packages/katana_cli/lib/command/create.dart index 757400cb5..c0ed0c992 100644 --- a/packages/katana_cli/lib/command/create.dart +++ b/packages/katana_cli/lib/command/create.dart @@ -30,6 +30,7 @@ final importPackages = [ final allOptionsImportPackage = [ "flutter_animate", "font_awesome_flutter", + "url_strategy", ]; /// Package for dev to import. @@ -134,6 +135,7 @@ class CreateCliCommand extends CliCommand { "--dev", ...importDevPackages, "melos", + "import_sorter", ], ); label("Replace lib/${moduleName.toSnakeCase()}.dart"); diff --git a/packages/katana_cli/lib/src/framework.dart b/packages/katana_cli/lib/src/framework.dart index a6576a37d..f82ecb291 100644 --- a/packages/katana_cli/lib/src/framework.dart +++ b/packages/katana_cli/lib/src/framework.dart @@ -427,6 +427,56 @@ Future find(Directory root, Pattern pattern) async { return null; } +/// Get the first directory in [root] that matches [pattern]. +/// +/// [root]の中にある[pattern]に最初に当てはまるディレクトリを取得します。 +Future findDirectory(Directory root, Pattern pattern) async { + final files = root.list(recursive: true); + await for (final file in files) { + final name = file.path.trimQuery().last(); + final match = pattern.allMatches(name); + if (match.isEmpty) { + continue; + } + return Directory(file.path); + } + return null; +} + +/// Get the directory where Git resides. +/// +/// Gitが存在するディレクトリを取得します。 +Future findGitDirectory(Directory current) { + return findDirectory(current, RegExp(r"^\.git$")).then((value) { + if (value != null) { + return value.parent; + } + if (current.path == current.parent.path) { + return null; + } + return findGitDirectory(current.parent); + }); +} + +extension CliDirectoryExtensions on Directory { + /// Obtains a path relative to the current directory. + /// + /// 現在のディレクトリとの相対パスを取得します。 + String difference(Directory? other) { + if (other == null) { + return path; + } + if (other.path.length < path.length) { + final relative = path.replaceAll(other.path, "").trimStringLeft("/"); + return ("../" * relative.split("/").length).trimString("/"); + } else if (other.path.length > path.length) { + return other.path.replaceAll(path, "").trimStringLeft("/"); + } else { + return ""; + } + } +} + /// Extended methods to make [Process] easier to use. /// /// [Process]を使いやすくするための拡張メソッド。