Git에서 GPG key로 signoff 하기
Posted: October 9, 2015 Filed under: Code, FOSS | Tags: git, gpg Leave a comment공헌자들 패치를 받아서 커밋할 때, 컨트리뷰터의 author를 유지하면서 또한 커미터가 직접 확인했다는 증명을 signoff 기능을 통해 할 수 가 있다. 그런데 signoff 가 단순하게 커밋로그에 남는 ‘메일 주소와 이름 뿐’인 태그일 뿐이라서 진짜 그 사람이 signoff를 했는지 증명하는 것이 어렵다는 문제가 있다. 다행히 git에서는 GPG key를 이용한 signoff 기능을 제공한다. 우선은 내가 볼 목적으로 그리고 동료들에게 설명할 목적으로 정리를 해본다.
GPG에 대한 사용법은 생략한다. 우선 자신의 Key id를 얻는다.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| $ gpg –list-secret-keys | grep ^sec | |
| sub 4096R/4CFE2390 2013-10-16 [expires: 2017-10-16] | |
| # ^— your key id |
그리고 git config의 user.signingkey로 GPG key id를 설정한다. 각 repository 마다 설정하고 싶으면 –global 옵션을 빼면 지정 repository에만 (현재 디렉토리의 git repository) 지정할 수 있다.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # remove –global to use this key only on the current repository | |
| $ git config –global user.signingkey 4CFE2390 | |
| # ^- replace with your key id |
그리고 커밋을 한다. 아래 옵션이 많지만 GPG key로 사인을 위한 옵션은 -S 이다.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| hyunsik@workstation:~/Code/tajo/tajo$ git commit -S -m "TAJO-1909: Eliminate remained explicit diamond expressions."</code> | |
| You need a passphrase to unlock the secret key for | |
| user: "Hyunsik Choi <hyunsik@apache.o….>" | |
| 4096-bit RSA key, ID 4CFE2390, created 2013-10-16 (main key ID AC3885B9) | |
| [master 6bc9fbb] TAJO-1909: Eliminate remained explicit diamond expressions. | |
| Author: Dongkyu Hwangbo <hwang….@gma……>; | |
| Date: Thu Oct 8 15:02:58 2015 -0700 | |
| 72 files changed, 150 insertions(+), 147 deletions(-) |
GPG key-agent가 켜져 있다면 패스워드 직접 입력없이 자동으로 위에서 설정한 키로 사인과 함께 커밋이 된다. 그럼 확인해보자.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| hyunsik@workstation:~/Code/tajo/tajo$ git log –show-signature | |
| commit 6bc9fbb50fb8b45d3fd58d9f10f74fefe62106fe | |
| gpg: Signature made Thu 08 Oct 2015 03:15:39 PM PDT using RSA key ID 4CFE2390 | |
| gpg: Good signature from "Hyunsik Choi <hyunsik@apach.o..>" | |
| gpg: WARNING: This key is not certified with a trusted signature! | |
| gpg: There is no indication that the signature belongs to the owner. | |
| Primary key fingerprint: 9141 BD40 6A84 DBA1 F4BD 5F04 024C 922A AC38 85B9 | |
| Subkey fingerprint: 1BB1 D697 599C 74BD C917 2F89 FE68 DD32 4CFE 2390 |
‘not certified’라고 나올 수 가 있다. key가 로컬 머신에 등록되어 있지만 trust key로 설정되어 있지 않아서 그렇다고 한다 (자세히는 모름). 해결은 아래와 같이 --edit-key 옵션으로 한다.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| hyunsik@workstation:~/Code/tajo/tajo$ gpg –edit-key 4CFE2390 trust | |
| gpg (GnuPG) 1.4.18; Copyright (C) 2014 Free Software Foundation, Inc. | |
| This is free software: you are free to change and redistribute it. | |
| There is NO WARRANTY, to the extent permitted by law. | |
| Secret key is available. | |
| pub 4096R/AC3885B9 created: 2013-10-16 expires: 2017-10-16 usage: SCEA | |
| trust: unknown validity: unknown | |
| sub 4096R/4CFE2390 created: 2013-10-16 expires: 2017-10-16 usage: SEA | |
| [ unknown] (1). Hyunsik Choi <hyunsik@apach.o….>; | |
| pub 4096R/AC3885B9 created: 2013-10-16 expires: 2017-10-16 usage: SCEA | |
| trust: unknown validity: unknown | |
| sub 4096R/4CFE2390 created: 2013-10-16 expires: 2017-10-16 usage: SEA | |
| [ unknown] (1). Hyunsik Choi <hyunsik@apach.o….>; | |
| Please decide how far you trust this user to correctly verify other users' keys | |
| (by looking at passports, checking fingerprints from different sources, etc.) | |
| 1 = I don't know or won't say | |
| 2 = I do NOT trust | |
| 3 = I trust marginally | |
| 4 = I trust fully | |
| 5 = I trust ultimately | |
| m = back to the main menu | |
| Your decision? 5 | |
| Do you really want to set this key to ultimate trust? (y/N) y |
그리고 다시 확인해보자.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| hyunsik@workstation:~/Code/tajo/tajo$ git log –show-signature | |
| commit 5d470bc6001bb4fe096d7a8d221e51c18c683899 | |
| gpg: Signature made Thu 08 Oct 2015 03:21:24 PM PDT using RSA key ID 4CFE2390 | |
| gpg: Good signature from "Hyunsik Choi " |
Warning이 없어진 것을 알 수 있다.
See Also
근래 배운 몇 가지 패턴 정리: Provider, Builder, Delegation
Posted: October 5, 2015 Filed under: Code | Tags: design pattern Leave a commentProvider
정확히 말하면 디자인 패턴은 아니라고 한다. 자세한 설명은 [1]에 있다. Factory 패턴과 유사하나 외부 설정에 따라 다른 객체를 생성하는 패턴을 칭한다. 나쁜 패턴이라며 [1]과 함께 Constructor Injection 같은 방법을 써야 한다는 주장이 있지만, 실제로 잘 작성된 오픈소스 프로젝트들에서도 이러한 구현을 꽤 많이 볼 수 있다.
Builder
생성자에 전달되어야 할 파라메터가 다양해서 골치 아픈 경우 Builder 패턴이 좋은 해결책이 된다. 방법은 Builder 객체를 만들고 setter 를 통해 필요한 파라메터를 설정 한 후에 build() 메소드 호출을 통해 실제 객체를 생성한다.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| let storage = StorageBuilder.newBuilder() | |
| .setURL("file:///tmp/test.csv") | |
| .setType("csv") | |
| .setFieldDelimiter(",") | |
| .setLineDelimiter("\n") | |
| .setEncoding("UTF-8") | |
| .build(); |
Delegation
처음 Delegation 패턴을 봤을 때는 Interface의 구현과 차이점을 잘 발견하지 못했었다. 위키 피디아에도 설명이 있지만 언제 써야 하는지가 설명되어 있지 않았다. [3] 에서 이유를 찾았는데. 요약을 해보면,
- 원래 있는 객체의 동작을 그대로 유지하면서 동작의 앞뒤에 처리를 추가하고 싶을 때
- 호환되지 않는 인터페이스를 위한 Proxy 를 구현할 때
- 실제 구현 사용 시 복잡도가 높은 콜 루틴을 단순하게 제공하려고 할 때
경우에 따라 서브클래싱과 함께 쓸 수 있을 것 같으며 데코레이터 패턴에서 주로 나타나는 패턴인 것 같다.
See Also
[1] Provider Model Design Pattern and Specification, Part 1
[2] Provider is not a pattern
[3] http://stackoverflow.com/questions/7168714/what-is-the-purpose-of-a-delegation-pattern/7168737#7168737
Jni Native를 통한 Rust 함수 호출
Posted: September 25, 2015 Filed under: Code, FOSS, Tokamak Project | Tags: jni, rust, Tajo Leave a comment회사 허락을 맡아 홀로 프로젝트를 하나 시작했다. 큰 그림은 일부 컴포넌트를 Rust로 구현하고 컴포넌트간 연결은 rpc로 하는 것인데 아직 Rust 로 rpc 구현을 하기에 시간이 더 필요하다. 임시적인 수단으로 JNI를 통해 기존 컴포넌트에 연결을 하려고 한다.
그 외 프로젝트에 자세한 이야기는 나중에 설명하고 위 목적으로 Stackoverflow 에서 참고하고 https://github.com/Monnoroch/RustJni 를 참고해서 JNI를 테스트를 해봤다.
C 바인딩이 쉬운것은 Rust의 장점 중 하나인데 JNI 바인딩 역시 순조로웠다. 방법은 우선 아래와 같이 native 함수 인터페이스를 작성하고
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public class NativeInvoke { | |
| public static native void procedure(); | |
| public static native void stringArg(String str); | |
| public static native String returnString(); | |
| } |
아래와 같이 Rust 코드를 작성하면 된다.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #![crate_type="dylib"] | |
| #![feature(libc)] | |
| #![allow(non_camel_case_types)] | |
| #![allow(non_snake_case)] | |
| #![allow(unused_variables)] | |
| extern crate libc; | |
| extern crate jni; | |
| use libc::c_void; | |
| use std::ptr; | |
| use jni::native::*; | |
| use jni::helper::*; | |
| #[no_mangle] | |
| pub extern fn Java_org_github_hyunsik_NativeInvoke_procedure(jre: *mut JNIEnv, | |
| class: *const c_void) { | |
| println!("Invoked native method, jre: {:p}, class: {:p}", jre, class); | |
| unsafe { | |
| let v = ((**jre).GetVersion)(jre); | |
| println!(">> version: {:?}", v); | |
| } | |
| } | |
| #[no_mangle] | |
| pub extern fn Java_org_github_hyunsik_NativeInvoke_stringArg(jre: *mut JNIEnv, | |
| class: *const c_void, name: jstring) { | |
| unsafe { | |
| let string = ((**jre).GetStringUTFChars)(jre, name, ptr::null_mut()); | |
| println!("{}", chars_to_str(string)); | |
| ((**jre).ReleaseStringUTFChars)(jre, name, string); | |
| } | |
| } | |
| #[no_mangle] | |
| pub extern fn Java_org_github_hyunsik_NativeInvoke_returnString(jre: *mut JNIEnv, | |
| class: *const c_void) -> jstring { | |
| unsafe { | |
| return str_to_jstring(jre, "jni native"); | |
| } | |
| } |
이게 전부다. 위에서 사용된 chars_to_str와 str_to_jstring 는 아래 github repository에 있다.
https://github.com/hyunsik/jni-rs/blob/master/src/helper.rs
위 repository 는 https://github.com/Monnoroch/RustJni를 fork 해서 JNI 뿐 아니라 JNI 프로그램 작성 중에 반복되는 코드들에 대한 유틸리티 함수들을 추가할 계획이다.
그리고 아래는 JNI Native + Rust 를 위한 템플릿 프로젝트이다.
https://github.com/hyunsik/rust-jni-template