freelang-v4 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +548 -0
- package/dist/ast.d.ts +367 -0
- package/dist/ast.js +4 -0
- package/dist/ast.js.map +1 -0
- package/dist/async-basic.test.d.ts +1 -0
- package/dist/async-basic.test.js +88 -0
- package/dist/async-basic.test.js.map +1 -0
- package/dist/async-jest.test.d.ts +1 -0
- package/dist/async-jest.test.js +99 -0
- package/dist/async-jest.test.js.map +1 -0
- package/dist/channel-jest.test.d.ts +1 -0
- package/dist/channel-jest.test.js +148 -0
- package/dist/channel-jest.test.js.map +1 -0
- package/dist/checker-jest.test.d.ts +1 -0
- package/dist/checker-jest.test.js +160 -0
- package/dist/checker-jest.test.js.map +1 -0
- package/dist/checker.d.ts +149 -0
- package/dist/checker.js +1565 -0
- package/dist/checker.js.map +1 -0
- package/dist/checker.test.d.ts +1 -0
- package/dist/checker.test.js +217 -0
- package/dist/checker.test.js.map +1 -0
- package/dist/compiler-jest.test.d.ts +1 -0
- package/dist/compiler-jest.test.js +233 -0
- package/dist/compiler-jest.test.js.map +1 -0
- package/dist/compiler.d.ts +127 -0
- package/dist/compiler.js +1588 -0
- package/dist/compiler.js.map +1 -0
- package/dist/compiler.test.d.ts +1 -0
- package/dist/compiler.test.js +313 -0
- package/dist/compiler.test.js.map +1 -0
- package/dist/db-100m-full.d.ts +5 -0
- package/dist/db-100m-full.js +78 -0
- package/dist/db-100m-full.js.map +1 -0
- package/dist/db-100m-no-index.d.ts +12 -0
- package/dist/db-100m-no-index.js +119 -0
- package/dist/db-100m-no-index.js.map +1 -0
- package/dist/db-100m-real.d.ts +5 -0
- package/dist/db-100m-real.js +131 -0
- package/dist/db-100m-real.js.map +1 -0
- package/dist/db-100m-streaming.d.ts +15 -0
- package/dist/db-100m-streaming.js +164 -0
- package/dist/db-100m-streaming.js.map +1 -0
- package/dist/db-100m-test.d.ts +5 -0
- package/dist/db-100m-test.js +111 -0
- package/dist/db-100m-test.js.map +1 -0
- package/dist/db-jest.test.d.ts +1 -0
- package/dist/db-jest.test.js +182 -0
- package/dist/db-jest.test.js.map +1 -0
- package/dist/db-runtime.d.ts +24 -0
- package/dist/db-runtime.js +204 -0
- package/dist/db-runtime.js.map +1 -0
- package/dist/db.d.ts +249 -0
- package/dist/db.js +593 -0
- package/dist/db.js.map +1 -0
- package/dist/file-io-jest.test.d.ts +1 -0
- package/dist/file-io-jest.test.js +225 -0
- package/dist/file-io-jest.test.js.map +1 -0
- package/dist/for-of-jest.test.d.ts +1 -0
- package/dist/for-of-jest.test.js +230 -0
- package/dist/for-of-jest.test.js.map +1 -0
- package/dist/for-of.test.d.ts +1 -0
- package/dist/for-of.test.js +305 -0
- package/dist/for-of.test.js.map +1 -0
- package/dist/function-literal-jest.test.d.ts +1 -0
- package/dist/function-literal-jest.test.js +180 -0
- package/dist/function-literal-jest.test.js.map +1 -0
- package/dist/function-literal.test.d.ts +1 -0
- package/dist/function-literal.test.js +245 -0
- package/dist/function-literal.test.js.map +1 -0
- package/dist/generics-jest.test.d.ts +1 -0
- package/dist/generics-jest.test.js +93 -0
- package/dist/generics-jest.test.js.map +1 -0
- package/dist/ir-gen.d.ts +15 -0
- package/dist/ir-gen.js +400 -0
- package/dist/ir-gen.js.map +1 -0
- package/dist/ir.d.ts +114 -0
- package/dist/ir.js +5 -0
- package/dist/ir.js.map +1 -0
- package/dist/lexer.d.ts +110 -0
- package/dist/lexer.js +467 -0
- package/dist/lexer.js.map +1 -0
- package/dist/lexer.test.d.ts +1 -0
- package/dist/lexer.test.js +426 -0
- package/dist/lexer.test.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +241 -0
- package/dist/main.js.map +1 -0
- package/dist/module-jest.test.d.ts +1 -0
- package/dist/module-jest.test.js +123 -0
- package/dist/module-jest.test.js.map +1 -0
- package/dist/parser.d.ts +56 -0
- package/dist/parser.js +1060 -0
- package/dist/parser.js.map +1 -0
- package/dist/parser.test.d.ts +1 -0
- package/dist/parser.test.js +461 -0
- package/dist/parser.test.js.map +1 -0
- package/dist/pattern-matching-jest.test.d.ts +1 -0
- package/dist/pattern-matching-jest.test.js +158 -0
- package/dist/pattern-matching-jest.test.js.map +1 -0
- package/dist/pkg/init.d.ts +1 -0
- package/dist/pkg/init.js +118 -0
- package/dist/pkg/init.js.map +1 -0
- package/dist/pkg/install.d.ts +1 -0
- package/dist/pkg/install.js +77 -0
- package/dist/pkg/install.js.map +1 -0
- package/dist/pkg/registry.d.ts +23 -0
- package/dist/pkg/registry.js +106 -0
- package/dist/pkg/registry.js.map +1 -0
- package/dist/pkg/run.d.ts +1 -0
- package/dist/pkg/run.js +76 -0
- package/dist/pkg/run.js.map +1 -0
- package/dist/pkg/toml.d.ts +5 -0
- package/dist/pkg/toml.js +117 -0
- package/dist/pkg/toml.js.map +1 -0
- package/dist/repl.d.ts +15 -0
- package/dist/repl.js +197 -0
- package/dist/repl.js.map +1 -0
- package/dist/runtime/bytecode.d.ts +92 -0
- package/dist/runtime/bytecode.js +253 -0
- package/dist/runtime/bytecode.js.map +1 -0
- package/dist/runtime/value.d.ts +102 -0
- package/dist/runtime/value.js +302 -0
- package/dist/runtime/value.js.map +1 -0
- package/dist/runtime/vm.d.ts +65 -0
- package/dist/runtime/vm.js +293 -0
- package/dist/runtime/vm.js.map +1 -0
- package/dist/struct-instance-jest.test.d.ts +1 -0
- package/dist/struct-instance-jest.test.js +209 -0
- package/dist/struct-instance-jest.test.js.map +1 -0
- package/dist/struct-instance.test.d.ts +1 -0
- package/dist/struct-instance.test.js +291 -0
- package/dist/struct-instance.test.js.map +1 -0
- package/dist/struct-jest.test.d.ts +1 -0
- package/dist/struct-jest.test.js +176 -0
- package/dist/struct-jest.test.js.map +1 -0
- package/dist/struct.test.d.ts +1 -0
- package/dist/struct.test.js +231 -0
- package/dist/struct.test.js.map +1 -0
- package/dist/trait-jest.test.d.ts +1 -0
- package/dist/trait-jest.test.js +120 -0
- package/dist/trait-jest.test.js.map +1 -0
- package/dist/vm-jest.test.d.ts +1 -0
- package/dist/vm-jest.test.js +569 -0
- package/dist/vm-jest.test.js.map +1 -0
- package/dist/vm.d.ts +81 -0
- package/dist/vm.js +1956 -0
- package/dist/vm.js.map +1 -0
- package/dist/vm.test.d.ts +1 -0
- package/dist/vm.test.js +337 -0
- package/dist/vm.test.js.map +1 -0
- package/dist/web-repl/sandbox.d.ts +11 -0
- package/dist/web-repl/sandbox.js +76 -0
- package/dist/web-repl/sandbox.js.map +1 -0
- package/dist/web-repl/server.d.ts +1 -0
- package/dist/web-repl/server.js +111 -0
- package/dist/web-repl/server.js.map +1 -0
- package/dist/while-loop-jest.test.d.ts +1 -0
- package/dist/while-loop-jest.test.js +201 -0
- package/dist/while-loop-jest.test.js.map +1 -0
- package/dist/while-loop.test.d.ts +1 -0
- package/dist/while-loop.test.js +262 -0
- package/dist/while-loop.test.js.map +1 -0
- package/docs/EXPERIENCE.md +787 -0
- package/docs/README.md +175 -0
- package/docs/V1_V2_V3_ANALYSIS.md +107 -0
- package/docs/_config.yml +36 -0
- package/docs/api-reference.md +459 -0
- package/docs/architecture.md +470 -0
- package/docs/benchmarks.md +295 -0
- package/docs/comparison.md +454 -0
- package/docs/index.md +335 -0
- package/docs/language-completeness.md +228 -0
- package/docs/learning-guide.md +651 -0
- package/package.json +65 -0
- package/src/api/deploy_key.fl +294 -0
- package/src/api/issue.fl +302 -0
- package/src/api/org.fl +356 -0
- package/src/api/repo.fl +394 -0
- package/src/api/team.fl +299 -0
- package/src/api/user.fl +385 -0
- package/src/api/webhook.fl +273 -0
- package/src/ast.ts +158 -0
- package/src/async-basic.test.ts +94 -0
- package/src/async-jest.test.ts +107 -0
- package/src/channel-jest.test.ts +158 -0
- package/src/checker-jest.test.ts +189 -0
- package/src/checker.test.ts +279 -0
- package/src/checker.ts +1861 -0
- package/src/commands/analyze.fl +227 -0
- package/src/commands/auth.fl +315 -0
- package/src/commands/batch.fl +349 -0
- package/src/commands/config.fl +199 -0
- package/src/commands/deploy_key.fl +352 -0
- package/src/commands/issue.fl +275 -0
- package/src/commands/main.fl +492 -0
- package/src/commands/org.fl +425 -0
- package/src/commands/repo.fl +581 -0
- package/src/commands/team.fl +244 -0
- package/src/commands/user.fl +423 -0
- package/src/commands/webhook.fl +400 -0
- package/src/compiler-jest.test.ts +275 -0
- package/src/compiler.test.ts +375 -0
- package/src/compiler.ts +1770 -0
- package/src/config.fl +175 -0
- package/src/core/batch.fl +355 -0
- package/src/core/cache.fl +284 -0
- package/src/core/ensure.fl +324 -0
- package/src/db-100m-full.ts +96 -0
- package/src/db-100m-no-index.ts +133 -0
- package/src/db-100m-real.ts +152 -0
- package/src/db-100m-streaming.ts +154 -0
- package/src/db-100m-test.ts +136 -0
- package/src/db-jest.test.ts +161 -0
- package/src/db-runtime.ts +242 -0
- package/src/db.ts +676 -0
- package/src/errors.fl +134 -0
- package/src/for-of-jest.test.ts +246 -0
- package/src/for-of.test.ts +308 -0
- package/src/function-literal-jest.test.ts +193 -0
- package/src/function-literal.test.ts +248 -0
- package/src/generics-jest.test.ts +104 -0
- package/src/http/client.fl +327 -0
- package/src/ir-gen.ts +459 -0
- package/src/ir.ts +80 -0
- package/src/lexer.test.ts +499 -0
- package/src/lexer.ts +522 -0
- package/src/main.ts +223 -0
- package/src/models.fl +162 -0
- package/src/module-jest.test.ts +145 -0
- package/src/parser.test.ts +542 -0
- package/src/parser.ts +1211 -0
- package/src/pattern-matching-jest.test.ts +170 -0
- package/src/pkg/init.ts +91 -0
- package/src/pkg/install.ts +56 -0
- package/src/pkg/registry.ts +103 -0
- package/src/pkg/run.ts +49 -0
- package/src/pkg/toml.ts +129 -0
- package/src/repl.ts +190 -0
- package/src/runtime/bytecode.ts +291 -0
- package/src/runtime/value.ts +322 -0
- package/src/runtime/vm.ts +354 -0
- package/src/self-host/bootstrap.fl +68 -0
- package/src/self-host/interpreter.fl +361 -0
- package/src/self-host/lexer-simple.fl +22 -0
- package/src/self-host/lexer.fl +305 -0
- package/src/self-host/parser.fl +580 -0
- package/src/struct-instance-jest.test.ts +221 -0
- package/src/struct-instance.test.ts +293 -0
- package/src/struct-jest.test.ts +187 -0
- package/src/struct.test.ts +234 -0
- package/src/trait-jest.test.ts +136 -0
- package/src/vm-jest.test.ts +754 -0
- package/src/vm.ts +1976 -0
- package/src/web-repl/public/index.html +50 -0
- package/src/web-repl/public/main.js +105 -0
- package/src/web-repl/public/style.css +225 -0
- package/src/web-repl/sandbox.ts +88 -0
- package/src/web-repl/server.ts +97 -0
- package/src/while-loop-jest.test.ts +218 -0
- package/src/while-loop.test.ts +267 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
// FreeLang v4.2 — gogs-cli Phase 5 배치 명령어
|
|
2
|
+
// create, ensure, delete 구현 (병렬 처리)
|
|
3
|
+
// 300라인
|
|
4
|
+
|
|
5
|
+
/// 배치 생성
|
|
6
|
+
/// gogs batch create REPOS_FILE.yaml [--parallel 10] [--skip-existing]
|
|
7
|
+
async fn cmd_batch_create(args: CliArgs) -> CliResult {
|
|
8
|
+
// 1. 인자 검증
|
|
9
|
+
var file_path = get_positional(args, 0)
|
|
10
|
+
if file_path == "" {
|
|
11
|
+
return CliResult {
|
|
12
|
+
exit_code: 1,
|
|
13
|
+
output: "",
|
|
14
|
+
error: "Repository file (YAML) is required"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// 2. 플래그 파싱
|
|
19
|
+
var parallel_str = get_flag(args, "parallel")
|
|
20
|
+
var parallel = if parallel_str != "" then parse_int(parallel_str) else 5
|
|
21
|
+
var skip_existing = has_flag(args, "skip-existing")
|
|
22
|
+
|
|
23
|
+
// 3. 설정 로드
|
|
24
|
+
var host = await get_default_host()
|
|
25
|
+
if host.url == "" {
|
|
26
|
+
return CliResult {
|
|
27
|
+
exit_code: 1,
|
|
28
|
+
output: "",
|
|
29
|
+
error: "Not logged in"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// 4. 파일 읽기
|
|
34
|
+
println("Reading repository file: " + file_path)
|
|
35
|
+
|
|
36
|
+
// TODO: read_file, parse_yaml 구현
|
|
37
|
+
// var content = read_file(file_path)
|
|
38
|
+
// var repos = parse_yaml(content)
|
|
39
|
+
|
|
40
|
+
// 5. 클라이언트 및 캐시
|
|
41
|
+
var client = new_client(host.url, host.token)
|
|
42
|
+
var cache = new_cache(300)
|
|
43
|
+
|
|
44
|
+
// 6. 배치 생성 (병렬)
|
|
45
|
+
println("Creating repositories (parallel: " + str(parallel) + ")...")
|
|
46
|
+
|
|
47
|
+
var repo_service = new_repo_service(client, cache)
|
|
48
|
+
|
|
49
|
+
// TODO: 배열 처리 및 병렬 실행
|
|
50
|
+
// var results = await batch_create_repos(repo_service, repos, parallel)
|
|
51
|
+
|
|
52
|
+
var output = ""
|
|
53
|
+
output = output + "✓ Batch create completed\n"
|
|
54
|
+
output = output + " Created: 0\n"
|
|
55
|
+
output = output + " Failed: 0\n"
|
|
56
|
+
output = output + " Skipped: 0\n"
|
|
57
|
+
|
|
58
|
+
CliResult {
|
|
59
|
+
exit_code: 0,
|
|
60
|
+
output: output,
|
|
61
|
+
error: ""
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/// 배치 동기화 (멱등성)
|
|
66
|
+
/// gogs batch ensure DESIRED.yaml [--parallel 20]
|
|
67
|
+
async fn cmd_batch_ensure(args: CliArgs) -> CliResult {
|
|
68
|
+
// 1. 인자 검증
|
|
69
|
+
var file_path = get_positional(args, 0)
|
|
70
|
+
if file_path == "" {
|
|
71
|
+
return CliResult {
|
|
72
|
+
exit_code: 1,
|
|
73
|
+
output: "",
|
|
74
|
+
error: "Repository file (YAML) is required"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// 2. 플래그 파싱
|
|
79
|
+
var parallel_str = get_flag(args, "parallel")
|
|
80
|
+
var parallel = if parallel_str != "" then parse_int(parallel_str) else 10
|
|
81
|
+
|
|
82
|
+
// 3. 설정 로드
|
|
83
|
+
var host = await get_default_host()
|
|
84
|
+
if host.url == "" {
|
|
85
|
+
return CliResult {
|
|
86
|
+
exit_code: 1,
|
|
87
|
+
output: "",
|
|
88
|
+
error: "Not logged in"
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// 4. 파일 읽기
|
|
93
|
+
println("Reading desired state: " + file_path)
|
|
94
|
+
|
|
95
|
+
// TODO: read_file, parse_yaml 구현
|
|
96
|
+
// var content = read_file(file_path)
|
|
97
|
+
// var desired_repos = parse_yaml(content)
|
|
98
|
+
|
|
99
|
+
// 5. 클라이언트 및 캐시
|
|
100
|
+
var client = new_client(host.url, host.token)
|
|
101
|
+
var cache = new_cache(300)
|
|
102
|
+
|
|
103
|
+
// 6. 현재 저장소 조회
|
|
104
|
+
println("Fetching current repositories...")
|
|
105
|
+
// var repo_service = new_repo_service(client, cache)
|
|
106
|
+
// var current_repos = await list_repos(repo_service)
|
|
107
|
+
|
|
108
|
+
// 7. 차이 계산 및 적용 (병렬)
|
|
109
|
+
println("Syncing repositories (parallel: " + str(parallel) + ")...")
|
|
110
|
+
|
|
111
|
+
var output = ""
|
|
112
|
+
output = output + "✓ Batch ensure completed\n"
|
|
113
|
+
output = output + " Created: 0\n"
|
|
114
|
+
output = output + " Updated: 0\n"
|
|
115
|
+
output = output + " Deleted: 0\n"
|
|
116
|
+
output = output + " Unchanged: 0\n"
|
|
117
|
+
|
|
118
|
+
CliResult {
|
|
119
|
+
exit_code: 0,
|
|
120
|
+
output: output,
|
|
121
|
+
error: ""
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/// 배치 삭제
|
|
126
|
+
/// gogs batch delete REPOS.yaml [--parallel 10] [--force]
|
|
127
|
+
async fn cmd_batch_delete(args: CliArgs) -> CliResult {
|
|
128
|
+
// 1. 인자 검증
|
|
129
|
+
var file_path = get_positional(args, 0)
|
|
130
|
+
if file_path == "" {
|
|
131
|
+
return CliResult {
|
|
132
|
+
exit_code: 1,
|
|
133
|
+
output: "",
|
|
134
|
+
error: "Repository file (YAML) is required"
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// 2. 플래그 파싱
|
|
139
|
+
var parallel_str = get_flag(args, "parallel")
|
|
140
|
+
var parallel = if parallel_str != "" then parse_int(parallel_str) else 5
|
|
141
|
+
var force = has_flag(args, "force")
|
|
142
|
+
|
|
143
|
+
if !force {
|
|
144
|
+
println("⚠️ This will delete all repositories in " + file_path)
|
|
145
|
+
println("Run with --force to confirm")
|
|
146
|
+
return CliResult {
|
|
147
|
+
exit_code: 1,
|
|
148
|
+
output: "",
|
|
149
|
+
error: "Deletion not confirmed"
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// 3. 설정 로드
|
|
154
|
+
var host = await get_default_host()
|
|
155
|
+
if host.url == "" {
|
|
156
|
+
return CliResult {
|
|
157
|
+
exit_code: 1,
|
|
158
|
+
output: "",
|
|
159
|
+
error: "Not logged in"
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// 4. 파일 읽기
|
|
164
|
+
println("Reading repository file: " + file_path)
|
|
165
|
+
|
|
166
|
+
// TODO: read_file, parse_yaml 구현
|
|
167
|
+
// var content = read_file(file_path)
|
|
168
|
+
// var repos = parse_yaml(content)
|
|
169
|
+
|
|
170
|
+
// 5. 클라이언트 및 캐시
|
|
171
|
+
var client = new_client(host.url, host.token)
|
|
172
|
+
var cache = new_cache(300)
|
|
173
|
+
|
|
174
|
+
// 6. 배치 삭제 (병렬)
|
|
175
|
+
println("Deleting repositories (parallel: " + str(parallel) + ")...")
|
|
176
|
+
|
|
177
|
+
var repo_service = new_repo_service(client, cache)
|
|
178
|
+
|
|
179
|
+
// TODO: 배열 처리 및 병렬 실행
|
|
180
|
+
// var results = await batch_delete_repos(repo_service, repos, parallel)
|
|
181
|
+
|
|
182
|
+
var output = ""
|
|
183
|
+
output = output + "✓ Batch delete completed\n"
|
|
184
|
+
output = output + " Deleted: 0\n"
|
|
185
|
+
output = output + " Failed: 0\n"
|
|
186
|
+
|
|
187
|
+
CliResult {
|
|
188
|
+
exit_code: 0,
|
|
189
|
+
output: output,
|
|
190
|
+
error: ""
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ==================== 배치 처리 유틸리티 ====================
|
|
195
|
+
|
|
196
|
+
/// 배치 결과 구조
|
|
197
|
+
struct BatchResult {
|
|
198
|
+
total: i32
|
|
199
|
+
success: i32
|
|
200
|
+
failed: i32
|
|
201
|
+
errors: [str]
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/// 배치 진행 상황 출력
|
|
205
|
+
fn print_batch_progress(current: i32, total: i32, message: str) {
|
|
206
|
+
var percent = (current * 100) / total
|
|
207
|
+
println("[" + str(percent) + "%] " + message)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/// 배치 작업 결과 요약
|
|
211
|
+
fn print_batch_summary(result: BatchResult) {
|
|
212
|
+
println("✓ Batch operation completed")
|
|
213
|
+
println(" Total: " + str(result.total))
|
|
214
|
+
println(" Success: " + str(result.success))
|
|
215
|
+
println(" Failed: " + str(result.failed))
|
|
216
|
+
|
|
217
|
+
if result.failed > 0 {
|
|
218
|
+
println("\nErrors:")
|
|
219
|
+
var i: i32 = 0
|
|
220
|
+
while i < length(result.errors) && i < 10 {
|
|
221
|
+
println(" - " + result.errors[i])
|
|
222
|
+
i = i + 1
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if length(result.errors) > 10 {
|
|
226
|
+
println(" ... and " + str(length(result.errors) - 10) + " more")
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// ==================== 배치 처리 패턴 ====================
|
|
232
|
+
|
|
233
|
+
/// 저장소 배열에 대한 배치 생성
|
|
234
|
+
async fn batch_create_repos(
|
|
235
|
+
service: RepoService,
|
|
236
|
+
repos: [CreateRepoRequest],
|
|
237
|
+
parallel: i32
|
|
238
|
+
) -> BatchResult {
|
|
239
|
+
var result = BatchResult {
|
|
240
|
+
total: length(repos),
|
|
241
|
+
success: 0,
|
|
242
|
+
failed: 0,
|
|
243
|
+
errors: []
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// TODO: 병렬 실행 구현
|
|
247
|
+
// 현재: 순차 실행
|
|
248
|
+
|
|
249
|
+
var i: i32 = 0
|
|
250
|
+
while i < length(repos) {
|
|
251
|
+
var req = repos[i]
|
|
252
|
+
var repo_result = await create_repo(service, req)
|
|
253
|
+
|
|
254
|
+
match repo_result {
|
|
255
|
+
Result::Ok(_) => {
|
|
256
|
+
result.success = result.success + 1
|
|
257
|
+
}
|
|
258
|
+
Result::Err(err) => {
|
|
259
|
+
result.failed = result.failed + 1
|
|
260
|
+
result.errors.push(error_message(err))
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
print_batch_progress(i + 1, result.total, "Creating " + req.name)
|
|
265
|
+
i = i + 1
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
result
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/// 저장소 배열에 대한 배치 삭제
|
|
272
|
+
async fn batch_delete_repos(
|
|
273
|
+
service: RepoService,
|
|
274
|
+
repo_paths: [str],
|
|
275
|
+
parallel: i32
|
|
276
|
+
) -> BatchResult {
|
|
277
|
+
var result = BatchResult {
|
|
278
|
+
total: length(repo_paths),
|
|
279
|
+
success: 0,
|
|
280
|
+
failed: 0,
|
|
281
|
+
errors: []
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// TODO: 병렬 실행 구현
|
|
285
|
+
|
|
286
|
+
var i: i32 = 0
|
|
287
|
+
while i < length(repo_paths) {
|
|
288
|
+
var path = repo_paths[i]
|
|
289
|
+
var parts = split_repo_path(path)
|
|
290
|
+
|
|
291
|
+
if length(parts) >= 2 {
|
|
292
|
+
var owner = parts[0]
|
|
293
|
+
var repo_name = parts[1]
|
|
294
|
+
|
|
295
|
+
var del_result = await delete_repo(service, owner, repo_name)
|
|
296
|
+
|
|
297
|
+
match del_result {
|
|
298
|
+
Result::Ok(_) => {
|
|
299
|
+
result.success = result.success + 1
|
|
300
|
+
}
|
|
301
|
+
Result::Err(err) => {
|
|
302
|
+
result.failed = result.failed + 1
|
|
303
|
+
result.errors.push(error_message(err))
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
print_batch_progress(i + 1, result.total, "Deleting " + path)
|
|
309
|
+
i = i + 1
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
result
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// ==================== 유틸리티 ====================
|
|
316
|
+
|
|
317
|
+
fn split_repo_path(path: str) -> [str] {
|
|
318
|
+
var result: [str] = []
|
|
319
|
+
var idx = indexOf(path, "/")
|
|
320
|
+
if idx == -1 {
|
|
321
|
+
result.push(path)
|
|
322
|
+
return result
|
|
323
|
+
}
|
|
324
|
+
result.push(substring(path, 0, idx))
|
|
325
|
+
result.push(substring(path, idx + 1, length(path)))
|
|
326
|
+
result
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
fn indexOf(s: str, substr: str) -> i32 {
|
|
330
|
+
var i: i32 = 0
|
|
331
|
+
var len = length(s)
|
|
332
|
+
var sublen = length(substr)
|
|
333
|
+
while i <= len - sublen {
|
|
334
|
+
if substring(s, i, i + sublen) == substr { return i }
|
|
335
|
+
i = i + 1
|
|
336
|
+
}
|
|
337
|
+
-1
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
fn parse_int(s: str) -> i32 {
|
|
341
|
+
0 // TODO: implement parse_int
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// 필요한 함수들:
|
|
345
|
+
// - get_positional, has_flag, get_flag
|
|
346
|
+
// - get_default_host, new_client, new_cache
|
|
347
|
+
// - new_repo_service, create_repo, delete_repo, list_repos
|
|
348
|
+
// - read_file, parse_yaml
|
|
349
|
+
// - error_message
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
// FreeLang v4.2 — gogs-cli Phase 5 설정 명령어
|
|
2
|
+
// set, get 구현
|
|
3
|
+
// 150라인
|
|
4
|
+
|
|
5
|
+
/// 설정 저장
|
|
6
|
+
/// gogs config set KEY VALUE
|
|
7
|
+
async fn cmd_config_set(args: CliArgs) -> CliResult {
|
|
8
|
+
// 1. 인자 검증
|
|
9
|
+
var key = get_positional(args, 0)
|
|
10
|
+
var value = get_positional(args, 1)
|
|
11
|
+
|
|
12
|
+
if key == "" {
|
|
13
|
+
return CliResult {
|
|
14
|
+
exit_code: 1,
|
|
15
|
+
output: "",
|
|
16
|
+
error: "Key is required"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if value == "" {
|
|
21
|
+
return CliResult {
|
|
22
|
+
exit_code: 1,
|
|
23
|
+
output: "",
|
|
24
|
+
error: "Value is required"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// 2. 설정 로드
|
|
29
|
+
var cfg = await load_config()
|
|
30
|
+
|
|
31
|
+
// 3. 설정 값 저장 (확장 필드)
|
|
32
|
+
// TODO: Config 구조에 사용자 정의 필드 지원 필요
|
|
33
|
+
// cfg.settings[key] = value
|
|
34
|
+
|
|
35
|
+
// 4. 설정 저장
|
|
36
|
+
var saved = await save_config(cfg)
|
|
37
|
+
|
|
38
|
+
if saved {
|
|
39
|
+
CliResult {
|
|
40
|
+
exit_code: 0,
|
|
41
|
+
output: "✓ Configuration saved: " + key + " = " + value,
|
|
42
|
+
error: ""
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
CliResult {
|
|
46
|
+
exit_code: 1,
|
|
47
|
+
output: "",
|
|
48
|
+
error: "Failed to save configuration"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// 설정 조회
|
|
54
|
+
/// gogs config get KEY
|
|
55
|
+
async fn cmd_config_get(args: CliArgs) -> CliResult {
|
|
56
|
+
// 1. 인자 검증
|
|
57
|
+
var key = get_positional(args, 0)
|
|
58
|
+
|
|
59
|
+
if key == "" {
|
|
60
|
+
return CliResult {
|
|
61
|
+
exit_code: 1,
|
|
62
|
+
output: "",
|
|
63
|
+
error: "Key is required"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 2. 설정 로드
|
|
68
|
+
var cfg = await load_config()
|
|
69
|
+
|
|
70
|
+
// 3. 값 조회
|
|
71
|
+
// TODO: Config 구조에 사용자 정의 필드 지원 필요
|
|
72
|
+
// var value = cfg.settings[key]
|
|
73
|
+
|
|
74
|
+
var value = "" // placeholder
|
|
75
|
+
|
|
76
|
+
if value == "" {
|
|
77
|
+
return CliResult {
|
|
78
|
+
exit_code: 1,
|
|
79
|
+
output: "",
|
|
80
|
+
error: "Configuration key not found: " + key
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
CliResult {
|
|
85
|
+
exit_code: 0,
|
|
86
|
+
output: value,
|
|
87
|
+
error: ""
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ==================== 기본 설정 값 ====================
|
|
92
|
+
|
|
93
|
+
/// 기본 설정
|
|
94
|
+
struct ConfigSettings {
|
|
95
|
+
editor: str // 기본 에디터 (vim, nano, etc.)
|
|
96
|
+
output_format: str // 기본 출력 포맷 (text, json, yaml)
|
|
97
|
+
auto_confirm: bool // 자동 확인 (위험한 작업)
|
|
98
|
+
color_output: bool // 색상 출력
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/// 기본 설정 값
|
|
102
|
+
fn default_settings() -> ConfigSettings {
|
|
103
|
+
ConfigSettings {
|
|
104
|
+
editor: "vim",
|
|
105
|
+
output_format: "text",
|
|
106
|
+
auto_confirm: false,
|
|
107
|
+
color_output: true
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// ==================== 설정 관리 ====================
|
|
112
|
+
|
|
113
|
+
/// 설정 파일 존재 확인
|
|
114
|
+
async fn config_exists() -> bool {
|
|
115
|
+
// TODO: file system 확인 필요
|
|
116
|
+
false // placeholder
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/// 기본 설정 파일 생성
|
|
120
|
+
async fn init_config() -> bool {
|
|
121
|
+
var cfg = Config {
|
|
122
|
+
default_host: "",
|
|
123
|
+
hosts: []
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
var saved = await save_config(cfg)
|
|
127
|
+
saved
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/// 모든 설정 보기
|
|
131
|
+
async fn show_all_config() -> CliResult {
|
|
132
|
+
var cfg = await load_config()
|
|
133
|
+
|
|
134
|
+
var output = ""
|
|
135
|
+
output = output + "╔════════════════════════════════════════╗\n"
|
|
136
|
+
output = output + "║ Configuration ║\n"
|
|
137
|
+
output = output + "╚════════════════════════════════════════╝\n"
|
|
138
|
+
output = output + "\n"
|
|
139
|
+
|
|
140
|
+
output = output + "Default Host: " + cfg.default_host + "\n"
|
|
141
|
+
output = output + "Hosts: " + str(length(cfg.hosts)) + "\n"
|
|
142
|
+
|
|
143
|
+
var i: i32 = 0
|
|
144
|
+
while i < length(cfg.hosts) {
|
|
145
|
+
var host = cfg.hosts[i]
|
|
146
|
+
output = output + " - " + host.name + ": " + host.url + "\n"
|
|
147
|
+
i = i + 1
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
output = output + "\n"
|
|
151
|
+
|
|
152
|
+
CliResult {
|
|
153
|
+
exit_code: 0,
|
|
154
|
+
output: output,
|
|
155
|
+
error: ""
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/// 설정 유효성 검증
|
|
160
|
+
fn validate_config(cfg: Config) -> bool {
|
|
161
|
+
if cfg.default_host == "" {
|
|
162
|
+
return false
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
var i: i32 = 0
|
|
166
|
+
while i < length(cfg.hosts) {
|
|
167
|
+
var host = cfg.hosts[i]
|
|
168
|
+
if host.name == "" || host.url == "" || host.token == "" {
|
|
169
|
+
return false
|
|
170
|
+
}
|
|
171
|
+
i = i + 1
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
true
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ==================== 환경 변수 지원 ====================
|
|
178
|
+
|
|
179
|
+
/// 환경 변수에서 설정 로드
|
|
180
|
+
fn load_from_env() -> Config {
|
|
181
|
+
// TODO: 환경 변수 읽기 구현
|
|
182
|
+
// GOGS_HOST, GOGS_TOKEN, GOGS_URL 등
|
|
183
|
+
|
|
184
|
+
Config {
|
|
185
|
+
default_host: "",
|
|
186
|
+
hosts: []
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/// 환경 변수 확인
|
|
191
|
+
fn has_env_config() -> bool {
|
|
192
|
+
// TODO: 환경 변수 확인 구현
|
|
193
|
+
false
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// 필요한 함수들:
|
|
197
|
+
// - get_positional
|
|
198
|
+
// - load_config, save_config
|
|
199
|
+
// - error_message
|