Skip to content

Commit 6a3f606

Browse files
committed
project: relocate imported archives into project root
1 parent f503f04 commit 6a3f606

3 files changed

Lines changed: 58 additions & 4 deletions

File tree

app/src/main/java/com/kyhsgeekcode/disassembler/project/ProjectManager.kt

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,17 +214,28 @@ object ProjectManager {
214214
*/
215215
fun import(source: File): ProjectModel {
216216
val dest = appCtx.cacheDir.resolve("project-extract")
217+
dest.deleteRecursively()
217218
extractZip(source, dest)
218219
val infoFile = dest.resolve("project_info.json")
219220
if (!infoFile.isAccessible())
220221
throw NotProjectException(source.absolutePath)
221-
val projectModel = openProject(infoFile.absolutePath)
222-
val projectDir = rootdir.resolve(projectModel.name.toValidFileName())
222+
val extractedProjectModel = openProject(infoFile.absolutePath)
223+
val projectDir = rootdir.resolve(extractedProjectModel.name.toValidFileName())
224+
projectDir.deleteRecursively()
223225
projectDir.mkdirs()
224226
dest.copyRecursively(projectDir)
225227
dest.deleteRecursively()
226-
// FileUtils.moveDirectory(dest, projectDir)
227-
return projectModel
228+
val relocatedProjectModel = relocateImportedProjectModel(extractedProjectModel, projectDir)
229+
val finalInfoFile = importedProjectInfoFile(projectDir)
230+
projectModels.remove(infoFile.absolutePath)
231+
projectPaths.remove(infoFile.absolutePath)
232+
projectModelToPath.remove(extractedProjectModel)
233+
projectModels[finalInfoFile.absolutePath] = relocatedProjectModel
234+
projectPaths.add(finalInfoFile.absolutePath)
235+
projectModelToPath[relocatedProjectModel] = finalInfoFile.absolutePath
236+
currentProject = relocatedProjectModel
237+
save(relocatedProjectModel)
238+
return relocatedProjectModel
228239
// FileUtils.moveDirectory(dest.resolve("baseFolder"), projectDir.resolve("baseFolder"))
229240
// FileUtils.moveDirectory(dest.resolve("sourceFilePath"), projectDir.resolve())
230241
}
@@ -273,6 +284,17 @@ object ProjectManager {
273284
}
274285
}
275286

287+
internal fun importedProjectInfoFile(projectDir: File): File {
288+
return projectDir.resolve("project_info.json")
289+
}
290+
291+
internal fun relocateImportedProjectModel(projectModel: ProjectModel, projectDir: File): ProjectModel {
292+
return projectModel.copy(
293+
generatedFolder = projectDir.resolve("baseFolder").path,
294+
sourceFilePath = projectDir.resolve("sourceFilePath").path
295+
)
296+
}
297+
276298
fun computeProjectRelativePath(projectModel: ProjectModel, path: String): String {
277299
if (path == projectModel.sourceFilePath) {
278300
return ""

app/src/test/java/com/kyhsgeekcode/disassembler/ProjectManagerTest.kt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.kyhsgeekcode.disassembler
22

33
import com.kyhsgeekcode.disassembler.project.computeProjectRelativePath
4+
import com.kyhsgeekcode.disassembler.project.importedProjectInfoFile
5+
import com.kyhsgeekcode.disassembler.project.relocateImportedProjectModel
46
import com.kyhsgeekcode.disassembler.project.models.ProjectSourceDescriptor
57
import com.kyhsgeekcode.disassembler.project.models.ProjectSourceKind
68
import com.kyhsgeekcode.disassembler.project.models.ProjectModel
@@ -93,6 +95,34 @@ class ProjectManagerTest {
9395
)
9496
}
9597

98+
@Test
99+
fun `relocateImportedProjectModel rewrites source and generated paths into project dir`() {
100+
val project = projectModelFor(
101+
sourceName = "temp/sourceFilePath",
102+
sourceDescriptor = ProjectSourceDescriptor(
103+
ProjectSourceKind.CONTENT_URI,
104+
"content://samples/app.apk"
105+
)
106+
).copy(generatedFolder = "temp/baseFolder")
107+
val projectDir = File("imported-project")
108+
109+
val relocated = relocateImportedProjectModel(project, projectDir)
110+
111+
assertEquals(projectDir.resolve("sourceFilePath").path, relocated.sourceFilePath)
112+
assertEquals(projectDir.resolve("baseFolder").path, relocated.generatedFolder)
113+
assertEquals(project.sourceDescriptor, relocated.sourceDescriptor)
114+
}
115+
116+
@Test
117+
fun `importedProjectInfoFile resolves inside project dir`() {
118+
val projectDir = File("imported-project")
119+
120+
assertEquals(
121+
projectDir.resolve("project_info.json"),
122+
importedProjectInfoFile(projectDir)
123+
)
124+
}
125+
96126
private fun projectModelFor(
97127
sourceName: String,
98128
sourceDescriptor: ProjectSourceDescriptor? = null

docs/maintenance/implementation-log.ko.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
| 이슈 `#523` 대용량 Hex 탭 렌더링 완화 | Hex 탭이 매우 큰 파일을 열 때 전체 바이트 배열을 그대로 Compose에 전달하지 않고, 상한이 있는 preview만 렌더링하며 원본 크기 안내 문구를 보여주도록 바꿨다 | 큰 파일을 Hex 화면에 띄우는 순간 UI 레이어가 과도한 메모리와 레이아웃 비용을 쓰는 경로를 줄여서 large-file cluster를 더 좁혔다 | `app/src/main/java/com/kyhsgeekcode/disassembler/ui/components/HexView.kt`, `app/src/main/java/com/kyhsgeekcode/disassembler/ui/tabs/HexTab.kt`, `app/src/test/java/com/kyhsgeekcode/disassembler/ui/components/HexViewLayoutTest.kt` | 완료 |
4040
| 이슈 `#523` 대용량 Text 탭 렌더링 완화 | Text 탭이 매우 큰 파일을 열 때 전체 바이트를 그대로 highlight하지 않고, 상한이 있는 preview만 decode/highlight하며 원본 크기 안내 문구를 보여주도록 바꿨다 | 큰 텍스트/스몰리/XML 파일을 Text 화면에 띄우는 순간 AnnotatedString과 syntax highlighter가 과도한 메모리를 잡는 경로를 줄였다 | `app/src/main/java/com/kyhsgeekcode/disassembler/ui/tabs/TextTab.kt`, `app/src/test/java/com/kyhsgeekcode/disassembler/ui/tabs/TextPreviewTest.kt` | 완료 |
4141
| 이슈 `#95` content URI import 파일 충돌 완화 | content URI를 app-private `imports/` 아래로 복사할 때 같은 display name이 이미 있으면 `_1`, `_2` suffix를 붙인 새 파일로 저장하도록 바꿨다 | 같은 이름의 문서를 여러 번 가져오거나 provider가 동일한 표시 이름을 줄 때 기존 import를 조용히 덮어쓰는 문제를 막아 SAF 기반 import 경계를 더 안전하게 만들었다 | `app/src/main/java/com/kyhsgeekcode/disassembler/viewmodel/MainViewModel.kt`, `app/src/test/java/com/kyhsgeekcode/disassembler/viewmodel/ImportedFileNameTest.kt` | 완료 |
42+
| 이슈 `#95` imported project reopen 경계 정리 | exported project ZIP을 import한 뒤 `sourceFilePath`, `generatedFolder`, `project_info.json` 경로를 새 프로젝트 디렉터리 기준으로 재작성하고, temp extract 경로 매핑을 제거하도록 바꿨다 | SAF나 로컬 파일에서 가져온 project archive를 다시 열었을 때 삭제된 temp extract 경로나 예전 경로를 계속 참조하는 문제를 막아 reopen/open 경계를 실제 프로젝트 위치로 닫았다 | `app/src/main/java/com/kyhsgeekcode/disassembler/project/ProjectManager.kt`, `app/src/test/java/com/kyhsgeekcode/disassembler/ProjectManagerTest.kt` | 완료 |
4243
| 이슈 `#129` `.ar` archive 지원 | 공용 archive extractor를 추가하고, Compose/legacy drawer의 archive 확장 경로를 ZIP 전용 구현에서 generic archive extractor로 교체했다 | archive 판정은 되는데 실제 확장은 ZIP만 되던 불일치를 제거해서 `.ar` 같은 지원 가능한 archive도 실제로 탐색 가능하게 만들었다 | `app/src/main/java/com/kyhsgeekcode/Util.kt`, `app/src/main/java/com/kyhsgeekcode/disassembler/ui/FileDrawerTree.kt`, `app/src/main/java/com/kyhsgeekcode/disassembler/FileDrawerListItem.kt`, `app/src/main/java/com/kyhsgeekcode/disassembler/FileDrawerListAdapter.kt`, `app/src/test/java/com/kyhsgeekcode/disassembler/ArchiveExtractionTest.kt` | 완료 |
4344
| 프로젝트 경로/파일명 회귀 방지 | 프로젝트 상대경로 계산과 import 파일명 정규화를 pure helper로 분리 | 단위 테스트가 가능하도록 로직을 분리하고 경계 케이스를 줄였다 | `app/src/main/java/com/kyhsgeekcode/disassembler/project/ProjectManager.kt`, `app/src/main/java/com/kyhsgeekcode/disassembler/viewmodel/MainViewModel.kt` | 완료 |
4445
| 회귀 테스트 부재 | `ProjectManager`, 저장소 권한, Hex 레이아웃, import 파일명 테스트 추가 | 최소한의 유지보수 안전망을 확보했다 | `app/src/test/java/com/kyhsgeekcode/disassembler/ProjectManagerTest.kt`, `app/src/test/java/com/kyhsgeekcode/disassembler/PermissionUtilsTest.kt`, `app/src/test/java/com/kyhsgeekcode/disassembler/ui/components/HexViewLayoutTest.kt`, `app/src/test/java/com/kyhsgeekcode/disassembler/viewmodel/ImportedFileNameTest.kt` | 완료 |
@@ -67,6 +68,7 @@
6768
| hex preview 테스트 | 통과 | Hex 탭이 큰 파일 바이트 배열을 preview 상한으로 잘라 렌더링하는 규칙을 고정 |
6869
| text preview 테스트 | 통과 | Text 탭이 큰 파일 바이트 배열을 preview 상한으로 잘라 highlight하는 규칙을 고정 |
6970
| import destination 파일명 테스트 | 통과 | 같은 display name으로 여러 번 import해도 app-private 파일이 덮어써지지 않는 규칙을 고정 |
71+
| imported project relocation 테스트 | 통과 | project archive import 후 `sourceFilePath`, `generatedFolder`, `project_info.json` 경로를 새 프로젝트 위치로 다시 맞추는 규칙을 고정 |
7072
| architecture mapping 테스트 | 통과 | `x86_64`, `PPC64`가 64-bit mode로 매핑되는 규칙을 고정 |
7173
| binary manual setup reload 테스트 | 통과 | override autosetup 변경 시 disassembly 재로드 필요 여부를 고정 |
7274
| project export archive 테스트 | 통과 | ZIP 엔트리가 절대경로를 포함하지 않고 `sourceFilePath`, `baseFolder/...`로 묶이는지 확인 |

0 commit comments

Comments
 (0)