3방향 병합
dojang merge는 저장소와 대상 경로에서 모두 변경된 파일을 해결합니다. 중간
스냅샷을 공통 조상으로 사용하고 설정된 병합 드라이버를 실행한 뒤, 승인한 결과를
원본, 대상 경로, 중간 스냅샷에 기록합니다.
명령 사용하기
현재 3방향 충돌을 모두 선택하려면 경로 없이 명령을 실행합니다:
$ dojang merge
원본 경로, 대상 경로, 또는 둘을 포함하는 디렉터리를 전달하면 선택 범위를 줄일 수 있습니다. 경로를 여러 개 전달할 수도 있습니다:
$ dojang merge HOME/.bashrc ~/.config/example/
--driver NAME은 기본값 대신 이름이 지정된 드라이버를 선택합니다.
--driver-file PATH는 다른 설정 파일을 읽습니다. --dry-run은 선택한 충돌과
드라이버 설정을 검증하고 계획을 출력하지만, 작업 영역을 만들거나 드라이버를
시작하거나 파일과 머신 상태를 바꾸지 않습니다.
버전 0.3은 identity 코덱을 사용하는 copy 경로 규칙의 UTF-8 정규 텍스트
파일을 지원합니다. 원본, 대상 경로, 중간 스냅샷이 모두 있어야 합니다.
디렉터리 경로 규칙, 배포 링크, 변환 코덱, 바이너리 파일, 잘못된 UTF-8, 공통
중간 스냅샷이 없는 충돌은 병합 드라이버를 시작하기 전에 거부됩니다. 경로 없이
실행했을 때 선택하지 않으려는 미지원 충돌이 명령을 막는다면, 지원되는 충돌의
경로를 명시적으로 전달하세요.
드라이버 설정하기
병합 드라이버는 머신별 로컬 설정입니다. 기본 설정 경로는 다음과 같습니다:
| 플랫폼 | 경로 |
|---|---|
| Windows | %APPDATA%\dojang\merge-drivers.toml |
| macOS | ~/Library/Application Support/dojang/merge-drivers.toml |
| 기타 플랫폼 | $XDG_CONFIG_HOME/dojang/merge-drivers.toml |
Windows에서는 APPDATA가 없거나 상대 경로이면
%USERPROFILE%\AppData\Roaming을 사용합니다. 그 밖의 플랫폼에서는
XDG_CONFIG_HOME이 없거나 상대 경로이면 ~/.config를 사용합니다.
설정 파일에는 기본 드라이버와 하나 이상의 드라이버를 선언합니다:
default-driver = "example"
[merge-drivers.example]
command = [
"my-merge-driver",
"{result}",
"{base}",
"{source}",
]
inherit-environment = ["PATH"]
unresolved-exit-codes = [1]
canceled-exit-codes = [130]
[merge-drivers.example.environment]
LC_ALL = "C"
command는 셸 명령이 아닌 인자 배열입니다. {source}, {base}, {result}는
각각 정확히 한 번씩 독립된 인자로 나타나야 합니다. {destination}은 선택
사항이며 한 번만 쓸 수 있습니다. 결과 파일은 대상 파일의 사본으로
초기화됩니다. 드라이버는 이 파일을 갱신하고 0을 반환해 충돌을 해결합니다.
자식 프로세스에는 inherit-environment로 지정한 변수와 environment의 고정
값만 전달됩니다. 고정 값은 상속한 값을 덮어씁니다.
unresolved-exit-codes에서 1부터 255까지의 코드는 해결되지 않은 충돌을
뜻합니다. canceled-exit-codes도 같은 범위를 사용하며 사용자가 병합을
취소했음을 뜻합니다. 두 목록은 겹칠 수 없습니다.
안전과 복구
Dojang은 첫 드라이버를 시작하기 전에 선택한 모든 입력을 검증합니다. 각
드라이버는 소유자 전용 작업 영역의 비공개 사본을 전달받으며 셸 없이 실행됩니다.
예비 충돌 감지 중이거나 입력을 캡처하는 동안 입력이 사라지거나 읽을 수 없게
되면 내부 오류 대신 충돌을 보고합니다. 승인한 결과를 기록하기 전에는 기준
파일이 검증 때 관찰한 바이트, 식별 정보, 모드와 여전히 일치하는지 확인합니다.
각 결과에 최종 모드를 먼저 적용해 준비한 뒤, 사본의 정확한 내용과 식별 정보,
모드가 그대로일 때만 교체합니다. 따라서 결과를 준비하는 동안 생긴 편집은
보존하고 충돌을 보고합니다. 선언된 모드도 게시 전에 적용하므로 나중에 교체된
심볼릭 링크가 권한 변경을 다른 파일로 돌릴 수 없습니다. 드라이버가 끝난 뒤에는
라우팅 컨텍스트를 다시 불러오고, 선택한 라우트나 해석된 경로, 종류, 모드, 코덱,
결정 근거가 바뀌었으면 결과를 거부합니다. 저장소, 머신, 상태 세대의 식별 정보가
바뀐 경우에도 결과를 거부합니다. 호출 작업 영역 생성과 마지막 사본 기록은
저장소 세대 잠금 안에서 하므로, 작업 영역을 정리한 뒤 다시 만드는 사이와 병합
커밋 도중에는 dojang forget이 삭제를 승인할 수 없습니다. 관리 대상 상태를
게시할 때도 상태 갱신 잠금 안에서 캡처한 세대를 다시 확인하여, 저장소를 잊고
다시 만든 세대에 이전 데이터를 게시하지 않습니다. post-merge 훅을 준비할
때는 현재 매니페스트, 환경, 머신 정보를 다시 불러오되 새 머신 상태를 준비하지
않고 캡처한 세대를 재사용하고 검증합니다. 따라서 삭제된 훅은 실행하지 않으며,
먼저 저장소를 잊으면 상태를 다시 만들거나 훅을 실행하지 않습니다.
결과는 원본, 대상 경로, 중간 스냅샷 순서로 기록합니다. 두 기준 사본에 결과를
기록하기 전에 중간 스냅샷이 수렴을 나타내지 않도록 하기 위한 순서입니다. 첫
쓰기 전에는 승인한 결과와 원래 공통 조상 및 대상의 해시를 저널에 기록합니다.
뒤쪽 쓰기에서 실패하면 앞서 쓴 결과는 남습니다. 원본 쓰기 뒤에 커밋이
중단되었을 때는 원본에 승인한 결과가 있고 나머지 입력이 기록한 해시와 일치하는
동안만 재시도에서 저널을 사용해 커밋을 마칩니다. 두 기준 사본에는 이미 결과가
있지만 대상 경로의 모드나 중간 내용 또는 모드가 뒤처진 경우도 복구 대상으로
인식합니다. dojang merge를 다시 실행하거나 보고된 작업 영역을 살펴 복구할
수 있습니다. 조건부 교체 중에는 이전 사본을 같은 디렉터리의 숨은
.dojang-replaced-* 형제 항목으로 잠시 옮깁니다. 일반적인 실패는 원래
자리로 복원하거나 보존된 경로를 보고합니다. 이전 사본을 옮기기 전에 준비한
결과의 식별 정보, 내용, 최종 모드를 묶어서 확인하고, 이름을 바꾼 뒤에도 같은
항목인지 다시 검증합니다. 옮긴 뒤 준비한 결과를 게시하기 전에 프로세스나
머신이 멈췄다면, 재시도하기 전에 그 형제 항목을 비어 있는 원래 사본 경로로
되돌리세요. 실패하거나 해결되지 않았거나 취소된 작업 영역은 보존하고 오류
출력에 경로를 표시합니다. 성공한 작업 영역은 삭제합니다.
dojang forget은 해당 저장소에 보존된 병합 작업 영역을 모두 삭제합니다.
재귀적으로 삭제하기 전에는 작업 영역 디렉터리와 그 상위 구성 요소 전체를
검증하고, 심볼릭 링크 때문에 머신 로컬 상태 밖으로 삭제 대상이 바뀔 수 있으면
정리를 거부합니다.
머신 상태를 게시하기 직전에는 세 사본을 모두 다시 관찰하고 선언된 대상 및 중간
모드를 다시 확인합니다. 내용이나 모드 수렴이 사라졌거나 입력을 더 이상 관찰할
수 없으면 충돌을 보고하고 복구 저널을 보존합니다. 드라이버가 끝난 뒤 라우트
정책을 새로 확인하는 동안 기준 입력을 다시 관찰할 수 없는 경우에도 같은 충돌
상태를 사용합니다. 일반 파일은 지문 계산과 변경 불가능한 베이스라인 생성을
전후해 정확한 내용, 식별 정보, 모드를 캡처하고, 지문과 베이스라인이 같은 내용을
나타내는지 확인한 다음 모든 사본을 다시 검증합니다. 따라서 어느 단계에서든
변경이 생기면 서로 다른 버전의 관찰 결과를 조합하지 않고 게시를 중단합니다.
다른 항목 때문에 같은 다중 파일 스냅샷 트랜잭션을 보존하더라도 거부된
베이스라인은 삭제합니다. 빈 디렉터리도 다른 항목이 성공적으로 기록한
베이스라인일 수 있으므로 상위 디렉터리는 보존합니다.
가드된 커밋이 중단된 뒤에도 게시 대기 마커를 보존하고 관리 대상 상태 게시가
성공한 뒤에만 삭제하므로, 나중에 수렴한 상태에서 머신 상태 레코드를 복구할 수
있습니다.
작업 영역 준비에 실패하면 비공개 부분 사본을 가능한 한 삭제합니다. 게시 대기
중인 작업을 복구할 때는 알려진 호출 및 충돌 디렉터리 단계만 탐색합니다. 각
단계는 고정한 디렉터리 항목을 통해 열람하고, 게시 대기 마커 생성과 삭제는
캡처한 작업 영역 및 상위 디렉터리 식별 정보에 결합합니다. 따라서 동시에
교체된 디렉터리는 변경하지 않고 보존합니다. 드라이버가 만든 하위 디렉터리는
재귀적으로 탐색하지 않습니다. 각 입력 사본은 고정한 작업 영역 디렉터리를
기준으로 소유자 전용 모드와 함께 생성하므로, 작업 영역 경로를 교체해도 쓰기
대상을 바꿀 수 없습니다. 이후 파일 시스템 작업이 실패하면 작업 영역을 보존하고
종료 상태 2를 사용합니다. 완료한 호출 작업 영역을 삭제하다 실패한 경우에도
같은 종료 상태를 사용하고 살펴볼 작업 영역 루트를 알려 줍니다. 비어 있는 호출
상위 디렉터리는 고정한 상태에서 비어 있음을 확인하고 작업 영역 정리 전에
캡처한 식별 정보가 여전히 일치할 때만 삭제합니다. 따라서 형제 복구 작업
영역은 원래 경로에 그대로 남습니다. 드라이버 결과를 읽을 수 없다면 잘못된
출력으로 취급하여 사본을 쓰기 전에 거부하고 종료 상태 4를 사용합니다.
명령은 충돌 선택에 사용할 컨텍스트를 불러오기 전에 pre-merge 훅을 실행합니다.
성공한 뒤 post-merge 훅을 선택하기 전에는 매니페스트, 환경, 머신 정보를 다시
불러옵니다. 설정 방법은 훅 문서를 참고하세요.
종료 상태
주요 종료 코드는 다음과 같습니다:
1: 잘못된 드라이버 설정 또는 선택.2: 파일 시스템 쓰기 실패.4: 드라이버 실행 실패, 시작 실패, 또는 잘못된 결과.13: 머신 상태 갱신 실패.30: 미지원 충돌, 해결되지 않은 충돌, 또는 동시 변경.32: 선택한 경로에 대응하는 경로 규칙이 없음.36: 드라이버가 취소를 보고함.40: 병합 훅 실패.
전체 목록은 종료 코드 문서를 참고하세요.