머신 상태
Dojang은 저장소별 중간 스냅샷과 로컬 메타데이터를 플랫폼의 사용자 데이터
디렉터리에 보관합니다. 이 상태는 저장소와 함께 이동하지 않습니다.
dojang.toml의 repository-id는 저장소와 함께 이동하는 안정적인 UUID이며,
체크아웃을 옮기거나 이름을 바꿔도 올바른 로컬 상태를 찾는 데 쓰입니다.
등록된 저장소가 하나뿐이면 저장소 명령은 기록된 체크아웃을 자동으로 선택할 수
있습니다. 자동 선택은 체크아웃 안에 있는 사용자 지정 이름을 포함해 기록된
manifest 경로도 복원합니다. 기록된 외부 manifest는 여러 활성 체크아웃의 중복
소유권을 판정할 때 여전히 유효하지만, 이 레이아웃을 선택하려면
-r/--repository-dir과 -m/--manifest-file을 명시해야 합니다.
dojang init은 새 저장소의 식별자와 상태 레코드를 만듭니다. 서로 관계없는
저장소에 식별자를 복사하지 마세요. 한 머신에 같은 식별자를 가진 체크아웃이
둘 이상 있으면 오류로 처리됩니다. 심볼릭 링크 별칭을 포함해 같은 체크아웃으로
해석되는 경로는 중복으로 간주하지 않습니다.
저장 위치
상태 루트는 플랫폼별 관례를 따릅니다.
- Linux:
$XDG_DATA_HOME/dojang.XDG_DATA_HOME이 없거나 비어 있거나 상대 경로이면 ~/.local/share/dojang - macOS: ~/Library/Application Support/dojang
- Windows:
%LOCALAPPDATA%\dojang.LOCALAPPDATA가 없거나 비어 있거나 상대 경로이면 ~/AppData/Local/dojang
Dojang은 이 레이아웃을 만들기 전에 상태 루트의 파일시스템 별칭을 해석합니다. 따라서 플랫폼 사용자 데이터 디렉터리는 심볼릭 링크여도 되지만, Dojang의 비공개 상태 레이아웃 안에 있는 심볼릭 링크는 여전히 허용되지 않습니다.
루트 아래의 비공개 레이아웃은 다음과 같습니다.
machine.toml
machine.lock
manifest-identity.lock
repositories/
<repository-id>/
state.toml
state.lock
snapshots/
current/
machine.toml은 스냅샷을 소유한 머신을 식별합니다. 각 state.toml 레코드는 스키마 버전, 저장소와 머신 식별자, 마지막 체크아웃 경로, 그 체크아웃에서 사용한 manifest 경로, 중간 스냅샷 경로, 시각 정보, 그리고 대상·훅·수명 주기 레코드를 위한 타입이 정해진 영역을 포함합니다. 최초 적용 성공 여부도 전역 현재 저장소 파일이 아니라 저장소별로 기록됩니다.
이 파일들은 구현 세부 사항입니다. 레코드가 손상되었거나 더 새로운 스키마
버전을 사용하거나, 다른 저장소 또는 머신에 속하면 Dojang은 이를 상태 부재로
간주하지 않고 중단합니다. 상태 문서 자체는 올바른 UTF-8이어야 하며, 해독할 수
없는 바이트를 다른 문자로 치환하지 않고 손상으로 보고합니다. 상태 문서는
디렉터리나 심볼릭 링크가 아닌 일반 파일이어야 합니다. 저장소 데이터가 남아
있는데 machine.toml이 사라졌다면 새 머신 식별자를 발급하지 않고 손상으로
보고합니다. 마찬가지로 마이그레이션 마커나 스냅샷 데이터가 있지만
state.toml 레코드가 없는 저장소 디렉터리는 중단되었거나 손상된 엔트리로
보고합니다. 첫 원자적 상태 쓰기가 끝나기 전에 남은 빈 비공개
snapshots/current/ 디렉터리만 재시도 가능한 예외입니다. 저장소 탐색은 상태
잠금을 잡은 채 엔트리를 확인하며 다른 저장소를 조용히 선택하지 않습니다.
디렉터리 이름이 올바른 저장소 ID가 아닌 비어 있지 않은 엔트리도 손상으로
보고합니다. repositories/ 저장소 자체도 일반 디렉터리여야 하며, 그 경로의
파일이나 심볼릭 링크를 빈 저장소로 간주하지 않습니다. 머신 상태를 사용하는
명령은 체크아웃을 변경하기 전에 이 저장소를 검증합니다.
-r/--repository-dir로 저장소를 명시적으로 선택해도 같습니다. 올바른 저장소
ID 이름을 가진 디렉터리도 심볼릭 링크가 아닌 실제 디렉터리여야 합니다.
I/O 오류 때문에 상태 경로를 검사·생성·읽기·갱신할 수 없다면 예상하지 못한 오류
예외를 내보내지 않고 종료 코드 13의 머신 상태 오류를 보고합니다.
저장소 레코드는 원자적으로 교체하므로 쓰기
도중 중단되어도 이전의 완전한 레코드가 남습니다. 잠금 파일은 머신 식별자와
상태의 동시 갱신을 직렬화하며, 각 갱신은 고유한 임시 파일을 사용합니다. 잠금
엔트리는 일반 파일이어야 하며, 심볼릭 링크·디렉터리·특수 파일은 잠금을 열기 전에
거부합니다. 비공개 스냅샷 경로의 모든 구성 요소도 심볼릭 링크가 아닌 실제
디렉터리여야 합니다. 기존 체크아웃이나 스냅샷을 파일시스템 별칭으로 방문하면
Dojang은 임시 별칭을 저장하지 않고 기존의 안정된 기록 경로를 유지합니다. 저장된
경로는 명시적인 인코딩을 사용해 올바른 UTF-8이 아닌 파일시스템 고유 경로 값도
보존합니다. 체크아웃, manifest, 중간 경로는 절대 경로여야 하며, 상대 경로 값이
있으면 손상된 레코드로 처리합니다. Dojang은 버전별 필드보다 스키마 버전을 먼저
읽습니다. 따라서 나머지 구조가 현재 릴리스와 달라도 더 새로운 레코드에는 복구
안내 대신 업그레이드 안내를 표시합니다.
기록된 중간 스냅샷이 사라졌거나 일반 파일로 바뀌면 Dojang은 중단합니다. 사라진 공통 조상을 빈 스냅샷으로 간주하지 않습니다.
기존 저장소 마이그레이션
기존 체크아웃에서 마이그레이션을 명시적으로 실행합니다.
$ dojang -r /path/to/dotfiles migrate
Stable repository identity added to /path/to/dotfiles/dojang.toml.
Repository machine state is ready at .../snapshots/current.
먼저 --dry-run으로 파일 작업을 확인할 수 있습니다. 이때 선언, 스냅샷,
상태 저장소는 바뀌지 않습니다.
$ dojang --dry-run -r /path/to/dotfiles migrate
Stable repository identity added to /path/to/dotfiles/dojang.toml.
Repository machine state is ready at .../snapshots/current.
Note: Since --dry-run was specified, those 8 changes were not actually
committed to the filesystem.
머신 상태 루트는 예전 .dojang/ 스냅샷과 겹칠 수 없습니다. Dojang은 경로
별칭을 해석하고 상태 디렉터리를 만들거나 선언에 식별자를 추가하기 전에 이를
검사합니다. XDG_DATA_HOME이나 LOCALAPPDATA 때문에 상태 루트가 .dojang/
안에 놓인다면 마이그레이션 전에 스냅샷 밖의 플랫폼 기본 데이터 디렉터리를
선택하세요.
마이그레이션은 dojang.toml의 나머지 내용을 다시 쓰지 않고 repository-id를
추가합니다. 갱신된 선언은 같은 디렉터리의 임시 파일에 쓴 뒤 원본과 원자적으로
교체하면서 POSIX 모드 전체를 포함한 기존 파일 권한을 유지합니다. 선언은 올바른
UTF-8이어야 합니다. 해독할 수 없는 바이트가 있으면 원본 파일을 교체하지 않고
마이그레이션을 거부합니다. manifest를 읽거나 원자적으로 교체하지 못하면 종료
코드 11의 manifest 오류를 보고하고 원본을 유지합니다. 체크아웃에 예전
.dojang/ 스냅샷이 있으면 외부 저장소로 복사하고 두 사본 전체를 비교한 뒤 상태
레코드를 씁니다. 읽기 전용 선언의 권한은 새 내용을 쓴 뒤에 적용하므로 부모
디렉터리에 쓰기 권한이 있으면 원자적으로 교체할 수 있습니다. 기존 디렉터리는 이
검증이 끝난 후에만 제거합니다. 도중에 중단되면 마이그레이션 마커와 하나 이상의
완전한 사본이 남으므로 같은 명령을 다시 실행하면 됩니다.
마커는 같은 디렉터리의 임시 파일로 쓴 뒤 원자적으로 교체하므로 쓰기가 실패하거나
중단되어도 부분 마커를 노출하지 않습니다. 원본과 목적지를 모두 기록하고 정리가
끝날 때까지 유지됩니다. 마이그레이션할 때 -i/--intermediate-dir를
사용했다면 같은 값으로 다시 실행하세요. Dojang은 다른 재시도 목적지를 어떤
항목도 제거하기 전에 거부합니다. 마커는 일반 파일이어야 합니다. 디렉터리,
심볼릭 링크, 명명 파이프 등 일반 파일이 아닌 항목은 내용을 읽기 전에 손상된
상태로 보고합니다.
목적지에 원본과 일치하는 항목 일부만 있으면 중단된 부분 복사로 인식하고 처음부터
다시 복사합니다. 기존 목적지에 원본과 다른 항목이 하나라도 있으면 마커와 두
사본을 모두 보존하고 충돌 해결을 요청합니다. 상태 레코드나 기존 원본 없이 외부
스냅샷만 있는 경우에도 이를 공통 조상으로 채택하지 않고 거부합니다.
정리 도중 기존 스냅샷의 일부가 이미 제거되었다면, 남은 모든 항목이 완전한
목적지와 일치할 때만 재시도에서 나머지를 제거합니다.
이전 Dojang 버전에서 사용자 지정 중간 디렉터리를 사용했다면 마이그레이션할 때 같은 디렉터리를 지정하세요.
$ dojang -r /path/to/dotfiles -i /path/to/existing-snapshot migrate
Stable repository identity added to /path/to/dotfiles/dojang.toml.
Repository machine state is ready at /path/to/existing-snapshot.
Dojang은 명시적으로 선택한 기존 스냅샷을 검증한 뒤 복사하지 않고 그 위치에서
바로 기록합니다. 이 경우 .dojang/ 디렉터리가 없어도 됩니다. 스냅샷에는 일반
파일과 디렉터리만 있을 수 있습니다. 심볼릭 링크, 명명 파이프, 소켓, 장치 노드는
Dojang이 읽거나 복사하기 전에 거부됩니다. -i를 생략하면 상태 레코드가 없는
기존 외부 스냅샷은 계속 소유자를 확인할 수 없는 것으로 보고 거부합니다.
Dojang은 내용이 같은 두 사본 안에 중첩된 링크를 포함해 스냅샷 안의 심볼릭 링크를 마이그레이션하지 않습니다. .dojang 디렉터리 자체가 심볼릭 링크이면 그 대상의 내용을 읽거나 제거하기 전에 거부합니다. .dojang 경로가 일반 파일 등 디렉터리가 아닌 항목으로 존재해도 스냅샷 부재로 간주하지 않고 거부합니다.
이전 위치와 새 위치에 서로 다른 스냅샷이 있으면 마이그레이션을 거부하고 둘 다
변경하지 않습니다. 두 사본을 보존한 채 올바른 공통 조상을 선택하고, 다른
사본을 제거하거나 옮긴 다음 dojang migrate를 다시 실행하세요. 상태 레코드를
쓴 뒤 정리에 실패했다면 외부 스냅샷을 확인할 때까지 기존 디렉터리를 복구용으로
보관하세요.
예전 ~/.dojang 레지스트리는 마이그레이션 이력을 보존하고 안내를 출력할 때만
인식됩니다. 전역 현재 저장소를 선택하는 데에는 더 이상 쓰이지 않습니다.
손상된 레지스트리는 새 저장소 상태 레코드를 만들기 전에 고치거나 제거해야 하며,
유효한 레코드가 만들어진 뒤에는 무시됩니다. 레지스트리는 심볼릭 링크가 아닌
일반 파일이어야 합니다. 디렉터리, 끊어진 심볼릭 링크 등 일반 파일이 아닌
항목은 내용을 읽기 전에 손상으로 보고합니다. dojang init은 새 저장소를 만들
때 선언이나 라우트 디렉터리를 쓰기 전에 이 검사를 수행합니다. 이미
*.dojang/*이 있는 체크아웃도 거부하며, 기존 스냅샷은 명시적인
dojang migrate를 위해 그대로 둡니다. 유효한 저장소 레코드가 하나뿐이면
마지막 체크아웃에 대해 기록해 둔 경로의 manifest가 저장된 repository-id를
사용하는지 확인한 뒤 자동으로 선택합니다. 나중에 지정한 -m/--manifest
값으로 이 소유권 검사를 바꾸지 않습니다. 체크아웃이 사라졌거나 이제 다른
저장소에 속하면 중단하고 -r/--repository-dir로 저장소를 명시하라고
안내합니다. 레코드가 둘 이상인 경우에도 기록된 체크아웃 중 하나가 일시적으로
사라졌는지와 관계없이 저장소를 명시해야 합니다. dojang version과
dojang help 같은 메타 명령은 머신 상태 저장소를 열지 않습니다. 저장소를
명시하면 관계없는 다른 저장소 레코드도 탐색하지 않습니다. 절대 경로 manifest는
경로를 해석한 결과가 기록된 체크아웃 안에 있을 때만 자동 선택된 체크아웃을
검증할 수 있습니다. 다른 위치의 manifest를 사용하려면 -r로 저장소도
명시하세요.
dojang init과 dojang migrate는 머신 상태 저장소를 검증하지만 등록된
체크아웃을 자동으로 선택하지 않습니다. -r를 생략하면 각 명령은 현재
디렉터리를 사용합니다. --ignore-env-file을 지정한 dojang env는 호스트
환경만 읽으므로 머신 상태 저장소를 열거나 저장소를 선택할 필요가 없습니다.
명시적으로 선택한 체크아웃이 이동한 경우, 예전 경로에 대해 기록해 둔 manifest를
읽을 수 있고 그 manifest가 같은 repository-id를 계속 사용할 때만 중복
저장소로 처리합니다. 나중에 예전 경로를 차지한 관계없는 데이터는 체크아웃
이동을 막지 않습니다.
예전 레지스트리가 마이그레이션할 체크아웃을 가리키면 최초 적용 완료 상태를 보존합니다. 이 비교 전에 체크아웃 경로의 별칭을 해석합니다. 이전 버전에서 이미 성공적으로 실행한 일회성 훅을 마이그레이션 뒤에 다시 실행하지 않습니다. 동시에 수명 주기 상태를 갱신할 때도 현재 레코드를 다시 읽으므로 예전 스냅샷 경로를 복원하지 않습니다.
동시에 실행한 마이그레이션은 선언의 저장소 식별자를 읽거나 할당하는 동안 같은 잠금을 공유합니다. 따라서 UUID는 하나만 기록되며, 각 프로세스는 저장소 상태를 준비하기 전에 잠금 안에서 그 식별자를 다시 읽습니다.
다른 중간 디렉터리 선택
-i/--intermediate-dir는 계속 지원됩니다. 지정한 경로는 한 번만 쓰는
오버라이드가 아니라 저장소 설정으로 저장됩니다. 상대 경로는 저장소 체크아웃을
기준으로 해석합니다. 다른 경로를 다시 명시하기 전까지 이후 명령은 저장된
경로를 사용합니다. .dojang이 마이그레이션 원본인 동안에는 그 하위 경로를
중간 디렉터리로 지정할 수 없습니다. 스냅샷은 체크아웃이나 머신 상태 루트를
포함할 수 없고, 상태 루트 안의 경로는 해당 저장소의 전용 snapshots/ 디렉터리
안에 있어야 합니다. 이 규칙은 이후 정리가 저장소 파일이나 머신 상태
메타데이터를 함께 제거하지 못하게 합니다.
저장된 중간 경로를 바꿀 때도 같은 복사·비교·충돌 규칙이 적용됩니다. 이 옵션으로
지정한 새 경로와 현재 스냅샷 경로는 서로를 포함할 수 없습니다. Dojang은 이
규칙을 확인하기 전에 파일시스템 별칭을 해석하며, 한 스냅샷의 별칭을 서로 다른
기존 사본으로 간주해 제거하지 않습니다. 검증된 새 사본을 가리키는 상태 레코드가
저장될 때까지 기존 스냅샷을 보존합니다. -i를 생략하면 사용하지 않는 기본
경로가 아니라 실제로 저장된 사용자 지정
경로를 검증합니다. 복사를 시작하기 전에 마이그레이션 마커를 기록하므로 복사가
중단되거나 실패해도 같은 -i/--intermediate-dir
값으로 재시도할 수 있습니다. 목적지에 이미 완전하고 동일한 사본이 있어도 상태
레코드를 갱신하기 전에 마커를 기록합니다. 따라서 정리가 중단되면 다음 실행이
기존 스냅샷 제거를 마칠 수 있습니다. 재시도할 때는 기존 항목이 모두 원본과
일치하는 목적지만 버립니다. 다른 데이터가 있으면 그대로 두고 충돌로
보고합니다. 이 옵션으로 머신 상태를 작업 트리 안에 둘 수도 있지만, 파일 동기화
서비스 같은 전송 수단이 머신별 이력을 다른 기기로 복사할 수 있습니다. 외부 기본
위치는 이 위험을 피합니다.