oto/apps/runner/lib/cli/commands/install/regist_path.dart
toki 86afabb3eb refactor(runner): 런타임 패키지를 앱 하위로 이동한다
독립 control plane 구성을 위해 기존 Dart CLI/runtime을 runner 앱 경계로 옮기고, 후속 client/core/root 작업을 같은 마일스톤 task group에 연결한다.
2026-06-05 06:34:45 +09:00

173 lines
4.7 KiB
Dart

import 'dart:io';
import 'package:dart_framework/utils/system_util.dart';
import '../../../oto/core/system_runtime.dart';
class RegistPath {
final SystemRuntime runtime;
RegistPath([this.runtime = const DefaultSystemRuntime()]);
static RegistPath? _instance;
// ignore: library_private_types_in_public_api, non_constant_identifier_names
static RegistPath? get OS {
if (_instance == null) {
const defaultRuntime = DefaultSystemRuntime();
if (defaultRuntime.isMacOS) {
_instance = _RegistPathOSX(defaultRuntime);
} else if (defaultRuntime.isLinux) {
_instance = _RegistPathLinux(defaultRuntime);
} else {
_instance = _RegistPathWindows(defaultRuntime);
}
}
return _instance;
}
factory RegistPath.create(
{SystemRuntime runtime = const DefaultSystemRuntime()}) {
if (runtime.isMacOS) {
return _RegistPathOSX(runtime);
} else if (runtime.isLinux) {
return _RegistPathLinux(runtime);
} else {
return _RegistPathWindows(runtime);
}
}
Future add(String path) async {
return await _instance?.add(path);
}
Future remove(String path) async {
return await _instance?.remove(path);
}
}
/// ************* MAC ***************
class _RegistPathOSX extends RegistPath {
_RegistPathOSX(super.runtime);
String getTargetPath(String targetPath) {
return 'export PATH=\${PATH}:$targetPath';
}
String get zprofile {
var userPath = runtime.environment['HOME'];
return '$userPath/.zprofile';
}
String get bprofile {
var userPath = runtime.environment['HOME'];
return '$userPath/.bash_profile';
}
@override
Future add(String path) async {
await addProfile(zprofile, path);
await addProfile(bprofile, path);
await runtime
.runShell(StringBuffer('source $zprofile && source $bprofile'));
return simpleFuture;
}
Future addProfile(String profilePath, String targetPath) async {
var file = File(profilePath);
var contents = '';
if (file.existsSync()) {
contents = await file.readAsString();
} else {
file.createSync();
}
if (contents.lastIndexOf('\n') != contents.length - 1) {
contents += '\n';
}
var addItem = getTargetPath(targetPath);
if (!contents.contains(addItem)) {
contents += addItem;
}
await file.writeAsString(contents, flush: true);
return simpleFuture;
}
@override
Future remove(String path) async {
await removeProfile(zprofile, path);
await removeProfile(bprofile, path);
await runtime
.runShell(StringBuffer('source $zprofile && source $bprofile'));
return simpleFuture;
}
Future removeProfile(String profilePath, String targetPath) async {
var file = File(profilePath);
var contents = '';
if (file.existsSync()) {
contents = await file.readAsString();
var removeItem = getTargetPath(targetPath);
if (contents.contains(removeItem)) {
contents = contents.replaceAll(removeItem, '');
await file.writeAsString(contents, flush: true);
}
}
return simpleFuture;
}
}
/// ************* LINUX ***************
class _RegistPathLinux extends RegistPath {
_RegistPathLinux(super.runtime);
@override
Future add(String path) async {
return null;
}
@override
Future remove(String path) async {
return null;
}
}
/// ************* WINDOWS ***************
class _RegistPathWindows extends RegistPath {
_RegistPathWindows(super.runtime);
var setUserPath = '''
@echo off
set "PathUser="
for /F "skip=2 tokens=1,2*" %%G in ('%SystemRoot%\\System32\\reg.exe query "HKCU\\Environment" /v "Path" 2^>nul') do if /I "%%G" == "Path" (
if /I "%%H" == "REG_EXPAND_SZ" (set "PathExpand=1" & set "PathUser=%%I") else if /I "%%H" == "REG_SZ" set "PathUser=%%I"
)
''';
@override
Future add(String path) async {
var shell = StringBuffer(setUserPath);
shell.writeln('setx path "%PathUser%;$path');
await runtime.runShell(shell);
return simpleFuture;
}
@override
Future remove(String path) async {
var userPath = runtime.environment['UserProfile'];
var pathTxt = File('$userPath/path.txt');
var shell = StringBuffer(setUserPath);
shell.writeln('echo "%PathUser%" > ${pathTxt.path}');
await runtime.runShell(StringBuffer(shell));
await Future.delayed(Duration(seconds: 1));
if (pathTxt.existsSync()) {
var contents = pathTxt.readAsStringSync();
contents = contents.replaceAll(';$path', '');
contents = contents.trimLeft();
contents = contents.trimRight();
print('New User Path =====> $contents');
await runtime.runShell(StringBuffer('setx path "$contents"'));
pathTxt.deleteSync();
}
return simpleFuture;
}
}