'패치'에 해당되는 글 3건

  1. 2009.12.08 Mercurial 1.4.1 - 1.5.1 timestamp patch by movsd
  2. 2009.12.02 patch 2.5.9 패치 by movsd
  3. 2008.01.07 cvs 1.12.13 패치 by movsd

Mercurial로의 이전을 염두에 두고 얼마동안 이리저리 실험을 해보았다. CVS에서 주로 사용하던 것들은 다 지원이 된다는 것에 일단 이전에 긍정적이다. 그런데 결정적으로 새 작업디렉토리를 만들때에 파일의 날짜가 항상 "지금"의 날짜와 시간으로 정해진다는 것에 적응이 되지 않는다. hg clonecvs co같이 쓰려고 하는 자세의 문제일 수도 있다. 메일링 리스트와 웹을 뒤져봐도, 기존의 timestamp에 관한 질문/기능신청에 대한 대답은, DVCS를 CVS처럼 쓰려고 하는게 잘못이라는 얘기들 뿐이다.

혹자는 Mercurial 위키에 소개된 timestamp extension을 쓰면 되지 않냐고 하겠지만, 코드를 읽어보니 작동방식이 좀 깔끔하지 못하다. 게다가 내가 원하는 파일 시간은 임의의 시간이 아니라, 마지막으로 파일을 변경하고 commit한 시간이므로 이 extension은 나에게는 별 도움이 되지 않는다. 어쨌거나, CVS에서 넘어오는 사용자를 위해 keyword를 쓰게끔 도와주면서, timestamp 하나 CVS처럼 찍어주는 것은 크게 어렵지 않을텐데 하는 생각이다. (물론, 나도 시간이 흘러 DVCS에 익숙해지면 이런 패치를 쓸데없는 짓이라고 할지도 모른다.)

이 패치의 목표는, 새로 생성되는 파일의 시간을 관련된 마지막 commit시간으로 지정하도록 하는 것이다. 새로 생성되는 파일이라 함은 hg archive로 생성되는 파일과, hg update를 실행했을때 작업디렉토리에 없는 파일(보통, 다른 사람이 추가한 파일이나, hg clone을 실행할때 새로 생성되는 작업디렉토리의 파일들)을 말한다. 이 시간 정보를 어떻게 읽어올 지는 keyword extension에 이미 나와있다. 그것과 os.utime()만 조합하면 문제는 간단히 해결된다. 그 간단한 패치는 밑에서 받을 수 있다. 패치는 몇일전에 나온 1.4.1버전을 대상으로 만들었다. (2010년 초하루에 나온 1.4.2버전과 1.4.3버전에도 깨끗하게 적용된다. 1.5버전에 해당하는 패치는 아래의 다운로드 링크를 참조.)

명령행 요약

tar xzf .../mercurial-1.4.1.tar.gz
cd mercurial-1.4.1
patch -p0 -b < .../timestamp.patch
python setup.py build
python setup.py install

패치를 읽어보면 금방 알겠지만, 이런 단순한 기능을 제작자들이 몰라서 또는 어려워서 안 넣었을 것 같지는 않다. 또, 없으면 안되는 기능이었다면 그 수많은 사용자들중에 누군가가 이미 그 방법을 알아내서 공개했었을 것이다. 그러므로, CVS로부터 넘어오는 사용자가 아니면 이 패치의 유용성은 제한될 것이다.

패치 파일

1.4.x용 패치
1.5.x용 패치
Posted by movsd
,

patch 2.5.9 패치

hack 2009. 12. 2. 20:00
유닉스에서는 아주 유용하게 쓰는 GNU patch의 윈도우즈용 실행파일을 업데이트 하려고 이리저리 찾아보아도 마음에 드는 것이 없어서 결국 소스코드 수준에서 고쳐서 쓰기로 했다.

실행파일 제공하는 곳은 cygwin, mingw, gnuwin32 등등 여러군데 있는데, 하나같이 불필요한 DLL을 설치하기를 강요하거나, 패치파일이나 패치대상 파일의 개행문자가 자기들이 정한대로 따르지 않으면 그냥 자빠져 버리는 등, 사용성에 있어서 참 짜증스럽게 만들어 놓았다.

어차피 patch는 소스가 공개되어 있으니 좀 고치면 원하는대로 바꿀 수 있다. 목표는, 우선 개행문자의 제약을 없애고, 다음으로 유닉스에서처럼 --posix옵션이 주어지지 않으면 백업파일을 자동으로 만들게 하는 것이다. 어차피 patch를 이용해 패치하는 파일들은 소스코드들이니, 개행문자를 가지고 패치가 엉터리라고 까다롭게 구는 것은 별 의미가 없다고 생각된다.

이 패치를 제작하는 과정에서 컴파일러는 마이크로소프트에서 무료로 제공하는 것을 썼다. 곁다리: gcc를 쓸거면 어차피 cygwin이나 mingw을 설치해야 gcc를 쓸 수 있으니, 거기서 제공하는 patch실행파일을 쓰는게 여기의 것을 쓰는 것보다 일관성의 측면에서 낫다. 게다가 mingw용 patch는 reject파일도 unified diff로 만드는 옵션이 있다. context diff에 익숙하지 않으면 꽤 유용한 옵션이다.

소스는 ftp://ftp.gnu.org/gnu/patch/patch-2.5.9.tar.gz에서 받아오면 되고, 패치파일은 아래에서 받으면 된다.

명령행 요약: (패치파일 맨처음과 같은 내용. 현재 스킨에서는 마지막 줄의 일부만 보인다.)

tar xzf patch-2.5.9.tar.gz
cd patch-2.5.9
patch -p0 -b < patch.patch
cl /I. /DHAVE_CONFIG_H /Ded_PROGRAM=\"ed\" /Fepatch.exe error.c addext.c argmatch.c backupfile.c basename.c dirname.c getopt.c getopt1.c inp.c maketime.c partime.c patch.c pch.c quote.c quotearg.c quotesys.c util.c version.c xmalloc.c

---

@ 패치를 패치한다고 하니까 말이 꼬인다.

Posted by movsd
,

cvs 1.12.13 패치

hack 2008. 1. 7. 20:00

CVS는 많은 사람들이 사용하고 있고, 사용하지 않더라도 무엇인지 한번쯤은 들어봤을만한 도구이다. 윈도우즈에 특화하려는 의도로 시작된 CVSNT도 있지만, 나의 경우에는 실행파일 하나만 있으면 설치할 필요도 없이 간편하게 모든 CVS 기능을 사용할 수 있는 원조 CVS를 선호한다. 윈도우즈용 실행파일도 FSF의 FTP사이트에서 제공된다. 그런데, 이 실행파일을 사용하면, 로컬 저장소를 지정할때, 드라이브를 지정할 수 없는 경우가 있다. 예컨대,

cvs -d :local:c:\cvs init
이 경우에는 드라이브를 적어주어도 제대로 작동하나, 이렇게 만든 저장소를 관리하기 위해 다음과 같이 하면,
cvs -d :local:c:\cvs co CVSROOT
조금 전에 만든 저장소를 찾지 못한다.

이를 해결하려면, 소스코드를 받아서 약간 고쳐서 컴파일하면 된다. 패치는 다음과 같다. (아래에서 다운로드 받을 수 있다.)

--- lib/canonicalize.c.old	Fri Jun 10 15:30:20 2005
+++ lib/canonicalize.c	Sun Jan 06 09:34:40 2008
@@ -20,6 +20,12 @@
 # include <config.h>
 #endif
 
+#ifdef WIN32
+/* need the next to exclude winsock headers */
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
 #include "canonicalize.h"
 
 #ifdef STDC_HEADERS
@@ -127,13 +133,44 @@
   return resolved;
 
 # else
+#  ifdef WIN32
+	/* Use GetFullPathName() with existence check. */
+	char namebuf[_MAX_PATH+1];
+	DWORD n;
+	char *p, *resolved;
+
+	n = GetFullPathName(name, sizeof(namebuf), namebuf, &p);
+	if (n == 0)
+		return NULL;
+	/* n is strlen() or required size, so, we have malloc() size. */
+	if ((resolved = xmalloc(n + 1)) == NULL)
+		return NULL;
+	/* if name buf was not enough, GetFullPathName() again. */
+	if (n > sizeof(namebuf)) {	/* get it directly to `resolved' */
+		if ((n = GetFullPathName(name, n + 1, resolved, &p)) == 0) {
+			free(resolved);
+			return NULL;
+		}
+	}
+	else {
+	    memcpy(resolved, namebuf, n + 1);	/* copy including NUL */
+	}
+	/* check if it exists. */
+	if (GetFileAttributes(resolved) == -1) {
+		free(resolved);
+		return NULL;
+	}
+	return resolved;
+#  else
 
   return canonicalize_filename_mode (name, CAN_EXISTING);
 
+#  endif
 # endif /* !HAVE_RESOLVEPATH */
 }
 #endif /* !HAVE_CANONICALIZE_FILE_NAME */
 
+#ifndef WIN32
 /* Return the canonical absolute name of file NAME.  A canonical name
    does not contain any `.', `..' components nor any repeated file name
    separators ('/') or symlinks.  Whether components must exist
@@ -316,3 +353,4 @@
   free (rname);
   return NULL;
 }
+#endif

필요한 도구들

명령행 요약

unzip cvs-1.12.13a.zip
cd cvs-1.12.13a
patch -p0 < cvs.patch
nmake -f cvsnt.mak

패치 파일

Posted by movsd
,