From 1775451793b4538e27047dfdb2feec4b46b766a9 Mon Sep 17 00:00:00 2001 From: hpa Date: Wed, 28 Sep 2005 16:37:37 -0700 Subject: [PATCH 001/254] Options to compile on Cygwin --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 9920467d90..55b06f276b 100644 --- a/Makefile +++ b/Makefile @@ -172,6 +172,10 @@ ifeq ($(shell uname -s),SunOS) TAR = gtar PLATFORM_DEFINES += -D__EXTENSIONS__ endif +ifeq ($(shell uname -o),Cygwin) + NO_STRCASESTR = YesPlease + NEEDS_LIBICONV = YesPlease +endif ifneq (,$(findstring arm,$(shell uname -m))) ARM_SHA1 = YesPlease endif From 4c505f71e60b9d152a3a9d7a59b8b5146991a288 Mon Sep 17 00:00:00 2001 From: hpa Date: Wed, 28 Sep 2005 16:37:58 -0700 Subject: [PATCH 002/254] Cygwin doesn't support IPv6 or getaddrinfo() --- connect.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/connect.c b/connect.c index 825c439acc..0e6f27ea0a 100644 --- a/connect.c +++ b/connect.c @@ -290,6 +290,8 @@ static enum protocol get_protocol(const char *name) #define STR_(s) # s #define STR(s) STR_(s) +#ifndef __CYGWIN__ + static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path) { int sockfd = -1; @@ -346,6 +348,77 @@ static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path) return 0; } +#else /* __CYGWIN__ */ + +static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path) +{ + int sockfd = -1; + char *colon, *end; + char *port = STR(DEFAULT_GIT_PORT), *ep; + struct hostent *he; + struct sockaddr_in sa; + char **ap; + unsigned int nport; + + if (host[0] == '[') { + end = strchr(host + 1, ']'); + if (end) { + *end = 0; + end++; + host++; + } else + end = host; + } else + end = host; + colon = strchr(end, ':'); + + if (colon) { + *colon = 0; + port = colon + 1; + } + + + he = gethostbyname(host); + if (!he) + die("Unable to look up %s (%s)", host, hstrerror(h_errno)); + nport = strtoul(port, &ep, 10); + if ( ep == port || *ep ) { + /* Not numeric */ + struct servent *se = getservbyname(port,"tcp"); + if ( !se ) + die("Unknown port %s\n", port); + nport = se->s_port; + } + + for (ap = he->h_addr_list; *ap; ap++) { + sockfd = socket(he->h_addrtype, SOCK_STREAM, 0); + if (sockfd < 0) + continue; + + memset(&sa, 0, sizeof sa); + sa.sin_family = he->h_addrtype; + sa.sin_port = nport; + memcpy(&sa.sin_addr, ap, he->h_length); + + if (connect(sockfd, (struct sockaddr *)&sa, sizeof sa) < 0) { + close(sockfd); + sockfd = -1; + continue; + } + break; + } + + if (sockfd < 0) + die("unable to connect a socket (%s)", strerror(errno)); + + fd[0] = sockfd; + fd[1] = sockfd; + packet_write(sockfd, "%s %s\n", prog, path); + return 0; +} + +#endif /* __CYGWIN__ */ + /* * Yeah, yeah, fixme. Need to pass in the heads etc. */ From 49744d63e9c5ffdfb4677bd3aaeafb3371c3fdc1 Mon Sep 17 00:00:00 2001 From: hpa Date: Wed, 28 Sep 2005 16:52:21 -0700 Subject: [PATCH 003/254] Call it NO_IPV6 rather than hard-coding __CYGWIN__ --- Makefile | 12 +++++++++++- connect.c | 6 +++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 55b06f276b..be5c0a8605 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,8 @@ # # Define WITH_OWN_SUBPROCESS_PY if you want to use with python 2.3. # +# Define NO_IPV6 if you lack IPv6 support and getaddrinfo(). +# # Define COLLISION_CHECK below if you believe that SHA1's # 1461501637330902918203684832716283019655932542976 hashes do not give you # sufficient guarantee that no collisions between objects will ever happen. @@ -97,7 +99,11 @@ SCRIPT_PYTHON = \ # The ones that do not have to link with lcrypto nor lz. SIMPLE_PROGRAMS = \ git-get-tar-commit-id git-mailinfo git-mailsplit git-stripspace \ - git-daemon git-var + git-var +ifndef NO_IPV6 +# Not supported to IPv6-challenged platforms yet +SIMPLE_PROGRAMS += git-daemon +endif # ... and all the rest PROGRAMS = \ @@ -175,6 +181,7 @@ endif ifeq ($(shell uname -o),Cygwin) NO_STRCASESTR = YesPlease NEEDS_LIBICONV = YesPlease + NO_IPV6 = YesPlease endif ifneq (,$(findstring arm,$(shell uname -m))) ARM_SHA1 = YesPlease @@ -231,6 +238,9 @@ ifdef NO_STRCASESTR DEFINES += -Dstrcasestr=gitstrcasestr LIB_OBJS += compat/strcasestr.o endif +ifdef NO_IPV6 + DEFINES += -DNO_IPV6 +endif ifdef PPC_SHA1 SHA1_HEADER = "ppc/sha1.h" diff --git a/connect.c b/connect.c index 0e6f27ea0a..39d320ce28 100644 --- a/connect.c +++ b/connect.c @@ -290,7 +290,7 @@ static enum protocol get_protocol(const char *name) #define STR_(s) # s #define STR(s) STR_(s) -#ifndef __CYGWIN__ +#ifndef NO_IPV6 static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path) { @@ -348,7 +348,7 @@ static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path) return 0; } -#else /* __CYGWIN__ */ +#else /* NO_IPV6 */ static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path) { @@ -417,7 +417,7 @@ static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path) return 0; } -#endif /* __CYGWIN__ */ +#endif /* NO_IPV6 */ /* * Yeah, yeah, fixme. Need to pass in the heads etc. From 296fdc53bdd75147121aa290b4de0eeb3b4e7074 Mon Sep 17 00:00:00 2001 From: Peter Anvin Date: Wed, 28 Sep 2005 16:53:56 -0700 Subject: [PATCH 004/254] --- git.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/git.sh b/git.sh index 178d0f0c09..b67a1647e2 100755 --- a/git.sh +++ b/git.sh @@ -12,6 +12,7 @@ case "$#" in exit 0 ;; esac test -x $path/git-$cmd && exec $path/git-$cmd "$@" ;; + test -x $path/git-$cmd.exe && exec $path/git-$cmd.exe "$@" ;; esac echo "Usage: git COMMAND [OPTIONS] [TARGET]" From 918e723204651252e5a823481cc8450e498a45f9 Mon Sep 17 00:00:00 2001 From: Peter Anvin Date: Wed, 28 Sep 2005 16:56:08 -0700 Subject: [PATCH 005/254] For the benefit of Cygwin, test for git-cmd.exe --- git.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/git.sh b/git.sh index b67a1647e2..ea710aafc1 100755 --- a/git.sh +++ b/git.sh @@ -11,7 +11,10 @@ case "$#" in echo "git version @@GIT_VERSION@@" exit 0 ;; esac + test -x $path/git-$cmd && exec $path/git-$cmd "$@" ;; + + # In case we're running on Cygwin... test -x $path/git-$cmd.exe && exec $path/git-$cmd.exe "$@" ;; esac From 6573faff34eb002535843bbb59365be4ad58a120 Mon Sep 17 00:00:00 2001 From: Peter Anvin Date: Wed, 28 Sep 2005 17:26:44 -0700 Subject: [PATCH 006/254] NO_IPV6 support for git daemon --- Makefile | 2 +- connect.c | 2 +- daemon.c | 91 +++++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 77 insertions(+), 18 deletions(-) diff --git a/Makefile b/Makefile index be5c0a8605..2183903965 100644 --- a/Makefile +++ b/Makefile @@ -239,7 +239,7 @@ ifdef NO_STRCASESTR LIB_OBJS += compat/strcasestr.o endif ifdef NO_IPV6 - DEFINES += -DNO_IPV6 + DEFINES += -DNO_IPV6 -Dsockaddr_storage=sockaddr_in endif ifdef PPC_SHA1 diff --git a/connect.c b/connect.c index 39d320ce28..b157cf1cc7 100644 --- a/connect.c +++ b/connect.c @@ -397,7 +397,7 @@ static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path) memset(&sa, 0, sizeof sa); sa.sin_family = he->h_addrtype; - sa.sin_port = nport; + sa.sin_port = htons(nport); memcpy(&sa.sin_addr, ap, he->h_length); if (connect(sockfd, (struct sockaddr *)&sa, sizeof sa) < 0) { diff --git a/daemon.c b/daemon.c index a369ce527e..79e72e0bdd 100644 --- a/daemon.c +++ b/daemon.c @@ -1,9 +1,11 @@ #include "cache.h" #include "pkt-line.h" +#include #include #include #include #include +#include #include #include #include @@ -328,6 +330,7 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen) inet_ntop(AF_INET, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf)); port = sin_addr->sin_port; +#ifndef NO_IPV6 } else if (addr->sa_family == AF_INET6) { struct sockaddr_in6 *sin6_addr = (void *) addr; @@ -337,6 +340,7 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen) strcat(buf, "]"); port = sin6_addr->sin6_port; +#endif } loginfo("Connection from %s:%d", addrbuf, port); @@ -369,16 +373,17 @@ static void child_handler(int signo) } } -static int serve(int port) +#ifndef NO_IPV6 + +static int socksetup(int port, int **socklist_p) { - struct addrinfo hints, *ai0, *ai; - int gai; int socknum = 0, *socklist = NULL; int maxfd = -1; fd_set fds_init, fds; char pbuf[NI_MAXSERV]; - signal(SIGCHLD, child_handler); + struct addrinfo hints, *ai0, *ai; + int gai; sprintf(pbuf, "%d", port); memset(&hints, 0, sizeof(hints)); @@ -438,16 +443,59 @@ static int serve(int port) freeaddrinfo(ai0); - if (socknum == 0) - die("unable to allocate any listen sockets on port %u", port); + *socklist_p = socklist; + return socknum; +} + +#else /* NO_IPV6 */ + +static int socksetup(int port, int **socklist_p) +{ + struct sockaddr_in sin; + int sockfd; + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) + return 0; + + memset(&sin, 0, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(INADDR_ANY); + sin.sin_port = htons(port); + + if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) { + close(sockfd); + return 0; + } + *socklist_p = malloc(sizeof(int)); + if ( !*socklist_p ) + die("memory allocation failed: %s", strerror(errno)); + **socklist_p = sockfd; +} + +#endif + +static int service_loop(int socknum, int *socklist) +{ + struct pollfd *pfd; + int i; + + pfd = calloc(socknum, sizeof(struct pollfd)); + if (!pfd) + die("memory allocation failed: %s", strerror(errno)); + + for (i = 0; i < socknum; i++) { + pfd[i].fd = socklist[i]; + pfd[i].events = POLLIN; + } + for (;;) { int i; - fds = fds_init; - - if (select(maxfd + 1, &fds, NULL, NULL, NULL) < 0) { + + if (poll(pfd, socknum, 0) < 0) { if (errno != EINTR) { - error("select failed, resuming: %s", + error("poll failed, resuming: %s", strerror(errno)); sleep(1); } @@ -455,12 +503,10 @@ static int serve(int port) } for (i = 0; i < socknum; i++) { - int sockfd = socklist[i]; - - if (FD_ISSET(sockfd, &fds)) { + if (pfd[i].revents & POLLIN) { struct sockaddr_storage ss; int sslen = sizeof(ss); - int incoming = accept(sockfd, (struct sockaddr *)&ss, &sslen); + int incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen); if (incoming < 0) { switch (errno) { case EAGAIN: @@ -477,6 +523,19 @@ static int serve(int port) } } +static int serve(int port) +{ + int socknum, *socklist; + + signal(SIGCHLD, child_handler); + + socknum = socksetup(port, &socklist); + if (socknum == 0) + die("unable to allocate any listen sockets on port %u", port); + + return service_loop(socknum, socklist); +} + int main(int argc, char **argv) { int port = DEFAULT_GIT_PORT; @@ -526,7 +585,7 @@ int main(int argc, char **argv) if (inetd_mode) { fclose(stderr); //FIXME: workaround return execute(); + } else { + return serve(port); } - - return serve(port); } From dc4afa57ce3e07645690bec1e4c20ab59e8a9bd0 Mon Sep 17 00:00:00 2001 From: Peter Anvin Date: Wed, 28 Sep 2005 18:00:24 -0700 Subject: [PATCH 007/254] Remove *.exe for Cygwin's benefit --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 2183903965..7ae12d8823 100644 --- a/Makefile +++ b/Makefile @@ -395,7 +395,7 @@ deb: dist ### Cleaning rules clean: - rm -f *.o mozilla-sha1/*.o ppc/*.o compat/*.o $(PROGRAMS) $(LIB_FILE) + rm -f *.o *.exe mozilla-sha1/*.o ppc/*.o compat/*.o $(PROGRAMS) $(LIB_FILE) rm -f $(filter-out gitk,$(SCRIPTS)) rm -f git-core.spec *.pyc *.pyo rm -rf $(GIT_TARNAME) From e72456bb67bfcadf3703dc2f8240af7d9d8aebdb Mon Sep 17 00:00:00 2001 From: Peter Anvin Date: Wed, 28 Sep 2005 18:01:55 -0700 Subject: [PATCH 008/254] Remove variables not needed when using poll --- daemon.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/daemon.c b/daemon.c index 79e72e0bdd..526ac782cf 100644 --- a/daemon.c +++ b/daemon.c @@ -379,7 +379,6 @@ static int socksetup(int port, int **socklist_p) { int socknum = 0, *socklist = NULL; int maxfd = -1; - fd_set fds_init, fds; char pbuf[NI_MAXSERV]; struct addrinfo hints, *ai0, *ai; @@ -396,8 +395,6 @@ static int socksetup(int port, int **socklist_p) if (gai) die("getaddrinfo() failed: %s\n", gai_strerror(gai)); - FD_ZERO(&fds_init); - for (ai = ai0; ai; ai = ai->ai_next) { int sockfd; int *newlist; @@ -436,7 +433,6 @@ static int socksetup(int port, int **socklist_p) socklist = newlist; socklist[socknum++] = sockfd; - FD_SET(sockfd, &fds_init); if (maxfd < sockfd) maxfd = sockfd; } From a23cd8ece70262fac2a80ef3e454c1cf1c63605a Mon Sep 17 00:00:00 2001 From: Peter Anvin Date: Wed, 28 Sep 2005 19:08:37 -0700 Subject: [PATCH 009/254] Handle Cygwin .exe extensions --- Makefile | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/Makefile b/Makefile index 7ae12d8823..ff12fbf099 100644 --- a/Makefile +++ b/Makefile @@ -99,11 +99,7 @@ SCRIPT_PYTHON = \ # The ones that do not have to link with lcrypto nor lz. SIMPLE_PROGRAMS = \ git-get-tar-commit-id git-mailinfo git-mailsplit git-stripspace \ - git-var -ifndef NO_IPV6 -# Not supported to IPv6-challenged platforms yet -SIMPLE_PROGRAMS += git-daemon -endif + git-var git-daemon # ... and all the rest PROGRAMS = \ @@ -182,6 +178,7 @@ ifeq ($(shell uname -o),Cygwin) NO_STRCASESTR = YesPlease NEEDS_LIBICONV = YesPlease NO_IPV6 = YesPlease + X = .exe endif ifneq (,$(findstring arm,$(shell uname -m))) ARM_SHA1 = YesPlease @@ -267,10 +264,13 @@ SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ $(patsubst %.py,%,$(SCRIPT_PYTHON)) \ gitk +PROGRAMS_X = $(patsubst %,%$(X),$(PROGRAMS)) +SIMPLE_PROGRAMS_X = $(patsubst %,%$(X),$(SIMPLE_PROGRAMS)) + export TAR INSTALL DESTDIR SHELL_PATH ### Build rules -all: $(PROGRAMS) $(SCRIPTS) +all: $(PROGRAMS_X) $(SCRIPTS) all: $(MAKE) -C templates @@ -304,30 +304,30 @@ $(patsubst %.py,%,$(SCRIPT_PYTHON)) : % : %.py %.o: %.S $(CC) -o $*.o -c $(ALL_CFLAGS) $< -git-%: %.o $(LIB_FILE) +git-%$(X): %.o $(LIB_FILE) $(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^) $(LIBS) -git-mailinfo : SIMPLE_LIB += $(LIB_4_ICONV) -$(SIMPLE_PROGRAMS) : $(LIB_FILE) -$(SIMPLE_PROGRAMS) : git-% : %.o +git-mailinfo$(X) : SIMPLE_LIB += $(LIB_4_ICONV) +$(SIMPLE_PROGRAMS_X) : $(LIB_FILE) +$(SIMPLE_PROGRAMS_X) : git-%$(X) : %.o $(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^) $(LIB_FILE) $(SIMPLE_LIB) -git-http-fetch: fetch.o -git-local-fetch: fetch.o -git-ssh-fetch: rsh.o fetch.o -git-ssh-upload: rsh.o -git-ssh-pull: rsh.o fetch.o -git-ssh-push: rsh.o +git-http-fetch$(X): fetch.o +git-local-fetch$(X): fetch.o +git-ssh-fetch$(X): rsh.o fetch.o +git-ssh-upload$(X): rsh.o +git-ssh-pull$(X): rsh.o fetch.o +git-ssh-push$(X): rsh.o -git-http-fetch: LIBS += $(CURL_LIBCURL) -git-rev-list: LIBS += $(OPENSSL_LIBSSL) +git-http-fetch$(X): LIBS += $(CURL_LIBCURL) +git-rev-list$(X): LIBS += $(OPENSSL_LIBSSL) init-db.o: init-db.c $(CC) -c $(ALL_CFLAGS) \ -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir)"' $*.c $(LIB_OBJS): $(LIB_H) -$(patsubst git-%,%.o,$(PROGRAMS)): $(LIB_H) +$(patsubst git-%$(X),%.o,$(PROGRAMS_X)): $(LIB_H) $(DIFF_OBJS): diffcore.h $(LIB_FILE): $(LIB_OBJS) @@ -342,10 +342,10 @@ doc: test: all $(MAKE) -C t/ all -test-date: test-date.c date.o +test-date$(X): test-date.c date.o $(CC) $(ALL_CFLAGS) -o $@ test-date.c date.o -test-delta: test-delta.c diff-delta.o patch-delta.o +test-delta$(X): test-delta.c diff-delta.o patch-delta.o $(CC) $(ALL_CFLAGS) -o $@ $^ check: @@ -355,9 +355,9 @@ check: ### Installation rules -install: $(PROGRAMS) $(SCRIPTS) +install: $(PROGRAMS_X) $(SCRIPTS) $(INSTALL) -d -m755 $(DESTDIR)$(bindir) - $(INSTALL) $(PROGRAMS) $(SCRIPTS) $(DESTDIR)$(bindir) + $(INSTALL) $(PROGRAMS_X) $(SCRIPTS) $(DESTDIR)$(bindir) $(INSTALL) git-revert $(DESTDIR)$(bindir)/git-cherry-pick $(MAKE) -C templates install $(INSTALL) -d -m755 $(DESTDIR)$(GIT_PYTHON_DIR) @@ -395,7 +395,7 @@ deb: dist ### Cleaning rules clean: - rm -f *.o *.exe mozilla-sha1/*.o ppc/*.o compat/*.o $(PROGRAMS) $(LIB_FILE) + rm -f *.o mozilla-sha1/*.o ppc/*.o compat/*.o $(PROGRAMS_X) $(LIB_FILE) rm -f $(filter-out gitk,$(SCRIPTS)) rm -f git-core.spec *.pyc *.pyo rm -rf $(GIT_TARNAME) From 11b1a5db4f8d5750781d8ed9a1ae539b28267370 Mon Sep 17 00:00:00 2001 From: Peter Anvin Date: Wed, 28 Sep 2005 23:22:02 -0700 Subject: [PATCH 010/254] Ignore *.exe files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c3eb9543ff..b99a37e9ba 100644 --- a/.gitignore +++ b/.gitignore @@ -100,3 +100,4 @@ git-core-*/?* *.dsc *.deb git-core.spec +*.exe From bb8c91d617e8a2ab4a78712086d1574da6e24e68 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 28 Sep 2005 23:31:18 -0700 Subject: [PATCH 011/254] Just explicitly add $(X) to most programs. --- Makefile | 55 +++++++++++++++++++++++++------------------------------ 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/Makefile b/Makefile index ff12fbf099..97b584b419 100644 --- a/Makefile +++ b/Makefile @@ -98,31 +98,29 @@ SCRIPT_PYTHON = \ # The ones that do not have to link with lcrypto nor lz. SIMPLE_PROGRAMS = \ - git-get-tar-commit-id git-mailinfo git-mailsplit git-stripspace \ - git-var git-daemon + git-get-tar-commit-id$(X) git-mailinfo$(X) git-mailsplit$(X) \ + git-stripspace$(X) git-var$(X) git-daemon$(X) # ... and all the rest PROGRAMS = \ - git-apply git-cat-file \ - git-checkout-index git-clone-pack git-commit-tree \ - git-convert-objects git-diff-files \ - git-diff-index git-diff-stages \ - git-diff-tree git-fetch-pack git-fsck-objects \ - git-hash-object git-init-db \ - git-local-fetch git-ls-files git-ls-tree git-merge-base \ - git-merge-index git-mktag git-pack-objects git-patch-id \ - git-peek-remote git-prune-packed git-read-tree \ - git-receive-pack git-rev-list git-rev-parse \ - git-send-pack git-show-branch \ - git-show-index git-ssh-fetch \ - git-ssh-upload git-tar-tree git-unpack-file \ - git-unpack-objects git-update-index git-update-server-info \ - git-upload-pack git-verify-pack git-write-tree \ - git-update-ref \ - $(SIMPLE_PROGRAMS) + git-apply$(X) git-cat-file$(X) git-checkout-index$(X) \ + git-clone-pack$(X) git-commit-tree$(X) git-convert-objects$(X) \ + git-diff-files$(X) git-diff-index$(X) git-diff-stages$(X) \ + git-diff-tree$(X) git-fetch-pack$(X) git-fsck-objects$(X) \ + git-hash-object$(X) git-init-db$(X) git-local-fetch$(X) \ + git-ls-files$(X) git-ls-tree$(X) git-merge-base$(X) \ + git-merge-index$(X) git-mktag$(X) git-pack-objects$(X) \ + git-patch-id$(X) git-peek-remote$(X) git-prune-packed$(X) \ + git-read-tree$(X) git-receive-pack$(X) git-rev-list$(X) \ + git-rev-parse$(X) git-send-pack$(X) git-show-branch$(X) \ + git-show-index$(X) git-ssh-fetch$(X) git-ssh-upload$(X) \ + git-tar-tree$(X) git-unpack-file$(X) git-unpack-objects$(X) \ + git-update-index$(X) git-update-server-info$(X) \ + git-upload-pack$(X) git-verify-pack$(X) git-write-tree$(X) \ + git-update-ref$(X) $(SIMPLE_PROGRAMS) # Backward compatibility -- to be removed in 0.99.8 -PROGRAMS += git-ssh-pull git-ssh-push +PROGRAMS += git-ssh-pull$(X) git-ssh-push$(X) PYMODULES = \ gitMergeCommon.py @@ -264,13 +262,10 @@ SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ $(patsubst %.py,%,$(SCRIPT_PYTHON)) \ gitk -PROGRAMS_X = $(patsubst %,%$(X),$(PROGRAMS)) -SIMPLE_PROGRAMS_X = $(patsubst %,%$(X),$(SIMPLE_PROGRAMS)) - export TAR INSTALL DESTDIR SHELL_PATH ### Build rules -all: $(PROGRAMS_X) $(SCRIPTS) +all: $(PROGRAMS) $(SCRIPTS) all: $(MAKE) -C templates @@ -308,8 +303,8 @@ git-%$(X): %.o $(LIB_FILE) $(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^) $(LIBS) git-mailinfo$(X) : SIMPLE_LIB += $(LIB_4_ICONV) -$(SIMPLE_PROGRAMS_X) : $(LIB_FILE) -$(SIMPLE_PROGRAMS_X) : git-%$(X) : %.o +$(SIMPLE_PROGRAMS) : $(LIB_FILE) +$(SIMPLE_PROGRAMS) : git-%$(X) : %.o $(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^) $(LIB_FILE) $(SIMPLE_LIB) git-http-fetch$(X): fetch.o @@ -327,7 +322,7 @@ init-db.o: init-db.c -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir)"' $*.c $(LIB_OBJS): $(LIB_H) -$(patsubst git-%$(X),%.o,$(PROGRAMS_X)): $(LIB_H) +$(patsubst git-%$(X),%.o,$(PROGRAMS)): $(LIB_H) $(DIFF_OBJS): diffcore.h $(LIB_FILE): $(LIB_OBJS) @@ -355,9 +350,9 @@ check: ### Installation rules -install: $(PROGRAMS_X) $(SCRIPTS) +install: $(PROGRAMS) $(SCRIPTS) $(INSTALL) -d -m755 $(DESTDIR)$(bindir) - $(INSTALL) $(PROGRAMS_X) $(SCRIPTS) $(DESTDIR)$(bindir) + $(INSTALL) $(PROGRAMS) $(SCRIPTS) $(DESTDIR)$(bindir) $(INSTALL) git-revert $(DESTDIR)$(bindir)/git-cherry-pick $(MAKE) -C templates install $(INSTALL) -d -m755 $(DESTDIR)$(GIT_PYTHON_DIR) @@ -395,7 +390,7 @@ deb: dist ### Cleaning rules clean: - rm -f *.o mozilla-sha1/*.o ppc/*.o compat/*.o $(PROGRAMS_X) $(LIB_FILE) + rm -f *.o mozilla-sha1/*.o ppc/*.o compat/*.o $(PROGRAMS) $(LIB_FILE) rm -f $(filter-out gitk,$(SCRIPTS)) rm -f git-core.spec *.pyc *.pyo rm -rf $(GIT_TARNAME) From fef1ef8e1b87f28f019bf973547644e41f4be7cd Mon Sep 17 00:00:00 2001 From: hpa Date: Thu, 29 Sep 2005 10:38:26 -0700 Subject: [PATCH 012/254] git-http-fetch needs $(X) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 97b584b419..1f4f31b53b 100644 --- a/Makefile +++ b/Makefile @@ -190,7 +190,7 @@ ifndef NO_CURL else CURL_LIBCURL = -lcurl endif - PROGRAMS += git-http-fetch + PROGRAMS += git-http-fetch$(X) endif ifndef SHELL_PATH From 2f29dd521832540450610893319561a5a136b3fb Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 30 Sep 2005 10:46:25 -0700 Subject: [PATCH 013/254] Change $(X) -> $X to be less annoying. --- Makefile | 66 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/Makefile b/Makefile index 8b152dd558..e5b8a51afe 100644 --- a/Makefile +++ b/Makefile @@ -98,29 +98,29 @@ SCRIPT_PYTHON = \ # The ones that do not have to link with lcrypto nor lz. SIMPLE_PROGRAMS = \ - git-get-tar-commit-id$(X) git-mailinfo$(X) git-mailsplit$(X) \ - git-stripspace$(X) git-var$(X) git-daemon$(X) + git-get-tar-commit-id$X git-mailinfo$X git-mailsplit$X \ + git-stripspace$X git-var$X git-daemon$X # ... and all the rest PROGRAMS = \ - git-apply$(X) git-cat-file$(X) git-checkout-index$(X) \ - git-clone-pack$(X) git-commit-tree$(X) git-convert-objects$(X) \ - git-diff-files$(X) git-diff-index$(X) git-diff-stages$(X) \ - git-diff-tree$(X) git-fetch-pack$(X) git-fsck-objects$(X) \ - git-hash-object$(X) git-init-db$(X) git-local-fetch$(X) \ - git-ls-files$(X) git-ls-tree$(X) git-merge-base$(X) \ - git-merge-index$(X) git-mktag$(X) git-pack-objects$(X) \ - git-patch-id$(X) git-peek-remote$(X) git-prune-packed$(X) \ - git-read-tree$(X) git-receive-pack$(X) git-rev-list$(X) \ - git-rev-parse$(X) git-send-pack$(X) git-show-branch$(X) \ - git-show-index$(X) git-ssh-fetch$(X) git-ssh-upload$(X) \ - git-tar-tree$(X) git-unpack-file$(X) git-unpack-objects$(X) \ - git-update-index$(X) git-update-server-info$(X) \ - git-upload-pack$(X) git-verify-pack$(X) git-write-tree$(X) \ - git-update-ref$(X) $(SIMPLE_PROGRAMS) + git-apply$X git-cat-file$X git-checkout-index$X \ + git-clone-pack$X git-commit-tree$X git-convert-objects$X \ + git-diff-files$X git-diff-index$X git-diff-stages$X \ + git-diff-tree$X git-fetch-pack$X git-fsck-objects$X \ + git-hash-object$X git-init-db$X git-local-fetch$X \ + git-ls-files$X git-ls-tree$X git-merge-base$X \ + git-merge-index$X git-mktag$X git-pack-objects$X \ + git-patch-id$X git-peek-remote$X git-prune-packed$X \ + git-read-tree$X git-receive-pack$X git-rev-list$X \ + git-rev-parse$X git-send-pack$X git-show-branch$X \ + git-show-index$X git-ssh-fetch$X git-ssh-upload$X \ + git-tar-tree$X git-unpack-file$X git-unpack-objects$X \ + git-update-index$X git-update-server-info$X \ + git-upload-pack$X git-verify-pack$X git-write-tree$X \ + git-update-ref$X $(SIMPLE_PROGRAMS) # Backward compatibility -- to be removed after 1.0 -PROGRAMS += git-ssh-pull$(X) git-ssh-push$(X) +PROGRAMS += git-ssh-pull$X git-ssh-push$X PYMODULES = \ gitMergeCommon.py @@ -190,7 +190,7 @@ ifndef NO_CURL else CURL_LIBCURL = -lcurl endif - PROGRAMS += git-http-fetch$(X) + PROGRAMS += git-http-fetch$X endif ifndef SHELL_PATH @@ -299,30 +299,30 @@ $(patsubst %.py,%,$(SCRIPT_PYTHON)) : % : %.py %.o: %.S $(CC) -o $*.o -c $(ALL_CFLAGS) $< -git-%$(X): %.o $(LIB_FILE) +git-%$X: %.o $(LIB_FILE) $(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^) $(LIBS) -git-mailinfo$(X) : SIMPLE_LIB += $(LIB_4_ICONV) +git-mailinfo$X : SIMPLE_LIB += $(LIB_4_ICONV) $(SIMPLE_PROGRAMS) : $(LIB_FILE) -$(SIMPLE_PROGRAMS) : git-%$(X) : %.o +$(SIMPLE_PROGRAMS) : git-%$X : %.o $(CC) $(ALL_CFLAGS) -o $@ $(filter %.o,$^) $(LIB_FILE) $(SIMPLE_LIB) -git-http-fetch$(X): fetch.o -git-local-fetch$(X): fetch.o -git-ssh-fetch$(X): rsh.o fetch.o -git-ssh-upload$(X): rsh.o -git-ssh-pull$(X): rsh.o fetch.o -git-ssh-push$(X): rsh.o +git-http-fetch$X: fetch.o +git-local-fetch$X: fetch.o +git-ssh-fetch$X: rsh.o fetch.o +git-ssh-upload$X: rsh.o +git-ssh-pull$X: rsh.o fetch.o +git-ssh-push$X: rsh.o -git-http-fetch$(X): LIBS += $(CURL_LIBCURL) -git-rev-list$(X): LIBS += $(OPENSSL_LIBSSL) +git-http-fetch$X: LIBS += $(CURL_LIBCURL) +git-rev-list$X: LIBS += $(OPENSSL_LIBSSL) init-db.o: init-db.c $(CC) -c $(ALL_CFLAGS) \ -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir)"' $*.c $(LIB_OBJS): $(LIB_H) -$(patsubst git-%$(X),%.o,$(PROGRAMS)): $(LIB_H) +$(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(DIFF_OBJS): diffcore.h $(LIB_FILE): $(LIB_OBJS) @@ -337,10 +337,10 @@ doc: test: all $(MAKE) -C t/ all -test-date$(X): test-date.c date.o +test-date$X: test-date.c date.o $(CC) $(ALL_CFLAGS) -o $@ test-date.c date.o -test-delta$(X): test-delta.c diff-delta.o patch-delta.o +test-delta$X: test-delta.c diff-delta.o patch-delta.o $(CC) $(ALL_CFLAGS) -o $@ $^ check: From d6b89e7bf882648c23bd7fd4598696087487329d Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 30 Sep 2005 10:46:42 -0700 Subject: [PATCH 014/254] Don't need --- daemon.c | 1 - 1 file changed, 1 deletion(-) diff --git a/daemon.c b/daemon.c index 8366a33bcb..b6006c7829 100644 --- a/daemon.c +++ b/daemon.c @@ -1,6 +1,5 @@ #include "cache.h" #include "pkt-line.h" -#include #include #include #include From 1b4713fb9e6ec614e8dbca90b1a57d5ffa2f3fde Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 30 Sep 2005 10:47:50 -0700 Subject: [PATCH 015/254] Use xmalloc/xcalloc --- daemon.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/daemon.c b/daemon.c index b6006c7829..6298f53fcf 100644 --- a/daemon.c +++ b/daemon.c @@ -463,9 +463,7 @@ static int socksetup(int port, int **socklist_p) return 0; } - *socklist_p = malloc(sizeof(int)); - if ( !*socklist_p ) - die("memory allocation failed: %s", strerror(errno)); + *socklist_p = xmalloc(sizeof(int)); **socklist_p = sockfd; } @@ -476,9 +474,7 @@ static int service_loop(int socknum, int *socklist) struct pollfd *pfd; int i; - pfd = calloc(socknum, sizeof(struct pollfd)); - if (!pfd) - die("memory allocation failed: %s", strerror(errno)); + pfd = xcalloc(socknum, sizeof(struct pollfd)); for (i = 0; i < socknum; i++) { pfd[i].fd = socklist[i]; From 7626e49e9f04ac386965d16ae11e130e20ebd518 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 30 Sep 2005 10:48:21 -0700 Subject: [PATCH 016/254] socklen_t is unsigned int on most Linux platforms --- daemon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon.c b/daemon.c index 6298f53fcf..fc5e1c3037 100644 --- a/daemon.c +++ b/daemon.c @@ -496,7 +496,7 @@ static int service_loop(int socknum, int *socklist) for (i = 0; i < socknum; i++) { if (pfd[i].revents & POLLIN) { struct sockaddr_storage ss; - int sslen = sizeof(ss); + unsigned int sslen = sizeof(ss); int incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen); if (incoming < 0) { switch (errno) { From 9220282a9c6fae98d326bd10e4f427f1692b71ed Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 30 Sep 2005 11:01:57 -0700 Subject: [PATCH 017/254] Move signal setting into service_loop() --- daemon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/daemon.c b/daemon.c index fc5e1c3037..f285a8c98c 100644 --- a/daemon.c +++ b/daemon.c @@ -480,6 +480,8 @@ static int service_loop(int socknum, int *socklist) pfd[i].fd = socklist[i]; pfd[i].events = POLLIN; } + + signal(SIGCHLD, child_handler); for (;;) { int i; @@ -518,8 +520,6 @@ static int serve(int port) { int socknum, *socklist; - signal(SIGCHLD, child_handler); - socknum = socksetup(port, &socklist); if (socknum == 0) die("unable to allocate any listen sockets on port %u", port); From 039c6f162a63e9d91f360e2e6138e21a4015c543 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 30 Sep 2005 11:02:26 -0700 Subject: [PATCH 018/254] Better handling of exec extension in the git wrapper script --- Makefile | 3 ++- git.sh | 16 +++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index e5b8a51afe..38330c2e90 100644 --- a/Makefile +++ b/Makefile @@ -273,7 +273,8 @@ all: git: git.sh Makefile rm -f $@+ $@ sed -e '1s|#!.*/sh|#!$(SHELL_PATH)|' \ - -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' <$@.sh >$@+ + -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ + -e 's/@@X@@/$(X)/g' <$@.sh >$@+ chmod +x $@+ mv $@+ $@ diff --git a/git.sh b/git.sh index ea710aafc1..2986f08ce2 100755 --- a/git.sh +++ b/git.sh @@ -11,11 +11,17 @@ case "$#" in echo "git version @@GIT_VERSION@@" exit 0 ;; esac - - test -x $path/git-$cmd && exec $path/git-$cmd "$@" ;; - - # In case we're running on Cygwin... - test -x $path/git-$cmd.exe && exec $path/git-$cmd.exe "$@" ;; + + test -x $path/git-$cmd && exec $path/git-$cmd "$@" + + case '@@X@@' in + '') + ;; + *) + test -x $path/git-$cmd@@X@@ && exec $path/git-$cmd@@X@@ "$@" + ;; + esac + ;; esac echo "Usage: git COMMAND [OPTIONS] [TARGET]" From baaac6a7143ad07de62926421f8740cd640c241c Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 2 Oct 2005 16:37:27 -0700 Subject: [PATCH 019/254] Post 0.99.8 master branch Signed-off-by: Junio C Hamano --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 92f0bda5e7..25fd5cde86 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ # DEFINES += -DUSE_STDEV -GIT_VERSION = 0.99.8 +GIT_VERSION = 0.99.8.GIT CFLAGS = -g -O2 -Wall ALL_CFLAGS = $(CFLAGS) $(PLATFORM_DEFINES) $(DEFINES) From c8c5b21a3714db3272f869c82f3ce862ed9c2cc6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 3 Oct 2005 16:05:50 -0700 Subject: [PATCH 020/254] [PATCH] Merging the Cygwin changes Fix mismerge typo. Signed-off-by: Junio C Hamano --- Makefile | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 4ea6d9a71b..133808c82f 100644 --- a/Makefile +++ b/Makefile @@ -297,13 +297,9 @@ all: git: git.sh Makefile rm -f $@+ $@ sed -e '1s|#!.*/sh|#!$(SHELL_PATH)|' \ -<<<<<<< Makefile - -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ - -e 's/@@X@@/$(X)/g' <$@.sh >$@+ -======= -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ + -e 's/@@X@@/$(X)/g' \ $(GIT_LIST_TWEAK) <$@.sh >$@+ ->>>>>>> .merge_file_3QHyD4 chmod +x $@+ mv $@+ $@ From 4514385edd913f6c10fa03c828effc5ba974369e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 3 Oct 2005 19:05:01 -0700 Subject: [PATCH 021/254] On Cygwin, use symbolic ref, not a symbolic link, to express .git/HEAD H. Peter Anvin says that Samba "promotes" symlinks to hardlinks while Cygwin itself uses .lnk files to emulate symlinks. Avoid using symbolic link for .git/HEAD on Cygwin. This does not help the symlinks recorded in trees as user data, but at least we do not use them for our own bookkeeping. Signed-off-by: Junio C Hamano --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 133808c82f..0d3c27793e 100644 --- a/Makefile +++ b/Makefile @@ -183,6 +183,7 @@ ifeq ($(shell uname -o),Cygwin) NEEDS_LIBICONV = YesPlease NO_IPV6 = YesPlease X = .exe + PLATFORM_DEFINES += -DUSE_SYMLINK_HEAD=0 endif ifneq (,$(findstring arm,$(shell uname -m))) ARM_SHA1 = YesPlease From 4b12dae69a41471e7c8139de26c1135f7ecccbd8 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 3 Oct 2005 12:44:48 -0700 Subject: [PATCH 022/254] Return error when not checking out an entry due to dirtiness. Without -f flag, 'git-checkout-index foo.c' issued an error message when foo.c already existed in the working tree and did not match index. However it did not return an error from the underlying checkout_entry() function and resulted in a successful exit(0). Signed-off-by: Junio C Hamano --- checkout-index.c | 9 +++++++-- entry.c | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/checkout-index.c b/checkout-index.c index f32513c507..97845324be 100644 --- a/checkout-index.c +++ b/checkout-index.c @@ -63,15 +63,20 @@ static int checkout_file(const char *name) static int checkout_all(void) { - int i; + int i, errs = 0; for (i = 0; i < active_nr ; i++) { struct cache_entry *ce = active_cache[i]; if (ce_stage(ce)) continue; if (checkout_entry(ce, &state) < 0) - return -1; + errs++; } + if (errs) + /* we have already done our error reporting. + * exit with the same code as die(). + */ + exit(128); return 0; } diff --git a/entry.c b/entry.c index b8426dbd0d..15b34eb6f9 100644 --- a/entry.c +++ b/entry.c @@ -132,7 +132,7 @@ int checkout_entry(struct cache_entry *ce, struct checkout *state) if (!state->force) { if (!state->quiet) fprintf(stderr, "git-checkout-index: %s already exists\n", path); - return 0; + return -1; } /* From 56d33b1105e63590577672de9afb920f6e7fd22c Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 3 Oct 2005 13:16:39 -0700 Subject: [PATCH 023/254] git-apply: allow operating in sparsely populated working tree. This patch teaches 'git-apply --index' to automatically check out a file being patched. This happens only when the working tree does not have it checked out. Signed-off-by: Junio C Hamano --- apply.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/apply.c b/apply.c index f8862722fd..79c5d8a8f8 100644 --- a/apply.c +++ b/apply.c @@ -676,7 +676,10 @@ static int parse_fragment(char *line, unsigned long size, struct patch *patch, s /* We allow "\ No newline at end of file". Depending * on locale settings when the patch was produced we * don't know what this line looks like. The only - * thing we do know is that it begins with "\ ". */ + * thing we do know is that it begins with "\ ". + * Checking for 12 is just for sanity check -- any + * l10n of "\ No newline..." is at least that long. + */ case '\\': if (len < 12 || memcmp(line, "\\ ", 2)) return -1; @@ -1030,17 +1033,39 @@ static int check_patch(struct patch *patch) if (old_name) { int changed; + int stat_ret = lstat(old_name, &st); - if (lstat(old_name, &st) < 0) - return error("%s: %s", old_name, strerror(errno)); if (check_index) { int pos = cache_name_pos(old_name, strlen(old_name)); if (pos < 0) - return error("%s: does not exist in index", old_name); + return error("%s: does not exist in index", + old_name); + if (stat_ret < 0) { + struct checkout costate; + if (errno != ENOENT) + return error("%s: %s", old_name, + strerror(errno)); + /* checkout */ + costate.base_dir = ""; + costate.base_dir_len = 0; + costate.force = 0; + costate.quiet = 0; + costate.not_new = 0; + costate.refresh_cache = 1; + if (checkout_entry(active_cache[pos], + &costate) || + lstat(old_name, &st)) + return -1; + } + changed = ce_match_stat(active_cache[pos], &st); if (changed) - return error("%s: does not match index", old_name); + return error("%s: does not match index", + old_name); } + else if (stat_ret < 0) + return error("%s: %s", old_name, strerror(errno)); + if (patch->is_new < 0) patch->is_new = 0; st.st_mode = ntohl(create_ce_mode(st.st_mode)); From c2d5036de5c2e21fb736002ae5b385ceb7c6b23b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 3 Oct 2005 22:28:45 -0700 Subject: [PATCH 024/254] git-apply: retire unused/unimplemented --no-merge flag. The original plan was to do 3-way merge between local working tree, index and the patch being applied, but that was never implemented. Retire the flag to control its behaviour. Signed-off-by: Junio C Hamano --- Documentation/git-apply.txt | 7 +------ apply.c | 17 +---------------- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt index 4f7e1195de..cb676348f8 100644 --- a/Documentation/git-apply.txt +++ b/Documentation/git-apply.txt @@ -9,7 +9,7 @@ git-apply - Apply patch on a GIT index file and a work tree SYNOPSIS -------- -'git-apply' [--no-merge] [--stat] [--summary] [--check] [--index] [--show-files] [--apply] [...] +'git-apply' [--stat] [--summary] [--check] [--index] [--show-files] [--apply] [...] DESCRIPTION ----------- @@ -22,11 +22,6 @@ OPTIONS The files to read patch from. '-' can be used to read from the standard input. ---no-merge:: - The default mode of operation is the merge behaviour - which is not implemented yet. This flag explicitly - tells the program not to use the merge behaviour. - --stat:: Instead of applying the patch, output diffstat for the input. Turns off "apply". diff --git a/apply.c b/apply.c index 79c5d8a8f8..7be5041353 100644 --- a/apply.c +++ b/apply.c @@ -5,26 +5,16 @@ * * This applies patches on top of some (arbitrary) version of the SCM. * - * NOTE! It does all its work in the index file, and only cares about - * the files in the working directory if you tell it to "merge" the - * patch apply. - * - * Even when merging it always takes the source from the index, and - * uses the working tree as a "branch" for a 3-way merge. */ #include #include #include "cache.h" -// We default to the merge behaviour, since that's what most people would -// expect. -// // --check turns on checking that the working tree matches the // files that are being modified, but doesn't apply the patch // --stat does just a diffstat, and doesn't actually apply // --show-files shows the directory changes // -static int merge_patch = 1; static int check_index = 0; static int write_index = 0; static int diffstat = 0; @@ -33,7 +23,7 @@ static int check = 0; static int apply = 1; static int show_files = 0; static const char apply_usage[] = -"git-apply [--no-merge] [--stat] [--summary] [--check] [--index] [--apply] [--show-files] ..."; +"git-apply [--stat] [--summary] [--check] [--index] [--apply] [--show-files] ..."; /* * For "diff-stat" like behaviour, we keep track of the biggest change @@ -1517,11 +1507,6 @@ int main(int argc, char **argv) excludes = x; continue; } - /* NEEDSWORK: this does not do anything at this moment. */ - if (!strcmp(arg, "--no-merge")) { - merge_patch = 0; - continue; - } if (!strcmp(arg, "--stat")) { apply = 0; diffstat = 1; From a567d3154ec05dd991abf50389eacc36bfc25965 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 4 Oct 2005 01:11:27 -0700 Subject: [PATCH 025/254] git-applypatch: cleanup. - Defined variable $INFO was not used properly. - Make sure there is an empty line between the sign-off and the log message. Signed-off-by: Junio C Hamano --- git-applypatch.sh | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/git-applypatch.sh b/git-applypatch.sh index 9f5a45bb2b..14635d9bce 100755 --- a/git-applypatch.sh +++ b/git-applypatch.sh @@ -29,10 +29,10 @@ INFO=$3 SIGNOFF=$4 EDIT=${VISUAL:-${EDITOR:-vi}} -export GIT_AUTHOR_NAME="$(sed -n '/^Author/ s/Author: //p' .dotest/info)" -export GIT_AUTHOR_EMAIL="$(sed -n '/^Email/ s/Email: //p' .dotest/info)" -export GIT_AUTHOR_DATE="$(sed -n '/^Date/ s/Date: //p' .dotest/info)" -export SUBJECT="$(sed -n '/^Subject/ s/Subject: //p' .dotest/info)" +export GIT_AUTHOR_NAME="$(sed -n '/^Author/ s/Author: //p' "$INFO")" +export GIT_AUTHOR_EMAIL="$(sed -n '/^Email/ s/Email: //p' "$INFO")" +export GIT_AUTHOR_DATE="$(sed -n '/^Date/ s/Date: //p' "$INFO")" +export SUBJECT="$(sed -n '/^Subject/ s/Subject: //p' "$INFO")" if test '' != "$SIGNOFF" then @@ -54,8 +54,10 @@ then sed -ne '/^Signed-off-by: /p' "$MSGFILE" | tail -n 1 ` - test "$LAST_SIGNED_OFF_BY" = "$SIGNOFF" || - echo "$SIGNOFF" >>"$MSGFILE" + test "$LAST_SIGNED_OFF_BY" = "$SIGNOFF" || { + test '' = "$LAST_SIGNED_OFF_BY" && echo + echo "$SIGNOFF" + } >>"$MSGFILE" fi fi @@ -99,7 +101,12 @@ echo echo Applying "'$SUBJECT'" echo -git-apply --index "$PATCHFILE" || exit 1 +git-apply --index "$PATCHFILE" || { + # Here if we know which revision the patch applies to, + # we create a temporary working tree and index, apply the + # patch, and attempt 3-way merge with the resulting tree. + exit 1 +} if test -x "$GIT_DIR"/hooks/pre-applypatch then From 3ff8cbeda635422f4740d325d56288dfdea10179 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 4 Oct 2005 12:41:35 -0700 Subject: [PATCH 026/254] Record which tree the patch applies to. Also note which version of GIT produced the patch. Signed-off-by: Junio C Hamano --- Makefile | 11 ++++++++--- git-format-patch.sh | 3 +++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 0d3c27793e..fd4e163bad 100644 --- a/Makefile +++ b/Makefile @@ -306,19 +306,24 @@ git: git.sh Makefile $(filter-out git,$(patsubst %.sh,%,$(SCRIPT_SH))) : % : %.sh rm -f $@ - sed -e '1s|#!.*/sh|#!$(SHELL_PATH)|' $@.sh >$@ + sed -e '1s|#!.*/sh|#!$(SHELL_PATH)|' \ + -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ + $@.sh >$@ chmod +x $@ $(patsubst %.perl,%,$(SCRIPT_PERL)) : % : %.perl rm -f $@ - sed -e '1s|#!.*perl|#!$(PERL_PATH)|' $@.perl >$@ + sed -e '1s|#!.*perl|#!$(PERL_PATH)|' \ + -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ + $@.perl >$@ chmod +x $@ $(patsubst %.py,%,$(SCRIPT_PYTHON)) : % : %.py rm -f $@ sed -e '1s|#!.*python|#!$(PYTHON_PATH)|' \ -e 's|@@GIT_PYTHON_PATH@@|$(GIT_PYTHON_DIR)|g' \ - $@.py >$@ + -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ + $@.py >$@ chmod +x $@ %.o: %.c diff --git a/git-format-patch.sh b/git-format-patch.sh index 2844799535..9378219d84 100755 --- a/git-format-patch.sh +++ b/git-format-patch.sh @@ -212,7 +212,10 @@ Date: '"$ad" echo git-diff-tree -p $diff_opts "$commit" | git-apply --stat --summary echo + git-cat-file commit "$commit^" | sed -e 's/^tree /applies-to: /' -e q git-diff-tree -p $diff_opts "$commit" + echo "---" + echo "@@GIT_VERSION@@" case "$mbox" in t) From a24e658649170c99fdcb4aaa41545679ad02f755 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 6 Oct 2005 01:37:17 -0700 Subject: [PATCH 027/254] git-shortlog: make the mailmap configurable. In addition to hardcoded list of kernel people, read from .mailmap file the list of email-to-name translations. Modernize regexps here and there minimally while at it. Signed-off-by: Junio C Hamano --- git-shortlog.perl | 143 +++++++++++++++++++++++++++------------------- 1 file changed, 83 insertions(+), 60 deletions(-) diff --git a/git-shortlog.perl b/git-shortlog.perl index 8f0984be02..0b14f833ee 100755 --- a/git-shortlog.perl +++ b/git-shortlog.perl @@ -2,55 +2,13 @@ use strict; -# -# Even with git, we don't always have name translations. -# So have an email->real name table to translate the -# (hopefully few) missing names -# -my %mailmap = ( - 'R.Marek@sh.cvut.cz' => 'Rudolf Marek', - 'Ralf.Wildenhues@gmx.de' => 'Ralf Wildenhues', - 'aherrman@de.ibm.com' => 'Andreas Herrmann', - 'akpm@osdl.org' => 'Andrew Morton', - 'andrew.vasquez@qlogic.com' => 'Andrew Vasquez', - 'aquynh@gmail.com' => 'Nguyen Anh Quynh', - 'axboe@suse.de' => 'Jens Axboe', - 'blaisorblade@yahoo.it' => 'Paolo \'Blaisorblade\' Giarrusso', - 'bunk@stusta.de' => 'Adrian Bunk', - 'domen@coderock.org' => 'Domen Puncer', - 'dougg@torque.net' => 'Douglas Gilbert', - 'dwmw2@shinybook.infradead.org' => 'David Woodhouse', - 'ecashin@coraid.com' => 'Ed L Cashin', - 'felix@derklecks.de' => 'Felix Moeller', - 'fzago@systemfabricworks.com' => 'Frank Zago', - 'gregkh@suse.de' => 'Greg Kroah-Hartman', - 'hch@lst.de' => 'Christoph Hellwig', - 'htejun@gmail.com' => 'Tejun Heo', - 'jejb@mulgrave.(none)' => 'James Bottomley', - 'jejb@titanic.il.steeleye.com' => 'James Bottomley', - 'jgarzik@pretzel.yyz.us' => 'Jeff Garzik', - 'johnpol@2ka.mipt.ru' => 'Evgeniy Polyakov', - 'kay.sievers@vrfy.org' => 'Kay Sievers', - 'minyard@acm.org' => 'Corey Minyard', - 'mshah@teja.com' => 'Mitesh shah', - 'pj@ludd.ltu.se' => 'Peter A Jonsson', - 'rmps@joel.ist.utl.pt' => 'Rui Saraiva', - 'santtu.hyrkko@gmail.com' => 'Santtu Hyrkkö', - 'simon@thekelleys.org.uk' => 'Simon Kelley', - 'ssant@in.ibm.com' => 'Sachin P Sant', - 'terra@gnome.org' => 'Morten Welinder', - 'tony.luck@intel.com' => 'Tony Luck', - 'welinder@anemone.rentec.com' => 'Morten Welinder', - 'welinder@darter.rentec.com' => 'Morten Welinder', - 'welinder@troll.com' => 'Morten Welinder', -); - +my (%mailmap); +my (%email); my (%map); my $pstate = 1; my $n_records = 0; my $n_output = 0; - sub shortlog_entry($$) { my ($name, $desc) = @_; my $key = $name; @@ -108,41 +66,35 @@ sub changelog_input { if ($pstate == 1) { my ($email); - next unless /^[Aa]uthor:? (.*)<(.*)>.*$/; - + next unless /^[Aa]uthor:?\s*(.*?)\s*<(.*)>/; + $n_records++; - + $author = $1; $email = $2; $desc = undef; - # trim trailing whitespace. - # why doesn't chomp work? - while ($author && ($author =~ /\s$/)) { - chop $author; - } - # cset author fixups if (exists $mailmap{$email}) { $author = $mailmap{$email}; } elsif (exists $mailmap{$author}) { $author = $mailmap{$author}; - } elsif ((!$author) || ($author eq "")) { + } elsif (!$author) { $author = $email; } - + $email{$author}{$email}++; $pstate++; } - + # skip to blank line elsif ($pstate == 2) { next unless /^\s*$/; $pstate++; } - + # skip to non-blank line elsif ($pstate == 3) { - next unless /^\s*(\S.*)$/; + next unless /^\s*?(.*)/; # skip lines that are obviously not # a 1-line cset description @@ -150,9 +102,9 @@ sub changelog_input { chomp; $desc = $1; - + &shortlog_entry($author, $desc); - + $pstate = 1; } @@ -162,16 +114,87 @@ sub changelog_input { } } +sub read_mailmap { + my ($fh, $mailmap) = @_; + while (<$fh>) { + chomp; + if (/^([^#].*?)\s*<(.*)>/) { + $mailmap->{$2} = $1; + } + } +} + +sub setup_mailmap { + read_mailmap(\*DATA, \%mailmap); + if (-f '.mailmap') { + my $fh = undef; + open $fh, '<', '.mailmap'; + read_mailmap($fh, \%mailmap); + close $fh; + } +} + sub finalize { #print "\n$n_records records parsed.\n"; if ($n_records != $n_output) { die "parse error: input records != output records\n"; } + if (0) { + for my $author (sort keys %email) { + my $e = $email{$author}; + for my $email (sort keys %$e) { + print STDERR "$author <$email>\n"; + } + } + } } +&setup_mailmap; &changelog_input; &shortlog_output; &finalize; exit(0); + +__DATA__ +# +# Even with git, we don't always have name translations. +# So have an email->real name table to translate the +# (hopefully few) missing names +# +Adrian Bunk +Andreas Herrmann +Andrew Morton +Andrew Vasquez +Christoph Hellwig +Corey Minyard +David Woodhouse +Domen Puncer +Douglas Gilbert +Ed L Cashin +Evgeniy Polyakov +Felix Moeller +Frank Zago +Greg Kroah-Hartman +James Bottomley +James Bottomley +Jeff Garzik +Jens Axboe +Kay Sievers +Mitesh shah +Morten Welinder +Morten Welinder +Morten Welinder +Morten Welinder +Nguyen Anh Quynh +Paolo 'Blaisorblade' Giarrusso +Peter A Jonsson +Ralf Wildenhues +Rudolf Marek +Rui Saraiva +Sachin P Sant +Santtu Hyrkk,Av(B +Simon Kelley +Tejun Heo +Tony Luck From 12aac5de3dd73a1f9d03f81c5b0087e71794cee7 Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Thu, 6 Oct 2005 14:10:39 -0700 Subject: [PATCH 028/254] Do not require ls-remote to be run inside a git repository. The scripts work perfectly without a repository. Signed-off-by: Alex Riesen Signed-off-by: Junio C Hamano --- git-ls-remote.sh | 2 +- git-parse-remote.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/git-ls-remote.sh b/git-ls-remote.sh index bfbd5a4d5a..f0f0b07f6f 100755 --- a/git-ls-remote.sh +++ b/git-ls-remote.sh @@ -1,6 +1,6 @@ #!/bin/sh # -. git-sh-setup || die "Not a git archive" +. git-sh-setup usage () { echo >&2 "usage: $0 [--heads] [--tags] ..." diff --git a/git-parse-remote.sh b/git-parse-remote.sh index 4d8a572a99..5e75e15a7e 100755 --- a/git-parse-remote.sh +++ b/git-parse-remote.sh @@ -1,6 +1,6 @@ #!/bin/sh -. git-sh-setup || die "Not a git archive" +. git-sh-setup get_data_source () { case "$1" in From bc162e40ea6dc3208e3bda76301d6409607ed3ff Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 6 Oct 2005 14:10:39 -0700 Subject: [PATCH 029/254] Allow "-u" flag to tag signing The current "git tag -s" thing always uses the tagger name as the signing user key, which is very irritating, since my key is under my email address, but the tagger key obviously contains the actual machine name too. Now, I could just use "GIT_COMMITTER_EMAIL" and force it to be my real email, but I actually think that it's nice to see which machine I use for my work. So rather than force my tagger ID to have to match the gpg key name, just support the "-u" flag to "git tag" instead. It implicitly enables signing, since it doesn't make any sense without it. Thus: git tag -u [] will use the named gpg key for signing. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- Documentation/git-tag.txt | 22 +++++++++++++++------- git-tag.sh | 18 ++++++++++++++---- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt index 1e0d4f5f46..1eafeef473 100644 --- a/Documentation/git-tag.txt +++ b/Documentation/git-tag.txt @@ -10,19 +10,27 @@ git-tag - Create a tag object signed with GPG SYNOPSIS -------- -'git-tag' [-s | -a] [-f] +'git-tag' [-a | -s | -u ] [-f] [-m ] DESCRIPTION ----------- -Adds a "tag" reference in .git/refs/tags/ +Adds a 'tag' reference in .git/refs/tags/ -Unless "-f" is given, the tag must not yet exist in ".git/refs/tags" +Unless `-f` is given, the tag must not yet exist in +`.git/refs/tags/` directory. -If "-s" or "-a" is passed, the user will be prompted for a tag message. -and a tag object is created. Otherwise just the SHA1 object -name of the commit object is written. +If one of `-a`, `-s`, or `-u ` is passed, the command +creates a 'tag' object, and requires the tag message. Unless +`-m ` is given, an editor is started for the user to type +in the tag message. -A GnuPG signed tag object will be created when "-s" is used. +Otherwise just the SHA1 object name of the commit object is +written (i.e. an lightweight tag). + +A GnuPG signed tag object will be created when `-s` or `-u +` is used. When `-u ` is not used, the +committer identity for the current user is used to find the +GnuPG key for signing. Author diff --git a/git-tag.sh b/git-tag.sh index 76c1bcd8c9..9afdf5cce7 100755 --- a/git-tag.sh +++ b/git-tag.sh @@ -4,7 +4,7 @@ . git-sh-setup || die "Not a git archive" usage () { - echo >&2 "Usage: git-tag [-a | -s] [-f] [-m "tag message"] tagname" + echo >&2 "Usage: git-tag [-a | -s | -u ] [-f] [-m ] " exit 1 } @@ -12,6 +12,7 @@ annotate= signed= force= message= +username= while case "$#" in 0) break ;; esac do case "$1" in @@ -30,6 +31,12 @@ do shift message="$1" ;; + -u) + annotate=1 + signed=1 + shift + username="$1" + ;; -*) usage ;; @@ -50,6 +57,7 @@ shift object=$(git-rev-parse --verify --default HEAD "$@") || exit 1 type=$(git-cat-file -t $object) || exit 1 tagger=$(git-var GIT_COMMITTER_IDENT) || exit 1 +: ${username:=$(expr "$tagger" : '\(.*>\)')} trap 'rm -f .tmp-tag* .tagmsg .editmsg' 0 @@ -65,13 +73,15 @@ if [ "$annotate" ]; then grep -v '^#' < .editmsg | git-stripspace > .tagmsg - [ -s .tagmsg ] || exit + [ -s .tagmsg ] || { + echo >&2 "No tag message?" + exit 1 + } ( echo -e "object $object\ntype $type\ntag $name\ntagger $tagger\n"; cat .tagmsg ) > .tmp-tag rm -f .tmp-tag.asc .tagmsg if [ "$signed" ]; then - me=$(expr "$tagger" : '\(.*>\)') && - gpg -bsa -u "$me" .tmp-tag && + gpg -bsa -u "$username" .tmp-tag && cat .tmp-tag.asc >>.tmp-tag || die "failed to sign the tag with GPG." fi From 47f0b6d5d49247b85898083d1ccf4f899ef7294a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 6 Oct 2005 14:25:52 -0700 Subject: [PATCH 030/254] Fall back to three-way merge when applying a patch. After git-apply fails, attempt to find a base tree that the patch cleanly applies to, and do a three-way merge using that base tree into the current index, if .dotest/.3way file exists. This flag can be controlled by giving -m flag to git-applymbox command. When the fall-back merge fails, the working tree can be resolved the same way as you would normally hand resolve a conflicting merge. When making commit, use .dotest/final-commit as the log message template. Or you could just choose to 'git-checkout-index -f -a' to revert the failed merge. Signed-off-by: Junio C Hamano --- Documentation/git-applymbox.txt | 10 ++++- git-applymbox.sh | 8 ++-- git-applypatch.sh | 73 ++++++++++++++++++++++++++++++++- 3 files changed, 86 insertions(+), 5 deletions(-) diff --git a/Documentation/git-applymbox.txt b/Documentation/git-applymbox.txt index bb543788c0..8f01ca6a16 100644 --- a/Documentation/git-applymbox.txt +++ b/Documentation/git-applymbox.txt @@ -8,7 +8,7 @@ git-applymbox - Apply a series of patches in a mailbox SYNOPSIS -------- -'git-applymbox' [-u] [-k] [-q] ( -c .dotest/ | ) [ ] +'git-applymbox' [-u] [-k] [-q] [-m] ( -c .dotest/ | ) [ ] DESCRIPTION ----------- @@ -33,6 +33,14 @@ OPTIONS munging, and is most useful when used to read back 'git format-patch --mbox' output. +-m:: + Patches are applied with `git-apply` command, and unless + it cleanly applies without fuzz, the processing fails. + With this flag, if a tree that the patch applies cleanly + is found in a repository, the patch is applied to the + tree and then a 3-way merge between the resulting tree + and the current tree. + -u:: By default, the commit log message, author name and author email are taken from the e-mail without any diff --git a/git-applymbox.sh b/git-applymbox.sh index e2bfd02870..a83246cad8 100755 --- a/git-applymbox.sh +++ b/git-applymbox.sh @@ -9,8 +9,6 @@ ## You give it a mbox-format collection of emails, and it will try to ## apply them to the kernel using "applypatch" ## -## applymbox [-u] [-k] [-q] (-c .dotest/msg-number | mail_archive) [Signoff_file]" -## ## The patch application may fail in the middle. In which case: ## (1) look at .dotest/patch and fix it up to apply ## (2) re-run applymbox with -c .dotest/msg-number for the current one. @@ -21,7 +19,7 @@ . git-sh-setup || die "Not a git archive" usage () { - echo >&2 "applymbox [-u] [-k] [-q] (-c .dotest/ | mbox) [signoff]" + echo >&2 "applymbox [-u] [-k] [-q] [-m] (-c .dotest/ | mbox) [signoff]" exit 1 } @@ -33,6 +31,7 @@ do -k) keep_subject=-k ;; -q) query_apply=t ;; -c) continue="$2"; resume=f; shift ;; + -m) fallback_3way=t ;; -*) usage ;; *) break ;; esac @@ -56,6 +55,9 @@ fi case "$query_apply" in t) touch .dotest/.query_apply esac +case "$fall_back_3way" in +t) : >.dotest/.3way +esac case "$keep_subject" in -k) : >.dotest/.keep_subject esac diff --git a/git-applypatch.sh b/git-applypatch.sh index 14635d9bce..66fd19ae2d 100755 --- a/git-applypatch.sh +++ b/git-applypatch.sh @@ -22,6 +22,8 @@ query_apply=.dotest/.query_apply ## if this file exists. keep_subject=.dotest/.keep_subject +## We do not attempt the 3-way merge fallback unless this file exists. +fall_back_3way=.dotest/.3way MSGFILE=$1 PATCHFILE=$2 @@ -102,10 +104,79 @@ echo Applying "'$SUBJECT'" echo git-apply --index "$PATCHFILE" || { + + # git-apply exits with status 1 when the patch does not apply, + # but it die()s with other failures, most notably upon corrupt + # patch. In the latter case, there is no point to try applying + # it to another tree and do 3-way merge. + test $? = 1 || exit 1 + + test -f "$fall_back_3way" || exit 1 + # Here if we know which revision the patch applies to, # we create a temporary working tree and index, apply the # patch, and attempt 3-way merge with the resulting tree. - exit 1 + + O_OBJECT=`cd "$GIT_OBJECT_DIRECTORY" && pwd` + rm -fr .patch-merge-* + + ( + N=10 + + # if the patch records the base tree... + sed -ne ' + /^diff /q + /^applies-to: \([0-9a-f]*\)$/{ + s//\1/p + q + } + ' "$PATCHFILE" + + # or hoping the patch is against our recent commits... + git-rev-list --max-count=$N HEAD + + # or hoping the patch is against known tags... + git-ls-remote --tags . + ) | + while read base junk + do + # Try it if we have it as a tree. + git-cat-file tree "$base" >/dev/null 2>&1 || continue + + rm -fr .patch-merge-tmp-* && + mkdir .patch-merge-tmp-dir || break + ( + cd .patch-merge-tmp-dir && + GIT_INDEX_FILE=../.patch-merge-tmp-index && + GIT_OBJECT_DIRECTORY="$O_OBJECT" && + export GIT_INDEX_FILE GIT_OBJECT_DIRECTORY && + git-read-tree "$base" && + git-apply --index && + mv ../.patch-merge-tmp-index ../.patch-merge-index && + echo "$base" >../.patch-merge-base + ) <"$PATCHFILE" 2>/dev/null && break + done + + test -f .patch-merge-index && + his_tree=$(GIT_INDEX_FILE=.patch-merge-index git-write-tree) && + orig_tree=$(cat .patch-merge-base) && + rm -fr .patch-merge-* || exit 1 + + echo Falling back to patching base and 3-way merge using $orig_tree... + + # This is not so wrong. Depending on which base we picked, + # orig_tree may be wildly different from ours, but his_tree + # has the same set of wildly different changes in parts the + # patch did not touch, so resolve ends up cancelling them, + # saying that we reverted all those changes. + + if git-merge-resolve $orig_tree -- HEAD $his_tree + then + echo Done. + else + echo Failed to merge in the changes. + exit 1 + fi } if test -x "$GIT_DIR"/hooks/pre-applypatch From 4ebe63dfe6f2a8c652ecd8dfe6ab8a77b6c82b2f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 6 Oct 2005 14:25:52 -0700 Subject: [PATCH 031/254] Clean mail files after dealing with them. When you are applying 200 mails in sequence, .dotest/ directory will be littered with many messsages, and when the patch in one of them fails to apply, it is not obvious which message was being processed. Remove the one that has been already dealt with, so that the last failed one is found typically as the lowest numbered split message. Signed-off-by: Junio C Hamano --- git-applymbox.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/git-applymbox.sh b/git-applymbox.sh index a83246cad8..79abce2a25 100755 --- a/git-applymbox.sh +++ b/git-applymbox.sh @@ -82,7 +82,11 @@ do do git-applypatch .dotest/msg-clean .dotest/patch .dotest/info "$signoff" case "$?" in - 0 | 2 ) + 0) + # Remove the cleanly applied one to reduce clutter. + rm -f .dotest/$i + ;; + 2) # 2 is a special exit code from applypatch to indicate that # the patch wasn't applied, but continue anyway ;; From 655c7470e2ea7f25f22703b6654d7570e1567a39 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 6 Oct 2005 14:25:52 -0700 Subject: [PATCH 032/254] git-format-patch: --stdout option. This new flag generates the mbox formatted output to the standard output, instead of saving them into a file per patch and implies --mbox. It also fixes a corner case where the commit does not have *any* message. Signed-off-by: Junio C Hamano --- git-format-patch.sh | 72 ++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/git-format-patch.sh b/git-format-patch.sh index 9378219d84..09b635e492 100755 --- a/git-format-patch.sh +++ b/git-format-patch.sh @@ -6,7 +6,7 @@ . git-sh-setup || die "Not a git archive." usage () { - echo >&2 "usage: $0"' [-n] [-o dir] [--keep-subject] [--mbox] [--check] [--signoff] [-...] upstream [ our-head ] + echo >&2 "usage: $0"' [-n] [-o dir | --stdout] [--keep-subject] [--mbox] [--check] [--signoff] [-...] upstream [ our-head ] Prepare each commit with its patch since our-head forked from upstream, one file per patch, for e-mail submission. Each output file is @@ -49,6 +49,8 @@ do numbered=t ;; -s|--s|--si|--sig|--sign|--signo|--signof|--signoff) signoff=t ;; + --st|--std|--stdo|--stdou|--stdout) + stdout=t mbox=t date=t author=t ;; -o=*|--o=*|--ou=*|--out=*|--outp=*|--outpu=*|--output=*|--output-=*|\ --output-d=*|--output-di=*|--output-dir=*|--output-dire=*|\ --output-direc=*|--output-direct=*|--output-directo=*|\ @@ -141,25 +143,7 @@ do esac done >$series -total=`wc -l <$series | tr -dc "[0-9]"` -i=1 -while read commit -do - git-cat-file commit "$commit" | git-stripspace >$commsg - title=`sed -ne "$titleScript" <$commsg` - case "$numbered" in - '') num= ;; - *) - case $total in - 1) num= ;; - *) num=' '`printf "%d/%d" $i $total` ;; - esac - esac - - file=`printf '%04d-%stxt' $i "$title"` - i=`expr "$i" + 1` - echo "* $file" - { +process_one () { mailScript=' /./d /^$/n' @@ -178,6 +162,7 @@ do echo 'From nobody Mon Sep 17 00:00:00 2001' ;# UNIX "From" line ;; esac + eval "$(sed -ne "$whosepatchScript" $commsg)" test "$author,$au" = ",$me" || { mailScript="$mailScript"' @@ -196,7 +181,9 @@ Date: '"$ad" n b body' - sed -ne "$mailScript" <$commsg + (cat $commsg ; echo; echo) | + sed -ne "$mailScript" | + git-stripspace test "$signoff" = "t" && { offsigner=`git-var GIT_COMMITTER_IDENT | sed -e 's/>.*/>/'` @@ -222,14 +209,39 @@ Date: '"$ad" echo ;; esac - } >"$outdir$file" - case "$check" in - t) - # This is slightly modified from Andrew Morton's Perfect Patch. - # Lines you introduce should not have trailing whitespace. - # Also check for an indentation that has SP before a TAB. - grep -n '^+\([ ]* .*\|.*[ ]\)$' "$outdir$file" - - : do not exit with non-zero because we saw no problem in the last one. +} + +total=`wc -l <$series | tr -dc "[0-9]"` +i=1 +while read commit +do + git-cat-file commit "$commit" | git-stripspace >$commsg + title=`sed -ne "$titleScript" <$commsg` + case "$numbered" in + '') num= ;; + *) + case $total in + 1) num= ;; + *) num=' '`printf "%d/%d" $i $total` ;; + esac esac + + file=`printf '%04d-%stxt' $i "$title"` + if test '' = "$stdout" + then + echo "* $file" + process_one >"$outdir$file" + if test t = "$check" + then + # This is slightly modified from Andrew Morton's Perfect Patch. + # Lines you introduce should not have trailing whitespace. + # Also check for an indentation that has SP before a TAB. + grep -n '^+\([ ]* .*\|.*[ ]\)$' "$outdir$file" + : + fi + else + echo >&2 "* $file" + process_one + fi + i=`expr "$i" + 1` done <$series From e11fc02066435b0f370d639e665ec70680e876a6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 6 Oct 2005 14:25:52 -0700 Subject: [PATCH 033/254] mailsplit: -d Instead of the default 4 digits with leading zeros, different precision can be specified for the generated filenames. Signed-off-by: Junio C Hamano --- git-applymbox.sh | 3 ++- mailsplit.c | 13 ++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/git-applymbox.sh b/git-applymbox.sh index 79abce2a25..4e77132ab5 100755 --- a/git-applymbox.sh +++ b/git-applymbox.sh @@ -42,7 +42,8 @@ case "$continue" in '') rm -rf .dotest mkdir .dotest - git-mailsplit "$1" .dotest || exit 1 + num_msgs=$(git-mailsplit "$1" .dotest) || exit 1 + echo "$num_msgs patch(es) to process." shift esac diff --git a/mailsplit.c b/mailsplit.c index 7afea1aaca..bd7c611bb9 100644 --- a/mailsplit.c +++ b/mailsplit.c @@ -17,7 +17,7 @@ static int usage(void) { - fprintf(stderr, "mailsplit \n"); + fprintf(stderr, "git-mailsplit [-d] \n"); exit(1); } @@ -96,11 +96,17 @@ corrupt: int main(int argc, char **argv) { - int fd, nr; + int fd, nr, nr_prec = 4; struct stat st; unsigned long size; void *map; + if (argc == 4 && !strncmp(argv[1], "-d", 2)) { + nr_prec = strtol(argv[1] + 2, NULL, 10); + if (nr_prec < 3 || 10 <= nr_prec) + usage(); + argc--; argv++; + } if (argc != 3) usage(); fd = open(argv[1], O_RDONLY); @@ -127,7 +133,7 @@ int main(int argc, char **argv) char name[10]; unsigned long len = parse_email(map, size); assert(len <= size); - sprintf(name, "%04d", ++nr); + sprintf(name, "%0*d", nr_prec, ++nr); fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0666); if (fd < 0) { perror(name); @@ -141,5 +147,6 @@ int main(int argc, char **argv) map += len; size -= len; } while (size > 0); + printf("%d\n", nr); return 0; } From 54ba6013b4eaff0d96f9ab96cf225ca392b08a30 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 6 Oct 2005 14:25:52 -0700 Subject: [PATCH 034/254] Describe new options to git-format-patch and git-mailsplit. Signed-off-by: Junio C Hamano --- Documentation/git-format-patch.txt | 6 +++++- Documentation/git-mailsplit.txt | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index a1483ffd0f..f3ef4c1e04 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -8,7 +8,7 @@ git-format-patch - Prepare patches for e-mail submission. SYNOPSIS -------- -'git-format-patch' [-n][-o ][-k][--mbox][--diff-options] [] +'git-format-patch' [-n][-o |--stdout][-k][--mbox][--diff-options] [] DESCRIPTION ----------- @@ -54,6 +54,10 @@ OPTIONS concatenated together and fed to `git-applymbox`. Implies --author and --date. +--stdout:: + This flag generates the mbox formatted output to the + standard output, instead of saving them into a file per + patch and implies --mbox. Author ------ diff --git a/Documentation/git-mailsplit.txt b/Documentation/git-mailsplit.txt index 557d2e9056..66239a8f8e 100644 --- a/Documentation/git-mailsplit.txt +++ b/Documentation/git-mailsplit.txt @@ -7,7 +7,7 @@ git-mailsplit - Totally braindamaged mbox splitter program. SYNOPSIS -------- -'git-mailsplit' +'git-mailsplit' [-d] DESCRIPTION ----------- @@ -22,6 +22,12 @@ OPTIONS :: Directory in which to place the individual messages. +-d:: + Instead of the default 4 digits with leading zeros, + different precision can be specified for the generated + filenames. + + Author ------ Written by Linus Torvalds From 8b73edf498adf2895af7ff9c750283cf9325a632 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 6 Oct 2005 15:55:43 -0700 Subject: [PATCH 035/254] mailsplit: allow feeding mbox from standard input. When mbox argument is missing, read the mailbox from the standard input. Signed-off-by: Junio C Hamano --- Documentation/git-mailsplit.txt | 7 +- mailsplit.c | 175 +++++++++++++++++--------------- 2 files changed, 96 insertions(+), 86 deletions(-) diff --git a/Documentation/git-mailsplit.txt b/Documentation/git-mailsplit.txt index 66239a8f8e..03a9477664 100644 --- a/Documentation/git-mailsplit.txt +++ b/Documentation/git-mailsplit.txt @@ -7,7 +7,7 @@ git-mailsplit - Totally braindamaged mbox splitter program. SYNOPSIS -------- -'git-mailsplit' [-d] +'git-mailsplit' [-d] [] DESCRIPTION ----------- @@ -17,7 +17,8 @@ directory so you can process them further from there. OPTIONS ------- :: - Mbox file to split. + Mbox file to split. If not given, the mbox is read from + the standard input. :: Directory in which to place the individual messages. @@ -31,6 +32,8 @@ OPTIONS Author ------ Written by Linus Torvalds +and Junio C Hamano + Documentation -------------- diff --git a/mailsplit.c b/mailsplit.c index bd7c611bb9..7981f87a72 100644 --- a/mailsplit.c +++ b/mailsplit.c @@ -14,25 +14,10 @@ #include #include #include +#include "cache.h" -static int usage(void) -{ - fprintf(stderr, "git-mailsplit [-d] \n"); - exit(1); -} - -static int linelen(const char *map, unsigned long size) -{ - int len = 0, c; - - do { - c = *map; - map++; - size--; - len++; - } while (size && c != '\n'); - return len; -} +static const char git_mailsplit_usage[] = +"git-mailsplit [-d] [] "; static int is_from_line(const char *line, int len) { @@ -65,88 +50,110 @@ static int is_from_line(const char *line, int len) return 1; } -static int parse_email(const void *map, unsigned long size) +/* Could be as small as 64, enough to hold a Unix "From " line. */ +static char buf[4096]; + +/* Called with the first line (potentially partial) + * already in buf[] -- normally that should begin with + * the Unix "From " line. Write it into the specified + * file. + */ +static int split_one(FILE *mbox, const char *name) { - unsigned long offset; + FILE *output = NULL; + int len = strlen(buf); + int fd; + int status = 0; - if (size < 6 || memcmp("From ", map, 5)) + if (!is_from_line(buf, len)) goto corrupt; - /* Make sure we don't trigger on this first line */ - map++; size--; offset=1; + fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0666); + if (fd < 0) + die("cannot open output file %s", name); + output = fdopen(fd, "w"); - /* - * Search for a line beginning with "From ", and - * having something that looks like a date format. + /* Copy it out, while searching for a line that begins with + * "From " and having something that looks like a date format. */ - do { - int len = linelen(map, size); - if (is_from_line(map, len)) - return offset; - map += len; - size -= len; - offset += len; - } while (size); - return offset; - -corrupt: + for (;;) { + int is_partial = (buf[len-1] != '\n'); + + if (fputs(buf, output) == EOF) + die("cannot write output"); + + if (fgets(buf, sizeof(buf), mbox) == NULL) { + if (feof(mbox)) { + status = 1; + break; + } + die("cannot read mbox"); + } + len = strlen(buf); + if (!is_partial && is_from_line(buf, len)) + break; /* done with one message */ + } + fclose(output); + return status; + + corrupt: + if (output) + fclose(output); + unlink(name); fprintf(stderr, "corrupt mailbox\n"); exit(1); } -int main(int argc, char **argv) +int main(int argc, const char **argv) { - int fd, nr, nr_prec = 4; - struct stat st; - unsigned long size; - void *map; - - if (argc == 4 && !strncmp(argv[1], "-d", 2)) { - nr_prec = strtol(argv[1] + 2, NULL, 10); - if (nr_prec < 3 || 10 <= nr_prec) - usage(); - argc--; argv++; - } - if (argc != 3) - usage(); - fd = open(argv[1], O_RDONLY); - if (fd < 0) { - perror(argv[1]); - exit(1); - } - if (chdir(argv[2]) < 0) - usage(); - if (fstat(fd, &st) < 0) { - perror("stat"); - exit(1); + int i, nr, nr_prec = 4; + FILE *mbox = NULL; + + for (i = 1; i < argc; i++) { + const char *arg = argv[i]; + + if (arg[0] != '-') + break; + /* do flags here */ + if (!strncmp(arg, "-d", 2)) { + nr_prec = strtol(arg + 2, NULL, 10); + if (nr_prec < 3 || 10 <= nr_prec) + usage(git_mailsplit_usage); + continue; + } } - size = st.st_size; - map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); - if (map == MAP_FAILED) { - perror("mmap"); - close(fd); - exit(1); + + /* Either one remaining arg (dir), or two (mbox and dir) */ + switch (argc - i) { + case 1: + mbox = stdin; + break; + case 2: + if ((mbox = fopen(argv[i], "r")) == NULL) + die("cannot open mbox %s for reading", argv[i]); + break; + default: + usage(git_mailsplit_usage); } - close(fd); + if (chdir(argv[argc - 1]) < 0) + usage(git_mailsplit_usage); + nr = 0; - do { + if (fgets(buf, sizeof(buf), mbox) == NULL) + die("cannot read mbox"); + + for (;;) { char name[10]; - unsigned long len = parse_email(map, size); - assert(len <= size); + sprintf(name, "%0*d", nr_prec, ++nr); - fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0666); - if (fd < 0) { - perror(name); - exit(1); - } - if (write(fd, map, len) != len) { - perror("write"); + switch (split_one(mbox, name)) { + case 0: + break; + case 1: + printf("%d\n", nr); + return 0; + default: exit(1); } - close(fd); - map += len; - size -= len; - } while (size > 0); - printf("%d\n", nr); - return 0; + } } From ec1fcc16af94810dd822c6da533f58fa2750f14a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 7 Oct 2005 03:42:00 -0700 Subject: [PATCH 036/254] Show original and resulting blob object info in diff output. This adds more cruft to diff --git header to record the blob SHA1 and the mode the patch/diff is intended to be applied against, to help the receiving end fall back on a three-way merge. The new header looks like this: diff --git a/apply.c b/apply.c index 7be5041..8366082 100644 --- a/apply.c +++ b/apply.c @@ -14,6 +14,7 @@ // files that are being modified, but doesn't apply the patch // --stat does just a diffstat, and doesn't actually apply +// --show-index-info shows the old and new index info for... ... Upon receiving such a patch, if the patch did not apply cleanly to the target tree, the recipient can try to find the matching old objects in her object database and create a temporary tree, apply the patch to that temporary tree, and attempt a 3-way merge between the patched temporary tree and the target tree using the original temporary tree as the common ancestor. The patch lifts the code to compute the hash for an on-filesystem object from update-index.c and makes it available to the diff output routine. Signed-off-by: Junio C Hamano --- cache.h | 1 + diff.c | 77 +++++++++++++++++++++++++--------- sha1_file.c | 39 +++++++++++++++++ t/diff-lib.sh | 10 ++++- t/t4000-diff-format.sh | 3 +- t/t4001-diff-rename.sh | 3 +- t/t4004-diff-rename-symlink.sh | 3 +- update-index.c | 33 ++------------- 8 files changed, 114 insertions(+), 55 deletions(-) diff --git a/cache.h b/cache.h index ec2a1610b2..514adb8f8e 100644 --- a/cache.h +++ b/cache.h @@ -165,6 +165,7 @@ extern int ce_match_stat(struct cache_entry *ce, struct stat *st); extern int ce_modified(struct cache_entry *ce, struct stat *st); extern int ce_path_match(const struct cache_entry *ce, const char **pathspec); extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, const char *type); +extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object); extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st); struct cache_file { diff --git a/diff.c b/diff.c index 7d06b035ae..cbb86320a6 100644 --- a/diff.c +++ b/diff.c @@ -596,15 +596,31 @@ static void run_external_diff(const char *pgm, remove_tempfile(); } +static void diff_fill_sha1_info(struct diff_filespec *one) +{ + if (DIFF_FILE_VALID(one)) { + if (!one->sha1_valid) { + struct stat st; + if (stat(one->path, &st) < 0) + die("stat %s", one->path); + if (index_path(one->sha1, one->path, &st, 0)) + die("cannot hash %s\n", one->path); + } + } + else + memset(one->sha1, 0, 20); +} + static void run_diff(struct diff_filepair *p) { const char *pgm = external_diff(); - char msg_[PATH_MAX*2+200], *xfrm_msg; + char msg[PATH_MAX*2+300], *xfrm_msg; struct diff_filespec *one; struct diff_filespec *two; const char *name; const char *other; int complete_rewrite = 0; + int len; if (DIFF_PAIR_UNMERGED(p)) { /* unmerged */ @@ -616,39 +632,60 @@ static void run_diff(struct diff_filepair *p) name = p->one->path; other = (strcmp(name, p->two->path) ? p->two->path : NULL); one = p->one; two = p->two; + + diff_fill_sha1_info(one); + diff_fill_sha1_info(two); + + len = 0; switch (p->status) { case DIFF_STATUS_COPIED: - sprintf(msg_, - "similarity index %d%%\n" - "copy from %s\n" - "copy to %s", - (int)(0.5 + p->score * 100.0/MAX_SCORE), - name, other); - xfrm_msg = msg_; + len += snprintf(msg + len, sizeof(msg) - len, + "similarity index %d%%\n" + "copy from %s\n" + "copy to %s\n", + (int)(0.5 + p->score * 100.0/MAX_SCORE), + name, other); break; case DIFF_STATUS_RENAMED: - sprintf(msg_, - "similarity index %d%%\n" - "rename from %s\n" - "rename to %s", - (int)(0.5 + p->score * 100.0/MAX_SCORE), - name, other); - xfrm_msg = msg_; + len += snprintf(msg + len, sizeof(msg) - len, + "similarity index %d%%\n" + "rename from %s\n" + "rename to %s\n", + (int)(0.5 + p->score * 100.0/MAX_SCORE), + name, other); break; case DIFF_STATUS_MODIFIED: if (p->score) { - sprintf(msg_, - "dissimilarity index %d%%", - (int)(0.5 + p->score * 100.0/MAX_SCORE)); - xfrm_msg = msg_; + len += snprintf(msg + len, sizeof(msg) - len, + "dissimilarity index %d%%\n", + (int)(0.5 + p->score * + 100.0/MAX_SCORE)); complete_rewrite = 1; break; } /* fallthru */ default: - xfrm_msg = NULL; + /* nothing */ + ; } + if (memcmp(one->sha1, two->sha1, 20)) { + char one_sha1[41]; + memcpy(one_sha1, sha1_to_hex(one->sha1), 41); + + len += snprintf(msg + len, sizeof(msg) - len, + "index %.7s..%.7s", one_sha1, + sha1_to_hex(two->sha1)); + if (one->mode == two->mode) + len += snprintf(msg + len, sizeof(msg) - len, + " %06o", one->mode); + len += snprintf(msg + len, sizeof(msg) - len, "\n"); + } + + if (len) + msg[--len] = 0; + xfrm_msg = len ? msg : NULL; + if (!pgm && DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two) && (S_IFMT & one->mode) != (S_IFMT & two->mode)) { diff --git a/sha1_file.c b/sha1_file.c index 895c1fab6f..287f618827 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1545,3 +1545,42 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, con munmap(buf, size); return ret; } + +int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object) +{ + int fd; + char *target; + + switch (st->st_mode & S_IFMT) { + case S_IFREG: + fd = open(path, O_RDONLY); + if (fd < 0) + return error("open(\"%s\"): %s", path, + strerror(errno)); + if (index_fd(sha1, fd, st, write_object, NULL) < 0) + return error("%s: failed to insert into database", + path); + break; + case S_IFLNK: + target = xmalloc(st->st_size+1); + if (readlink(path, target, st->st_size+1) != st->st_size) { + char *errstr = strerror(errno); + free(target); + return error("readlink(\"%s\"): %s", path, + errstr); + } + if (!write_object) { + unsigned char hdr[50]; + int hdrlen; + write_sha1_file_prepare(target, st->st_size, "blob", + sha1, hdr, &hdrlen); + } else if (write_sha1_file(target, st->st_size, "blob", sha1)) + return error("%s: failed to insert into database", + path); + free(target); + break; + default: + return error("%s: unsupported file type", path); + } + return 0; +} diff --git a/t/diff-lib.sh b/t/diff-lib.sh index a912f435aa..745a1b0311 100755 --- a/t/diff-lib.sh +++ b/t/diff-lib.sh @@ -29,7 +29,13 @@ compare_diff_raw_z () { compare_diff_patch () { # When heuristics are improved, the score numbers would change. # Ignore them while comparing. - sed -e '/^[dis]*imilarity index [0-9]*%$/d' <"$1" >.tmp-1 - sed -e '/^[dis]*imilarity index [0-9]*%$/d' <"$2" >.tmp-2 + sed -e ' + /^[dis]*imilarity index [0-9]*%$/d + /^index [0-9a-f]*\.\.[0-9a-f]/d + ' <"$1" >.tmp-1 + sed -e ' + /^[dis]*imilarity index [0-9]*%$/d + /^index [0-9a-f]*\.\.[0-9a-f]/d + ' <"$2" >.tmp-2 diff -u .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 } diff --git a/t/t4000-diff-format.sh b/t/t4000-diff-format.sh index f3b6330a9b..beb6d8f487 100755 --- a/t/t4000-diff-format.sh +++ b/t/t4000-diff-format.sh @@ -7,6 +7,7 @@ test_description='Test built-in diff output engine. ' . ./test-lib.sh +. ../diff-lib.sh echo >path0 'Line 1 Line 2 @@ -48,6 +49,6 @@ EOF test_expect_success \ 'validate git-diff-files -p output.' \ - 'cmp -s current expected' + 'compare_diff_patch current expected' test_done diff --git a/t/t4001-diff-rename.sh b/t/t4001-diff-rename.sh index be47485682..2e3c20d6b9 100755 --- a/t/t4001-diff-rename.sh +++ b/t/t4001-diff-rename.sh @@ -7,6 +7,7 @@ test_description='Test rename detection in diff engine. ' . ./test-lib.sh +. ../diff-lib.sh echo >path0 'Line 1 Line 2 @@ -61,6 +62,6 @@ EOF test_expect_success \ 'validate the output.' \ - 'diff -I "similarity.*" >/dev/null current expected' + 'compare_diff_patch current expected' test_done diff --git a/t/t4004-diff-rename-symlink.sh b/t/t4004-diff-rename-symlink.sh index f59614ae25..a23aaa0a94 100755 --- a/t/t4004-diff-rename-symlink.sh +++ b/t/t4004-diff-rename-symlink.sh @@ -10,6 +10,7 @@ copy of symbolic links, but should not produce rename/copy followed by an edit for them. ' . ./test-lib.sh +. ../diff-lib.sh test_expect_success \ 'prepare reference tree' \ @@ -61,6 +62,6 @@ EOF test_expect_success \ 'validate diff output' \ - 'diff -u current expected' + 'compare_diff_patch current expected' test_done diff --git a/update-index.c b/update-index.c index b825a11d2f..9dc518877b 100644 --- a/update-index.c +++ b/update-index.c @@ -37,8 +37,6 @@ static int add_file_to_cache(const char *path) int size, namelen, option, status; struct cache_entry *ce; struct stat st; - int fd; - char *target; status = lstat(path, &st); if (status < 0 || S_ISDIR(st.st_mode)) { @@ -77,34 +75,9 @@ static int add_file_to_cache(const char *path) fill_stat_cache_info(ce, &st); ce->ce_mode = create_ce_mode(st.st_mode); ce->ce_flags = htons(namelen); - switch (st.st_mode & S_IFMT) { - case S_IFREG: - fd = open(path, O_RDONLY); - if (fd < 0) - return error("open(\"%s\"): %s", path, strerror(errno)); - if (index_fd(ce->sha1, fd, &st, !info_only, NULL) < 0) - return error("%s: failed to insert into database", path); - break; - case S_IFLNK: - target = xmalloc(st.st_size+1); - if (readlink(path, target, st.st_size+1) != st.st_size) { - char *errstr = strerror(errno); - free(target); - return error("readlink(\"%s\"): %s", path, - errstr); - } - if (info_only) { - unsigned char hdr[50]; - int hdrlen; - write_sha1_file_prepare(target, st.st_size, "blob", - ce->sha1, hdr, &hdrlen); - } else if (write_sha1_file(target, st.st_size, "blob", ce->sha1)) - return error("%s: failed to insert into database", path); - free(target); - break; - default: - return error("%s: unsupported file type", path); - } + + if (index_path(ce->sha1, path, &st, !info_only)) + return -1; option = allow_add ? ADD_CACHE_OK_TO_ADD : 0; option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0; if (add_cache_entry(ce, option)) From 2cf67f1e35d3a2175e426b4b2841374e68105c2c Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 7 Oct 2005 03:42:00 -0700 Subject: [PATCH 037/254] git-apply: parse index information Add an new option --show-index-info to git-apply command to summarize the index information new git-diff outputs. The command shows something similar to git-ls-files --stage output for the pre-change image: 100644 7be5041... apply.c 100644 ec2a161... cache.h ... Signed-off-by: Junio C Hamano --- apply.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/apply.c b/apply.c index 7be5041353..155fbe84da 100644 --- a/apply.c +++ b/apply.c @@ -14,6 +14,7 @@ // files that are being modified, but doesn't apply the patch // --stat does just a diffstat, and doesn't actually apply // --show-files shows the directory changes +// --show-index-info shows the old and new index info for paths if available. // static int check_index = 0; static int write_index = 0; @@ -22,8 +23,9 @@ static int summary = 0; static int check = 0; static int apply = 1; static int show_files = 0; +static int show_index_info = 0; static const char apply_usage[] = -"git-apply [--stat] [--summary] [--check] [--index] [--apply] [--show-files] ..."; +"git-apply [--stat] [--summary] [--check] [--index] [--apply] [--show-files] [--show-index-info] ..."; /* * For "diff-stat" like behaviour, we keep track of the biggest change @@ -56,6 +58,8 @@ struct patch { struct fragment *fragments; char *result; unsigned long resultsize; + char old_sha1_prefix[41]; + char new_sha1_prefix[41]; struct patch *next; }; @@ -334,6 +338,38 @@ static int gitdiff_dissimilarity(const char *line, struct patch *patch) return 0; } +static int gitdiff_index(const char *line, struct patch *patch) +{ + /* index line is N hexadecimal, "..", N hexadecimal, + * and optional space with octal mode. + */ + const char *ptr, *eol; + int len; + + ptr = strchr(line, '.'); + if (!ptr || ptr[1] != '.' || 40 <= ptr - line) + return 0; + len = ptr - line; + memcpy(patch->old_sha1_prefix, line, len); + patch->old_sha1_prefix[len] = 0; + + line = ptr + 2; + ptr = strchr(line, ' '); + eol = strchr(line, '\n'); + + if (!ptr || eol < ptr) + ptr = eol; + len = ptr - line; + + if (40 <= len) + return 0; + memcpy(patch->new_sha1_prefix, line, len); + patch->new_sha1_prefix[len] = 0; + if (*ptr == ' ') + patch->new_mode = patch->old_mode = strtoul(ptr+1, NULL, 8); + return 0; +} + /* * This is normal for a diff that doesn't change anything: we'll fall through * into the next diff. Tell the parser to break out. @@ -438,6 +474,7 @@ static int parse_git_header(char *line, int len, unsigned int size, struct patch { "rename to ", gitdiff_renamedst }, { "similarity index ", gitdiff_similarity }, { "dissimilarity index ", gitdiff_dissimilarity }, + { "index ", gitdiff_index }, { "", gitdiff_unrecognized }, }; int i; @@ -1136,6 +1173,36 @@ static void show_file_list(struct patch *patch) } } +static inline int is_null_sha1(const unsigned char *sha1) +{ + return !memcmp(sha1, null_sha1, 20); +} + +static void show_index_list(struct patch *list) +{ + struct patch *patch; + + /* Once we start supporting the reverse patch, it may be + * worth showing the new sha1 prefix, but until then... + */ + for (patch = list; patch; patch = patch->next) { + const unsigned char *sha1_ptr; + unsigned char sha1[20]; + const char *name; + + name = patch->old_name ? patch->old_name : patch->new_name; + if (patch->is_new) + sha1_ptr = null_sha1; + else if (get_sha1(patch->old_sha1_prefix, sha1)) + die("sha1 information is lacking or useless (%s).", + name); + else + sha1_ptr = sha1; + printf("%06o %s %s\n",patch->old_mode, + sha1_to_hex(sha1_ptr), name); + } +} + static void stat_patch_list(struct patch *patch) { int files, adds, dels; @@ -1476,6 +1543,9 @@ static int apply_patch(int fd) if (show_files) show_file_list(list); + if (show_index_info) + show_index_list(list); + if (diffstat) stat_patch_list(list); @@ -1534,6 +1604,11 @@ int main(int argc, char **argv) show_files = 1; continue; } + if (!strcmp(arg, "--show-index-info")) { + apply = 0; + show_index_info = 1; + continue; + } fd = open(arg, O_RDONLY); if (fd < 0) usage(apply_usage); From d4dbf36df0eb2efe78822704d9779d662ed4dd8a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 7 Oct 2005 03:42:00 -0700 Subject: [PATCH 038/254] update-index: read --show-index-info output from standard input. Signed-off-by: Junio C Hamano --- update-index.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/update-index.c b/update-index.c index 9dc518877b..01b4088ad6 100644 --- a/update-index.c +++ b/update-index.c @@ -272,6 +272,54 @@ static void update_one(const char *path, const char *prefix, int prefix_length) die("Unable to process file %s", path); } +static void read_index_info(int line_termination) +{ + struct strbuf buf; + strbuf_init(&buf); + while (1) { + char *ptr; + unsigned char sha1[20]; + unsigned int mode; + + read_line(&buf, stdin, line_termination); + if (buf.eof) + break; + + mode = strtoul(buf.buf, &ptr, 8); + if (ptr == buf.buf || *ptr != ' ' || + get_sha1_hex(ptr + 1, sha1) || + ptr[41] != '\t') + goto bad_line; + + ptr += 42; + if (!verify_path(ptr)) { + fprintf(stderr, "Ignoring path %s\n", ptr); + continue; + } + + if (!mode) { + /* mode == 0 means there is no such path -- remove */ + if (remove_file_from_cache(ptr)) + die("git-update-index: unable to remove %s", + ptr); + } + else { + /* mode ' ' sha1 '\t' name + * ptr[-1] points at tab, + * ptr[-41] is at the beginning of sha1 + */ + ptr[-42] = ptr[-1] = 0; + if (add_cacheinfo(buf.buf, ptr-41, ptr)) + die("git-update-index: unable to update %s", + ptr); + } + continue; + + bad_line: + die("malformed index info %s", buf.buf); + } +} + int main(int argc, const char **argv) { int i, newfd, entries, has_errors = 0, line_termination = '\n'; @@ -346,6 +394,11 @@ int main(int argc, const char **argv) read_from_stdin = 1; break; } + if (!strcmp(path, "--index-info")) { + allow_add = allow_replace = allow_remove = 1; + read_index_info(line_termination); + continue; + } if (!strcmp(path, "--ignore-missing")) { not_new = 1; continue; From d1c5f2a42d7b5c0e3d3862212dea1f09809c4963 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 7 Oct 2005 03:44:18 -0700 Subject: [PATCH 039/254] Add git-am, applymbox replacement. It reorganizes the code and also has saner command line options syntax. Unlike git-applymbox, it can take more than one mailbox file from the command line, as well as reading from the standard input when '-' is specified. Signed-off-by: Junio C Hamano --- Makefile | 2 +- git-am.sh | 337 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 338 insertions(+), 1 deletion(-) create mode 100755 git-am.sh diff --git a/Makefile b/Makefile index fd4e163bad..1bdf4de75d 100644 --- a/Makefile +++ b/Makefile @@ -85,7 +85,7 @@ SCRIPT_SH = \ git-repack.sh git-request-pull.sh git-reset.sh \ git-resolve.sh git-revert.sh git-sh-setup.sh git-status.sh \ git-tag.sh git-verify-tag.sh git-whatchanged.sh git.sh \ - git-applymbox.sh git-applypatch.sh \ + git-applymbox.sh git-applypatch.sh git-am.sh \ git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \ git-merge-resolve.sh git-grep.sh diff --git a/git-am.sh b/git-am.sh new file mode 100755 index 0000000000..9e41e70313 --- /dev/null +++ b/git-am.sh @@ -0,0 +1,337 @@ +#!/bin/sh +# +# +. git-sh-setup || die "Not a git archive" + +files=$(git-diff-index --cached --name-only HEAD) || exit +if [ "$files" ]; then + echo "Dirty index: cannot apply patches (dirty: $files)" >&2 + exit 1 +fi + +usage () { + echo >&2 "usage: $0 [--signoff] [--dotest=] [--utf8] [--3way] " + echo >&2 " or, when resuming" + echo >&2 " $0 [--skip]" + exit 1; +} + +stop_here () { + echo "$1" >"$dotest/next" + exit 1 +} + +go_next () { + rm -f "$dotest/$msgnum" "$dotest/msg" "$dotest/msg-clean" \ + "$dotest/patch" "$dotest/info" + echo "$next" >"$dotest/next" + this=$next +} + +fall_back_3way () { + O_OBJECT=`cd "$GIT_OBJECT_DIRECTORY" && pwd` + + rm -fr "$dotest"/patch-merge-* + mkdir "$dotest/patch-merge-tmp-dir" + + # First see if the patch records the index info that we can use. + if git-apply --show-index-info "$dotest/patch" \ + >"$dotest/patch-merge-index-info" 2>/dev/null && + GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \ + git-update-index --index-info <"$dotest/patch-merge-index-info" && + GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \ + git-write-tree >"$dotest/patch-merge-base+" && + # index has the base tree now. + ( + cd "$dotest/patch-merge-tmp-dir" && + GIT_INDEX_FILE="../patch-merge-tmp-index" \ + GIT_OBJECT_DIRECTORY="$O_OBJECT" \ + git-apply --index <../patch + ) + then + echo Using index info to reconstruct a base tree... + mv "$dotest/patch-merge-base+" "$dotest/patch-merge-base" + mv "$dotest/patch-merge-tmp-index" "$dotest/patch-merge-index" + else + # Otherwise, try nearby trees that can be used to apply the + # patch. + ( + N=10 + + # Hoping the patch is against our recent commits... + git-rev-list --max-count=$N HEAD + + # or hoping the patch is against known tags... + git-ls-remote --tags . + ) | + while read base junk + do + # See if we have it as a tree... + git-cat-file tree "$base" >/dev/null 2>&1 || continue + + rm -fr "$dotest"/patch-merge-* && + mkdir "$dotest/patch-merge-tmp-dir" || break + ( + cd "$dotest/patch-merge-tmp-dir" && + GIT_INDEX_FILE=../patch-merge-tmp-index && + GIT_OBJECT_DIRECTORY="$O_OBJECT" && + export GIT_INDEX_FILE GIT_OBJECT_DIRECTORY && + git-read-tree "$base" && + git-apply --index && + mv ../patch-merge-tmp-index ../patch-merge-index && + echo "$base" >../patch-merge-base + ) <"$dotest/patch" 2>/dev/null && break + done + fi + + test -f "$dotest/patch-merge-index" && + his_tree=$(GIT_INDEX_FILE="$dotest/patch-merge-index" git-write-tree) && + orig_tree=$(cat "$dotest/patch-merge-base") && + rm -fr "$dotest"/patch-merge-* || exit 1 + + echo Falling back to patching base and 3-way merge... + + # This is not so wrong. Depending on which base we picked, + # orig_tree may be wildly different from ours, but his_tree + # has the same set of wildly different changes in parts the + # patch did not touch, so resolve ends up cancelling them, + # saying that we reverted all those changes. + + git-merge-resolve $orig_tree -- HEAD $his_tree || { + echo Failed to merge in the changes. + exit 1 + } +} + +prec=4 +dotest=.dotest sign= utf8= keep= skip= interactive= + +while case "$#" in 0) break;; esac +do + case "$1" in + -d=*|--d=*|--do=*|--dot=*|--dote=*|--dotes=*|--dotest=*) + dotest=`expr "$1" : '-[^=]*=\(.*\)'`; shift ;; + -d|--d|--do|--dot|--dote|--dotes|--dotest) + case "$#" in 1) usage ;; esac; shift + dotest="$1"; shift;; + + -i|--i|--in|--int|--inte|--inter|--intera|--interac|--interact|\ + --interacti|--interactiv|--interactive) + interactive=t; shift ;; + + -3|--3|--3w|--3wa|--3way) + threeway=t; shift ;; + -s|--s|--si|--sig|--sign|--signo|--signof|--signoff) + sign=t; shift ;; + -u|--u|--ut|--utf|--utf8) + utf8=t; shift ;; + -k|--k|--ke|--kee|--keep) + keep=t; shift ;; + + --sk|--ski|--skip) + skip=t; shift ;; + + --) + shift; break ;; + -*) + usage ;; + *) + break ;; + esac +done + +if test -d "$dotest" && + last=$(cat "$dotest/last") && + next=$(cat "$dotest/next") && + test $# != 0 && + test "$next" -gt "$last" +then + rm -fr "$dotest" +fi + +if test -d "$dotest" +then + test ",$#," = ",0," || + die "previous dotest directory $dotest still exists but mbox given." +else + # Make sure we are not given --skip + test ",$skip," = ,, || + die "we are not resuming." + + # Start afresh. + mkdir -p "$dotest" || exit + + # cat does the right thing for us, including '-' to mean + # standard input. + cat "$@" | + git-mailsplit -d$prec "$dotest/" >"$dotest/last" || { + rm -fr "$dotest" + exit 1 + } + + echo "$sign" >"$dotest/sign" + echo "$utf8" >"$dotest/utf8" + echo "$keep" >"$dotest/keep" + echo "$threeway" >"$dotest/3way" + echo 1 >"$dotest/next" +fi + +if test "$(cat "$dotest/utf8")" = t +then + utf8=-u +fi +if test "$(cat "$dotest/keep")" = t +then + keep=-k +fi +if test "$(cat "$dotest/sign")" = t +then + SIGNOFF=`git-var GIT_COMMITTER_IDENT | sed -e ' + s/>.*/>/ + s/^/Signed-off-by: /' + ` +else + SIGNOFF= +fi +threeway=$(cat "$dotest/3way") + +last=`cat "$dotest/last"` +this=`cat "$dotest/next"` +if test "$skip" = t +then + this=`expr "$this" + 1` +fi + +if test "$this" -gt "$last" +then + echo Nothing to do. + rm -fr "$dotest" + exit +fi + +while test "$this" -le "$last" +do + msgnum=`printf "%0${prec}d" $this` + next=`expr "$this" + 1` + test -f "$dotest/$msgnum" || { + go_next + continue + } + git-mailinfo $keep $utf8 "$dotest/msg" "$dotest/patch" \ + <"$dotest/$msgnum" >"$dotest/info" || + stop_here $this + git-stripspace < "$dotest/msg" > "$dotest/msg-clean" + + GIT_AUTHOR_NAME="$(sed -n '/^Author/ s/Author: //p' "$dotest/info")" + GIT_AUTHOR_EMAIL="$(sed -n '/^Email/ s/Email: //p' "$dotest/info")" + GIT_AUTHOR_DATE="$(sed -n '/^Date/ s/Date: //p' "$dotest/info")" + SUBJECT="$(sed -n '/^Subject/ s/Subject: //p' "$dotest/info")" + + case "$keep_subject" in -k) SUBJECT="[PATCH] $SUBJECT" ;; esac + if test '' != "$SIGNOFF" + then + LAST_SIGNED_OFF_BY=` + sed -ne '/^Signed-off-by: /p' "$dotest/msg-clean" | + tail -n 1 + ` + ADD_SIGNOFF=$(test "$LAST_SIGNED_OFF_BY" = "$SIGNOFF" || { + test '' = "$LAST_SIGNED_OFF_BY" && echo + echo "$SIGNOFF" + }) + else + ADD_SIGNOFF= + fi + { + echo "$SUBJECT" + if test -s "$dotest/msg-clean" + then + echo + cat "$dotest/msg-clean" + fi + if test '' != "$ADD_SIGNOFF" + then + echo "$ADD_SIGNOFF" + fi + } >"$dotest/final-commit" + + if test "$interactive" = t + then + action=again + while test "$action" = again + do + echo "Commit Body is:" + echo "--------------------------" + cat "$dotest/final-commit" + echo "--------------------------" + echo -n "Apply? [y]es/[n]o/[e]dit/[a]ccept all " + read reply + case "$reply" in + y*|Y*) action=yes ;; + a*|A*) action=yes interactive= ;; + n*|N*) action=skip ;; + e*|E*) "${VISUAL:-${EDITOR:-vi}}" "$dotest/final-commit" + action=again ;; + esac + done + else + action=yes + fi + + if test $action = skip + then + go_next + continue + fi + + if test -x "$GIT_DIR"/hooks/applypatch-msg + then + "$GIT_DIR"/hooks/applypatch-msg "$dotest/final-commit" || + stop_here $this + fi + + echo + echo "Applying '$SUBJECT'" + echo + + git-apply --index "$dotest/patch"; apply_status=$? + if test $apply_status = 1 && test "$threeway" = t + then + (fall_back_3way) || stop_here $this + + # Applying the patch to an earlier tree and merging the + # result may have produced the same tree as ours. + if test '' = "$(git-diff-index --cached --name-only -z HEAD)" + then + echo No changes -- Patch already applied. + go_next + continue + fi + fi + if test $apply_status != 0 + then + echo Patch failed at $msgnum. + stop_here $this + fi + + if test -x "$GIT_DIR"/hooks/pre-applypatch + then + "$GIT_DIR"/hooks/pre-applypatch || stop_here $this + fi + + tree=$(git-write-tree) && + echo Wrote tree $tree && + parent=$(git-rev-parse --verify HEAD) && + commit=$(git-commit-tree $tree -p $parent <"$dotest/final-commit") && + echo Committed: $commit && + git-update-ref HEAD $commit $parent || + stop_here $this + + if test -x "$GIT_DIR"/hooks/post-applypatch + then + "$GIT_DIR"/hooks/post-applypatch + fi + + go_next +done + +rm -fr "$dotest" From 230f13225df8b7e7eb0acc91a8c630f9e84967c1 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 8 Oct 2005 15:54:01 -0700 Subject: [PATCH 040/254] Create object subdirectories on demand This makes it possible to have a "sparse" git object subdirectory structure, something that has become much more attractive now that people use pack-files all the time. As a result of pack-files, a git object directory doesn't necessarily have any individual objects lying around, and in that case it's just wasting space to keep the empty first-level object directories around: on many filesystems the 256 empty directories will be aboue 1MB of diskspace. Even more importantly, after you re-pack a project that _used_ to be unpacked, you could be left with huge directories that no longer contain anything, but that waste space and take time to look through. With this change, "git prune-packed" can just do an rmdir() on the directories, and they'll get removed if empty, and re-created on demand. This patch also tries to fix up "write_sha1_from_fd()" to use the new common infrastructure for creating the object files, closing a hole where we might otherwise leave half-written objects in the object database. [jc: I unoptimized the part that really removes the fan-out directories to ease transition. init-db still wastes 1MB of diskspace to hold 256 empty fan-outs, and prune-packed rmdir()'s the grown but empty directories, but runs mkdir() immediately after that -- reducing the saving from 150KB to 146KB. These parts will be re-introduced when everybody has the on-demand capability.] Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- daemon.c | 2 +- fsck-objects.c | 5 +-- git-rename.perl | 2 +- git-sh-setup.sh | 2 +- prune-packed.c | 5 ++- sha1_file.c | 114 ++++++++++++++++++++++++++++++++--------------- t/t0000-basic.sh | 2 +- 7 files changed, 88 insertions(+), 44 deletions(-) diff --git a/daemon.c b/daemon.c index f285a8c98c..11fa3ed11f 100644 --- a/daemon.c +++ b/daemon.c @@ -142,7 +142,7 @@ static int upload(char *dir, int dirlen) * is ok with us doing this. */ if ((!export_all_trees && access("git-daemon-export-ok", F_OK)) || - access("objects/00", X_OK) || + access("objects/", X_OK) || access("HEAD", R_OK)) { logerror("Not a valid git-daemon-enabled repository: '%s'", dir); return -1; diff --git a/fsck-objects.c b/fsck-objects.c index 65cec7d12b..17d05363e0 100644 --- a/fsck-objects.c +++ b/fsck-objects.c @@ -329,9 +329,8 @@ static int fsck_dir(int i, char *path) DIR *dir = opendir(path); struct dirent *de; - if (!dir) { - return error("missing sha1 directory '%s'", path); - } + if (!dir) + return 0; while ((de = readdir(dir)) != NULL) { char name[100]; diff --git a/git-rename.perl b/git-rename.perl index a28c8c83bb..3b1127b1b2 100755 --- a/git-rename.perl +++ b/git-rename.perl @@ -15,7 +15,7 @@ sub usage($); my $GIT_DIR = $ENV{'GIT_DIR'} || ".git"; unless ( -d $GIT_DIR && -d $GIT_DIR . "/objects" && - -d $GIT_DIR . "/objects/00" && -d $GIT_DIR . "/refs") { + -d $GIT_DIR . "/objects/" && -d $GIT_DIR . "/refs") { usage("Git repository not found."); } diff --git a/git-sh-setup.sh b/git-sh-setup.sh index a0172686a9..dbb98842bf 100755 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -22,4 +22,4 @@ refs/*) : ;; *) false ;; esac && [ -d "$GIT_DIR/refs" ] && -[ -d "$GIT_OBJECT_DIRECTORY/00" ] +[ -d "$GIT_OBJECT_DIRECTORY/" ] diff --git a/prune-packed.c b/prune-packed.c index 5306e8e5ef..73f0f3a462 100644 --- a/prune-packed.c +++ b/prune-packed.c @@ -26,6 +26,9 @@ static void prune_dir(int i, DIR *dir, char *pathname, int len) else if (unlink(pathname) < 0) error("unable to unlink %s", pathname); } + pathname[len] = 0; + if (rmdir(pathname)) + mkdir(pathname, 0777); } static void prune_packed_objects(void) @@ -46,7 +49,7 @@ static void prune_packed_objects(void) sprintf(pathname + len, "%02x/", i); d = opendir(pathname); if (!d) - die("unable to open %s", pathname); + continue; prune_dir(i, d, pathname, len + 3); closedir(d); } diff --git a/sha1_file.c b/sha1_file.c index 287f618827..baaa4c00da 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1248,6 +1248,73 @@ char *write_sha1_file_prepare(void *buf, return sha1_file_name(sha1); } +/* + * Link the tempfile to the final place, possibly creating the + * last directory level as you do so. + * + * Returns the errno on failure, 0 on success. + */ +static int link_temp_to_file(const char *tmpfile, char *filename) +{ + int ret; + + if (!link(tmpfile, filename)) + return 0; + + /* + * Try to mkdir the last path component if that failed + * with an ENOENT. + * + * Re-try the "link()" regardless of whether the mkdir + * succeeds, since a race might mean that somebody + * else succeeded. + */ + ret = errno; + if (ret == ENOENT) { + char *dir = strrchr(filename, '/'); + if (dir) { + *dir = 0; + mkdir(filename, 0777); + *dir = '/'; + if (!link(tmpfile, filename)) + return 0; + ret = errno; + } + } + return ret; +} + +/* + * Move the just written object into its final resting place + */ +static int move_temp_to_file(const char *tmpfile, char *filename) +{ + int ret = link_temp_to_file(tmpfile, filename); + if (ret) { + /* + * Coda hack - coda doesn't like cross-directory links, + * so we fall back to a rename, which will mean that it + * won't be able to check collisions, but that's not a + * big deal. + * + * When this succeeds, we just return 0. We have nothing + * left to unlink. + */ + if (ret == EXDEV && !rename(tmpfile, filename)) + return 0; + } + unlink(tmpfile); + if (ret) { + if (ret != EEXIST) { + fprintf(stderr, "unable to write sha1 filename %s: %s", filename, strerror(ret)); + return -1; + } + /* FIXME!!! Collision check here ? */ + } + + return 0; +} + int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *returnsha1) { int size; @@ -1257,7 +1324,7 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha char *filename; static char tmpfile[PATH_MAX]; unsigned char hdr[50]; - int fd, hdrlen, ret; + int fd, hdrlen; /* Normally if we have it in the pack then we do not bother writing * it out into .git/objects/??/?{38} file. @@ -1320,32 +1387,7 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha close(fd); free(compressed); - ret = link(tmpfile, filename); - if (ret < 0) { - ret = errno; - - /* - * Coda hack - coda doesn't like cross-directory links, - * so we fall back to a rename, which will mean that it - * won't be able to check collisions, but that's not a - * big deal. - * - * When this succeeds, we just return 0. We have nothing - * left to unlink. - */ - if (ret == EXDEV && !rename(tmpfile, filename)) - return 0; - } - unlink(tmpfile); - if (ret) { - if (ret != EEXIST) { - fprintf(stderr, "unable to write sha1 filename %s: %s", filename, strerror(ret)); - return -1; - } - /* FIXME!!! Collision check here ? */ - } - - return 0; + return move_temp_to_file(tmpfile, filename); } int write_sha1_to_fd(int fd, const unsigned char *sha1) @@ -1420,8 +1462,7 @@ int write_sha1_to_fd(int fd, const unsigned char *sha1) int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer, size_t bufsize, size_t *bufposn) { - char *filename = sha1_file_name(sha1); - + char tmpfile[PATH_MAX]; int local; z_stream stream; unsigned char real_sha1[20]; @@ -1429,10 +1470,11 @@ int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer, int ret; SHA_CTX c; - local = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666); + snprintf(tmpfile, sizeof(tmpfile), "%s/obj_XXXXXX", get_object_directory()); + local = mkstemp(tmpfile); if (local < 0) - return error("Couldn't open %s\n", filename); + return error("Couldn't open %s for %s\n", tmpfile, sha1_to_hex(sha1)); memset(&stream, 0, sizeof(stream)); @@ -1462,7 +1504,7 @@ int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer, size = read(fd, buffer + *bufposn, bufsize - *bufposn); if (size <= 0) { close(local); - unlink(filename); + unlink(tmpfile); if (!size) return error("Connection closed?"); perror("Reading from connection"); @@ -1475,15 +1517,15 @@ int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer, close(local); SHA1_Final(real_sha1, &c); if (ret != Z_STREAM_END) { - unlink(filename); + unlink(tmpfile); return error("File %s corrupted", sha1_to_hex(sha1)); } if (memcmp(sha1, real_sha1, 20)) { - unlink(filename); + unlink(tmpfile); return error("File %s has bad hash\n", sha1_to_hex(sha1)); } - - return 0; + + return move_temp_to_file(tmpfile, sha1_file_name(sha1)); } int has_pack_index(const unsigned char *sha1) diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index bd940bd09b..5c5f854858 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -28,7 +28,7 @@ test_expect_success \ '.git/objects should be empty after git-init-db in an empty repo.' \ 'cmp -s /dev/null should-be-empty' -# also it should have 258 subdirectories; 256 fan-out, pack, and info. +# also it should have 258 subdirectories; 256 fan-out anymore, pack, and info. # 259 is counting "objects" itself find .git/objects -type d -print >full-of-directories test_expect_success \ From f22ca7c50d79fcfd769ddcda988e0981fb883a16 Mon Sep 17 00:00:00 2001 From: "robfitz@273k.net" Date: Sat, 8 Oct 2005 15:54:35 -0700 Subject: [PATCH 041/254] Reduce memory usage in git-update-server-info. Modify parse_object_cheap() to also free all the entries from the tree data structures. Signed-off-by: Robert Fitzsimons Signed-off-by: Junio C Hamano --- server-info.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/server-info.c b/server-info.c index a9e5607f2f..3c08a288db 100644 --- a/server-info.c +++ b/server-info.c @@ -59,6 +59,16 @@ static struct object *parse_object_cheap(const unsigned char *sha1) struct commit *commit = (struct commit *)o; free(commit->buffer); commit->buffer = NULL; + } else if (o->type == tree_type) { + struct tree *tree = (struct tree *)o; + struct tree_entry_list *e, *n; + for (e = tree->entries; e; e = n) { + free(e->name); + e->name = NULL; + n = e->next; + free(e); + } + tree->entries = NULL; } return o; } From d119e3de13ea1493107bd57381d0ce9c9dd90976 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 8 Oct 2005 15:54:35 -0700 Subject: [PATCH 042/254] Also use 'track_object_refs = 0' in update-server-info. Signed-off-by: Junio C Hamano --- update-server-info.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/update-server-info.c b/update-server-info.c index e824f62eaf..b70856373f 100644 --- a/update-server-info.c +++ b/update-server-info.c @@ -1,4 +1,5 @@ #include "cache.h" +#include "object.h" static const char update_server_info_usage[] = "git-update-server-info [--force]"; @@ -7,6 +8,8 @@ int main(int ac, char **av) { int i; int force = 0; + track_object_refs = 0; + for (i = 1; i < ac; i++) { if (av[i][0] == '-') { if (!strcmp("--force", av[i]) || From 730d48a2ef88a7fb7aa4409d40b1e6964a93267f Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 8 Oct 2005 15:54:36 -0700 Subject: [PATCH 043/254] [PATCH] If NO_MMAP is defined, fake mmap() and munmap() Since some platforms do not support mmap() at all, and others do only just so, this patch introduces the option to fake mmap() and munmap() by malloc()ing and read()ing explicitely. Signed-off-by: Johannes Schindelin --- Makefile | 6 +++ cache.h | 16 +++++++ compat/mmap.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++ mailsplit.c | 1 - 4 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 compat/mmap.c diff --git a/Makefile b/Makefile index 1bdf4de75d..7ca77cf2af 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,8 @@ # Define NEEDS_SOCKET if linking with libc is not enough (SunOS, # Patrick Mauritz). # +# Define NO_MMAP if you want to avoid mmap. +# # Define WITH_OWN_SUBPROCESS_PY if you want to use with python 2.3. # # Define NO_IPV6 if you lack IPv6 support and getaddrinfo(). @@ -258,6 +260,10 @@ ifdef NO_STRCASESTR DEFINES += -Dstrcasestr=gitstrcasestr LIB_OBJS += compat/strcasestr.o endif +ifdef NO_MMAP + DEFINES += -Dmmap=gitfakemmap -Dmunmap=gitfakemunmap -DNO_MMAP + LIB_OBJS += compat/mmap.o +endif ifdef NO_IPV6 DEFINES += -DNO_IPV6 -Dsockaddr_storage=sockaddr_in endif diff --git a/cache.h b/cache.h index 514adb8f8e..5987d4c125 100644 --- a/cache.h +++ b/cache.h @@ -11,7 +11,9 @@ #include #include #include +#ifndef NO_MMAP #include +#endif #include #include #include @@ -356,4 +358,18 @@ extern void packed_object_info_detail(struct pack_entry *, char *, unsigned long /* Dumb servers support */ extern int update_server_info(int); +#ifdef NO_MMAP + +#ifndef PROT_READ +#define PROT_READ 1 +#define PROT_WRITE 2 +#define MAP_PRIVATE 1 +#define MAP_FAILED ((void*)-1) +#endif + +extern void *gitfakemmap(void *start, size_t length, int prot , int flags, int fd, off_t offset); +extern int gitfakemunmap(void *start, size_t length); + +#endif + #endif /* CACHE_H */ diff --git a/compat/mmap.c b/compat/mmap.c new file mode 100644 index 0000000000..fca6321ce0 --- /dev/null +++ b/compat/mmap.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include "../cache.h" + +typedef struct fakemmapwritable { + void *start; + size_t length; + int fd; + off_t offset; + struct fakemmapwritable *next; +} fakemmapwritable; + +static fakemmapwritable *writablelist = NULL; + +void *gitfakemmap(void *start, size_t length, int prot , int flags, int fd, off_t offset) +{ + int n = 0; + + if(start != NULL) + die("Invalid usage of gitfakemmap."); + + if(lseek(fd, offset, SEEK_SET)<0) { + errno = EINVAL; + return MAP_FAILED; + } + + start = xmalloc(length); + if(start == NULL) { + errno = ENOMEM; + return MAP_FAILED; + } + + while(n < length) { + int count = read(fd, start+n, length-n); + + if(count == 0) { + memset(start+n, 0, length-n); + break; + } + + if(count < 0) { + free(start); + errno = EACCES; + return MAP_FAILED; + } + + n += count; + } + + if(prot & PROT_WRITE) { + fakemmapwritable *next = xmalloc(sizeof(fakemmapwritable)); + next->start = start; + next->length = length; + next->fd = dup(fd); + next->offset = offset; + next->next = writablelist; + writablelist = next; + } + + return start; +} + +int gitfakemunmap(void *start, size_t length) +{ + fakemmapwritable *writable = writablelist, *before = NULL; + + while(writable && (writable->start > start + length + || writable->start + writable->length < start)) { + before = writable; + writable = writable->next; + } + + if(writable) { + /* need to write back the contents */ + int n = 0; + + if(writable->start != start || writable->length != length) + die("fakemmap does not support partial write back."); + + if(lseek(writable->fd, writable->offset, SEEK_SET) < 0) { + free(start); + errno = EBADF; + return -1; + } + + while(n < length) { + int count = write(writable->fd, start + n, length - n); + + if(count < 0) { + errno = EINVAL; + return -1; + } + + n += count; + } + + close(writable->fd); + + if(before) + before->next = writable->next; + else + writablelist = writable->next; + + free(writable); + } + + free(start); + + return 0; +} + diff --git a/mailsplit.c b/mailsplit.c index 7981f87a72..0f8100dcca 100644 --- a/mailsplit.c +++ b/mailsplit.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include From f48000fcbe1009c18f1cc46e56cde2cb632071fa Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 8 Oct 2005 15:54:36 -0700 Subject: [PATCH 044/254] Yank writing-back support from gitfakemmap. We do not write through our use of mmap(), so make sure callers pass MAP_PRIVATE and remove support for writing changes back. Signed-off-by: Junio C Hamano --- compat/mmap.c | 75 +++++---------------------------------------------- 1 file changed, 6 insertions(+), 69 deletions(-) diff --git a/compat/mmap.c b/compat/mmap.c index fca6321ce0..a051c4767d 100644 --- a/compat/mmap.c +++ b/compat/mmap.c @@ -4,43 +4,33 @@ #include #include "../cache.h" -typedef struct fakemmapwritable { - void *start; - size_t length; - int fd; - off_t offset; - struct fakemmapwritable *next; -} fakemmapwritable; - -static fakemmapwritable *writablelist = NULL; - void *gitfakemmap(void *start, size_t length, int prot , int flags, int fd, off_t offset) { int n = 0; - if(start != NULL) + if (start != NULL || !(flags & MAP_PRIVATE)) die("Invalid usage of gitfakemmap."); - if(lseek(fd, offset, SEEK_SET)<0) { + if (lseek(fd, offset, SEEK_SET) < 0) { errno = EINVAL; return MAP_FAILED; } start = xmalloc(length); - if(start == NULL) { + if (start == NULL) { errno = ENOMEM; return MAP_FAILED; } - while(n < length) { + while (n < length) { int count = read(fd, start+n, length-n); - if(count == 0) { + if (count == 0) { memset(start+n, 0, length-n); break; } - if(count < 0) { + if (count < 0) { free(start); errno = EACCES; return MAP_FAILED; @@ -49,65 +39,12 @@ void *gitfakemmap(void *start, size_t length, int prot , int flags, int fd, off_ n += count; } - if(prot & PROT_WRITE) { - fakemmapwritable *next = xmalloc(sizeof(fakemmapwritable)); - next->start = start; - next->length = length; - next->fd = dup(fd); - next->offset = offset; - next->next = writablelist; - writablelist = next; - } - return start; } int gitfakemunmap(void *start, size_t length) { - fakemmapwritable *writable = writablelist, *before = NULL; - - while(writable && (writable->start > start + length - || writable->start + writable->length < start)) { - before = writable; - writable = writable->next; - } - - if(writable) { - /* need to write back the contents */ - int n = 0; - - if(writable->start != start || writable->length != length) - die("fakemmap does not support partial write back."); - - if(lseek(writable->fd, writable->offset, SEEK_SET) < 0) { - free(start); - errno = EBADF; - return -1; - } - - while(n < length) { - int count = write(writable->fd, start + n, length - n); - - if(count < 0) { - errno = EINVAL; - return -1; - } - - n += count; - } - - close(writable->fd); - - if(before) - before->next = writable->next; - else - writablelist = writable->next; - - free(writable); - } - free(start); - return 0; } From d2b8593fd3754cf2e0b9a121fe6ba63bfefa3a47 Mon Sep 17 00:00:00 2001 From: Kai Ruemmler Date: Sat, 8 Oct 2005 15:54:37 -0700 Subject: [PATCH 045/254] make $prefix available for sub-makefiles exports $prefix and makes Documentation/Makefile following it also. Signed-off-by: Kai Ruemmler Signed-off-by: Junio C Hamano --- Documentation/Makefile | 4 ++-- Makefile | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/Makefile b/Documentation/Makefile index bb21d6af44..3cfa360a9e 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -17,14 +17,14 @@ DOC_HTML += $(patsubst %,%.html,$(ARTICLES) $(SP_ARTICLES)) DOC_MAN1=$(patsubst %.txt,%.1,$(MAN1_TXT)) DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT)) -prefix=$(HOME) +prefix?=$(HOME) bin=$(prefix)/bin mandir=$(prefix)/man man1=$(mandir)/man1 man7=$(mandir)/man7 # DESTDIR= -INSTALL=install +INSTALL?=install # # Please note that there is a minor bug in asciidoc. diff --git a/Makefile b/Makefile index 7ca77cf2af..bcda943273 100644 --- a/Makefile +++ b/Makefile @@ -293,7 +293,7 @@ SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ $(patsubst %.py,%,$(SCRIPT_PYTHON)) \ gitk -export TAR INSTALL DESTDIR SHELL_PATH +export prefix TAR INSTALL DESTDIR SHELL_PATH ### Build rules all: $(PROGRAMS) $(SCRIPTS) From f7c153431b4049e7697664dee4a3d71013422f9d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 9 Oct 2005 12:52:35 -0700 Subject: [PATCH 046/254] Makefile: avoid error message from 'uname -o' The platform specific tweaking part was using 'uname -o' which is not always available. Squelch error message from it. It was suggested to chain the if..else, but I chose not to, because maintaining the nested if..else if..else..endif endif to match is a pain. If we had "elif", things would have been different, though. While we are at it, try not to invoke 'uname -s' for each platform candidate. Signed-off-by: Junio C Hamano --- Makefile | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index bcda943273..a201187395 100644 --- a/Makefile +++ b/Makefile @@ -166,11 +166,19 @@ LIBS += -lz # # Platform specific tweaks # -ifeq ($(shell uname -s),Darwin) + +# We choose to avoid "if .. else if .. else .. endif endif" +# because maintaining the nesting to match is a pain. If +# we had "elif" things would have been much nicer... +uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') +uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not') +uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not') + +ifeq ($(uname_S),Darwin) NEEDS_SSL_WITH_CRYPTO = YesPlease NEEDS_LIBICONV = YesPlease endif -ifeq ($(shell uname -s),SunOS) +ifeq ($(uname_S),SunOS) NEEDS_SOCKET = YesPlease NEEDS_NSL = YesPlease SHELL_PATH = /bin/bash @@ -180,20 +188,20 @@ ifeq ($(shell uname -s),SunOS) TAR = gtar PLATFORM_DEFINES += -D__EXTENSIONS__ endif -ifeq ($(shell uname -o),Cygwin) +ifeq ($(uname_O),Cygwin) NO_STRCASESTR = YesPlease NEEDS_LIBICONV = YesPlease NO_IPV6 = YesPlease X = .exe PLATFORM_DEFINES += -DUSE_SYMLINK_HEAD=0 endif -ifneq (,$(findstring arm,$(shell uname -m))) - ARM_SHA1 = YesPlease -endif -ifeq ($(shell uname -s),OpenBSD) +ifeq ($(uname_S),OpenBSD) NEEDS_LIBICONV = YesPlease PLATFORM_DEFINES += -I/usr/local/include -L/usr/local/lib endif +ifneq (,$(findstring arm,$(uname_M))) + ARM_SHA1 = YesPlease +endif ifndef NO_CURL ifdef CURLDIR From f8e2c54c9a17af3319e96db1d9e97ace36ae6831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Santi=5FB=C3=A9jar?= Date: Sun, 9 Oct 2005 17:30:19 -0700 Subject: [PATCH 047/254] Write .editmsg in GIT_DIR to avoid being in git-status. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It appears in the git-status output during a git-commit if you have something in info/exclude. Also for .cmitmsg and .cmitchk to make git-commit work in read-only working trees. [jc: while we are at it, I removed the use of .cmitchk temporary file which was not necessary, and renamed them -- they are out of way now and do not have to be dotfiles anymore.] Signed-off-by: Santi Béjar Signed-off-by: Junio C Hamano --- git-commit.sh | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/git-commit.sh b/git-commit.sh index 591fcdceb1..5bdee54a46 100755 --- a/git-commit.sh +++ b/git-commit.sh @@ -129,7 +129,7 @@ then elif test "$use_commit" != "" then git-cat-file commit "$use_commit" | sed -e '1,/^$/d' -fi | git-stripspace >.editmsg +fi | git-stripspace >"$GIT_DIR"/COMMIT_EDITMSG case "$signoff" in t) @@ -139,7 +139,7 @@ t) s/>.*/>/ s/^/Signed-off-by: / ' - } >>.editmsg + } >>"$GIT_DIR"/COMMIT_EDITMSG ;; esac @@ -153,7 +153,7 @@ if [ -f "$GIT_DIR/MERGE_HEAD" ]; then echo "# $GIT_DIR/MERGE_HEAD" echo "# and try again" echo "#" -fi >>.editmsg +fi >>"$GIT_DIR"/COMMIT_EDITMSG PARENTS="-p HEAD" if GIT_DIR="$GIT_DIR" git-rev-parse --verify HEAD >/dev/null 2>&1 @@ -197,16 +197,16 @@ else fi PARENTS="" fi -git-status >>.editmsg +git-status >>"$GIT_DIR"/COMMIT_EDITMSG if [ "$?" != "0" -a ! -f "$GIT_DIR/MERGE_HEAD" ] then - rm -f .editmsg + rm -f "$GIT_DIR/COMMIT_EDITMSG" git-status exit 1 fi case "$no_edit" in '') - ${VISUAL:-${EDITOR:-vi}} .editmsg + ${VISUAL:-${EDITOR:-vi}} "$GIT_DIR/COMMIT_EDITMSG" ;; esac @@ -214,16 +214,20 @@ case "$verify" in t) if test -x "$GIT_DIR"/hooks/commit-msg then - "$GIT_DIR"/hooks/commit-msg .editmsg || exit + "$GIT_DIR"/hooks/commit-msg "$GIT_DIR"/COMMIT_EDITMSG || exit fi esac -grep -v '^#' < .editmsg | git-stripspace > .cmitmsg -grep -v -i '^Signed-off-by' .cmitmsg >.cmitchk -if test -s .cmitchk +grep -v '^#' < "$GIT_DIR"/COMMIT_EDITMSG | +git-stripspace > "$GIT_DIR"/COMMIT_MSG + +if cnt=`grep -v -i '^Signed-off-by' "$GIT_DIR"/COMMIT_MSG | + git-stripspace | + wc -l` && + test 0 -lt $cnt then tree=$(git-write-tree) && - commit=$(cat .cmitmsg | git-commit-tree $tree $PARENTS) && + commit=$(cat "$GIT_DIR"/COMMIT_MSG | git-commit-tree $tree $PARENTS) && git-update-ref HEAD $commit $current && rm -f -- "$GIT_DIR/MERGE_HEAD" else @@ -231,7 +235,7 @@ else false fi ret="$?" -rm -f .cmitmsg .editmsg .cmitchk +rm -f "$GIT_DIR/COMMIT_MSG" "$GIT_DIR/COMMIT_EDITMSG" if test -x "$GIT_DIR"/hooks/post-commit && test "$ret" = 0 then From 89764f5d8b0ca8600e3a200e9f863c3c7a3ff5e8 Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Mon, 10 Oct 2005 11:15:09 +0200 Subject: [PATCH 048/254] cvsimport: report merge parents Matching and reporting merge parents happens in a subprocess. Re-open stdout before redirecting stdout to the pipe, so that printing verbose messages doesn't go to the wrong place. Signed-Off-By: Matthias Urlichs --- git-cvsimport.perl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/git-cvsimport.perl b/git-cvsimport.perl index f35c0d045b..cc0eed2946 100755 --- a/git-cvsimport.perl +++ b/git-cvsimport.perl @@ -567,6 +567,7 @@ my $commit = sub { unless($pid) { $pr->writer(); $pw->reader(); + open(OUT,">&STDOUT"); dup2($pw->fileno(),0); dup2($pr->fileno(),1); $pr->close(); @@ -584,10 +585,9 @@ my $commit = sub { if ( -e "$git_dir/refs/heads/$mparent") { $mparent = get_headref($mparent, $git_dir); push @par, '-p', $mparent; - # printing here breaks import # - # # print "Merge parent branch: $mparent\n" if $opt_v; + print OUT "Merge parent branch: $mparent\n" if $opt_v; } - } + } } exec("env", From eaf718f3ece277462de4e47391e5a965bbbaa297 Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Mon, 10 Oct 2005 11:40:43 +0200 Subject: [PATCH 049/254] New: git-svnimport. As the name suggests, this script imports from SVN. Only "normal" SVN repositories (with single trunk/, branches/, and tags/ subdrectories) are supported. Incremental imports require preserving the file .git/svn2git. Signed-Off-by: Matthias Urlichs --- Documentation/git-svnimport.txt | 99 +++++ Makefile | 3 +- git-svnimport.perl | 671 ++++++++++++++++++++++++++++++++ 3 files changed, 772 insertions(+), 1 deletion(-) create mode 100644 Documentation/git-svnimport.txt create mode 100755 git-svnimport.perl diff --git a/Documentation/git-svnimport.txt b/Documentation/git-svnimport.txt new file mode 100644 index 0000000000..be03a65f81 --- /dev/null +++ b/Documentation/git-svnimport.txt @@ -0,0 +1,99 @@ +git-svnimport(1) +================ +v0.1, July 2005 + +NAME +---- +git-svnimport - Import a SVN repository into git + + +SYNOPSIS +-------- +'git-svnimport' [ -o ] [ -h ] [ -v ] + [ -C ] [ -i ] [ -u ] + [ -b branch_subdir ] [ -t trunk_subdir ] [ -T tag_subdir ] + [ -m ] [ -M regex ] [ ] + + +DESCRIPTION +----------- +Imports a SVN repository into git. It will either create a new +repository, or incrementally import into an existing one. + +SVN access is done by the SVN:: Perl module. + +git-svnimport assumes that SVN repositories are organized into one +"trunk" directory where the main development happens, "branch/FOO" +directories for branches, and "/tags/FOO" directories for tags. +Other subdirectories are ignored. + +git-svnimport creates a file ".git/svn2git", which is required for +incremental SVN imports. + +OPTIONS +------- +-C :: + The GIT repository to import to. If the directory doesn't + exist, it will be created. Default is the current directory. + +-i:: + Import-only: don't perform a checkout after importing. This option + ensures the working directory and cache remain untouched and will + not create them if they do not exist. + +-t :: + Name the SVN trunk. Default "trunk". + +-T :: + Name the SVN subdirectory for tags. Default "tags". + +-b :: + Name the SVN subdirectory for branches. Default "branches". + +-o :: + The 'trunk' branch from SVN is imported to the 'origin' branch within + the git repository. Use this option if you want to import into a + different branch. + +-m:: + Attempt to detect merges based on the commit message. This option + will enable default regexes that try to capture the name source + branch name from the commit message. + +-M :: + Attempt to detect merges based on the commit message with a custom + regex. It can be used with -m to also see the default regexes. + You must escape forward slashes. + +-v:: + Verbosity: let 'svnimport' report what it is doing. + +:: + The URL of the SVN module you want to import. For local + repositories, use "file:///absolute/path". + +-h:: + Print a short usage message and exit. + +OUTPUT +------ +If '-v' is specified, the script reports what it is doing. + +Otherwise, success is indicated the Unix way, i.e. by simply exiting with +a zero exit status. + +Author +------ +Written by Matthias Urlichs , with help from +various participants of the git-list . + +Based on a cvs2git script by the same author. + +Documentation +-------------- +Documentation by Matthias Urlichs . + +GIT +--- +Part of the gitlink:git[7] suite + diff --git a/Makefile b/Makefile index fd4e163bad..30fda9ec7e 100644 --- a/Makefile +++ b/Makefile @@ -91,7 +91,8 @@ SCRIPT_SH = \ SCRIPT_PERL = \ git-archimport.perl git-cvsimport.perl git-relink.perl \ - git-rename.perl git-shortlog.perl git-fmt-merge-msg.perl + git-rename.perl git-shortlog.perl git-fmt-merge-msg.perl \ + git-svnimport-perl SCRIPT_PYTHON = \ git-merge-recursive.py diff --git a/git-svnimport.perl b/git-svnimport.perl new file mode 100755 index 0000000000..08645f7ebb --- /dev/null +++ b/git-svnimport.perl @@ -0,0 +1,671 @@ +#!/usr/bin/perl -w + +# This tool is copyright (c) 2005, Matthias Urlichs. +# It is released under the Gnu Public License, version 2. +# +# The basic idea is to pull and analyze SVN changes. +# +# Checking out the files is done by a single long-running CVS connection +# / server process. +# +# The head revision is on branch "origin" by default. +# You can change that with the '-o' option. + +require v5.8.0; # for shell-safe open("-|",LIST) +use strict; +use warnings; +use Getopt::Std; +use File::Spec; +use File::Temp qw(tempfile); +use File::Path qw(mkpath); +use File::Basename qw(basename dirname); +use Time::Local; +use IO::Pipe; +use POSIX qw(strftime dup2); +use IPC::Open2; +use SVN::Core; +use SVN::Ra; + +$SIG{'PIPE'}="IGNORE"; +$ENV{'TZ'}="UTC"; + +our($opt_h,$opt_o,$opt_v,$opt_u,$opt_C,$opt_i,$opt_m,$opt_M,$opt_t,$opt_T,$opt_b); + +sub usage() { + print STDERR <; + chomp $cvs_tree; + close $f; +} else { + usage(); +} + +our @mergerx = (); +if ($opt_m) { + @mergerx = ( qr/\W(?:from|of|merge|merging|merged) (\w+)/i ); +} +if ($opt_M) { + push (@mergerx, qr/$opt_M/); +} + +select(STDERR); $|=1; select(STDOUT); + + +package SVNconn; +# Basic SVN connection. +# We're only interested in connecting and downloading, so ... + +use File::Spec; +use File::Temp qw(tempfile); +use POSIX qw(strftime dup2); + +sub new { + my($what,$repo) = @_; + $what=ref($what) if ref($what); + + my $self = {}; + $self->{'buffer'} = ""; + bless($self,$what); + + $repo =~ s#/+$##; + $self->{'fullrep'} = $repo; + $self->conn(); + + $self->{'lines'} = undef; + + return $self; +} + +sub conn { + my $self = shift; + my $repo = $self->{'fullrep'}; + my $s = SVN::Ra->new($repo); + + die "SVN connection to $repo: $!\n" unless defined $s; + $self->{'svn'} = $s; + $self->{'repo'} = $repo; + $self->{'maxrev'} = $s->get_latest_revnum(); +} + +sub file { + my($self,$path,$rev) = @_; + my $res; + + my ($fh, $name) = tempfile('gitsvn.XXXXXX', + DIR => File::Spec->tmpdir(), UNLINK => 1); + + $self->{'svn'}->get_file($path,$rev,$fh) or do { + # retry + $self->conn(); + $self->{'svn'}->get_file($path,$rev,$fh) + or die "$rev: No file $path at $rev\n"; + }; + close ($fh); + + return ($name, $res); +} + + +package main; + +my $svn = SVNconn->new($cvs_tree); + + +sub pdate($) { + my($d) = @_; + $d =~ m#(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)# + or die "Unparseable date: $d\n"; + my $y=$1; $y-=1900 if $y>1900; + return timegm($6||0,$5,$4,$3,$2-1,$y); +} + +sub pmode($) { + my($mode) = @_; + my $m = 0; + my $mm = 0; + my $um = 0; + for my $x(split(//,$mode)) { + if($x eq ",") { + $m |= $mm&$um; + $mm = 0; + $um = 0; + } elsif($x eq "u") { $um |= 0700; + } elsif($x eq "g") { $um |= 0070; + } elsif($x eq "o") { $um |= 0007; + } elsif($x eq "r") { $mm |= 0444; + } elsif($x eq "w") { $mm |= 0222; + } elsif($x eq "x") { $mm |= 0111; + } elsif($x eq "=") { # do nothing + } else { die "Unknown mode: $mode\n"; + } + } + $m |= $mm&$um; + return $m; +} + +sub getwd() { + my $pwd = `pwd`; + chomp $pwd; + return $pwd; +} + + +sub get_headref($$) { + my $name = shift; + my $git_dir = shift; + my $sha; + + if (open(C,"$git_dir/refs/heads/$name")) { + chomp($sha = ); + close(C); + length($sha) == 40 + or die "Cannot get head id for $name ($sha): $!\n"; + } + return $sha; +} + + +-d $git_tree + or mkdir($git_tree,0777) + or die "Could not create $git_tree: $!"; +chdir($git_tree); + +my $orig_branch = ""; +my $forward_master = 0; +my %branches; + +my $git_dir = $ENV{"GIT_DIR"} || ".git"; +$git_dir = getwd()."/".$git_dir unless $git_dir =~ m#^/#; +$ENV{"GIT_DIR"} = $git_dir; +my $orig_git_index; +$orig_git_index = $ENV{GIT_INDEX_FILE} if exists $ENV{GIT_INDEX_FILE}; +my ($git_ih, $git_index) = tempfile('gitXXXXXX', SUFFIX => '.idx', + DIR => File::Spec->tmpdir()); +close ($git_ih); +$ENV{GIT_INDEX_FILE} = $git_index; +my $maxnum = 0; +my $last_rev = ""; +my $last_branch; +my $current_rev = 0; +unless(-d $git_dir) { + system("git-init-db"); + die "Cannot init the GIT db at $git_tree: $?\n" if $?; + system("git-read-tree"); + die "Cannot init an empty tree: $?\n" if $?; + + $last_branch = $opt_o; + $orig_branch = ""; +} else { + -f "$git_dir/refs/heads/$opt_o" + or die "Branch '$opt_o' does not exist.\n". + "Either use the correct '-o branch' option,\n". + "or import to a new repository.\n"; + + -f "$git_dir/svn2git" + or die "'$git_dir/svn2git' does not exist.\n". + "You need that file for incremental imports.\n"; + $last_branch = basename(readlink("$git_dir/HEAD")); + unless($last_branch) { + warn "Cannot read the last branch name: $! -- assuming 'master'\n"; + $last_branch = "master"; + } + $orig_branch = $last_branch; + $last_rev = get_headref($orig_branch, $git_dir); + if (-f "$git_dir/SVN2GIT_HEAD") { + die <) { + chomp; + my($num,$branch,$ref) = split; + $branches{$branch}{$num} = $ref; + $branches{$branch}{"LAST"} = $ref; + $current_rev = $num+1 if $current_rev < $num+1; + } + close($B); +} +-d $git_dir + or die "Could not create git subdir ($git_dir).\n"; + +open BRANCHES,">>", "$git_dir/svn2git"; + + +## cvsps output: +#--------------------- +#PatchSet 314 +#Date: 1999/09/18 13:03:59 +#Author: wkoch +#Branch: STABLE-BRANCH-1-0 +#Ancestor branch: HEAD +#Tag: (none) +#Log: +# See ChangeLog: Sat Sep 18 13:03:28 CEST 1999 Werner Koch +#Members: +# README:1.57->1.57.2.1 +# VERSION:1.96->1.96.2.1 +# +#--------------------- + +my $state = 0; + +sub get_file($$$) { + my($rev,$branch,$path) = @_; + + # revert split_path(), below + my $svnpath; + $path = "" if $path eq "/"; # this should not happen, but ... + if($branch eq "/") { + $svnpath = "/$trunk_name/$path"; + } elsif($branch =~ m#^/#) { + $svnpath = "/$tag_name$branch/$path"; + } else { + $svnpath = "/$branch_name/$branch/$path"; + } + + # now get it + my ($name, $res) = $svn->file($svnpath,$rev); + + open my $F, '-|', "git-hash-object -w $name" + or die "Cannot create object: $!\n"; + my $sha = <$F>; + chomp $sha; + close $F; + # my $mode = pmode($cvs->{'mode'}); + my $mode = "0644"; # SV does not seem to store any file modes + return [$mode, $sha, $path]; +} + +sub split_path($$) { + my($rev,$path) = @_; + my $branch; + + if($path =~ s#^/\Q$tag_name\E/([^/]+)/?##) { + $branch = "/$1"; + } elsif($path =~ s#^/\Q$trunk_name\E/?##) { + $branch = "/"; + } elsif($path =~ s#^/\Q$branch_name\E/([^/]+)/?##) { + $branch = $1; + } else { + print STDERR "$rev: Unrecognized path: $path\n"; + return () + } + $path = "/" if $path eq ""; + return ($branch,$path); +} + +sub commit { + my($branch, $changed_paths, $revision, $author, $date, $message) = @_; + my($author_name,$author_email,$dest); + my(@old,@new); + + if ($author =~ /^(.*?)\s+<(.*)>$/) { + ($author_name, $author_email) = ($1, $2); + } else { + $author =~ s/^<(.*)>$/$1/; + $author_name = $author_email = $author; + } + $date = pdate($date); + + my $tag; + my $parent; + if($branch eq "/") { # trunk + $parent = $opt_o; + } elsif($branch =~ m#^/(.+)#) { # tag + $tag = 1; + $parent = $1; + } else { # "normal" branch + # nothing to do + $parent = $branch; + } + $dest = $parent; + + my $prev = $changed_paths->{"/"}; + if($prev and $prev->action eq "A") { + delete $changed_paths->{"/"}; + my $oldpath = $prev->copyfrom_path; + my $rev; + if(defined $oldpath) { + my $p; + ($parent,$p) = split_path($revision,$oldpath); + if($parent eq "/") { + $parent = $opt_o; + } else { + $parent =~ s#^/##; # if it's a tag + } + } else { + $parent = undef; + } + } + + my $rev; + if(defined $parent) { + open(H,"git-rev-parse --verify $parent |"); + $rev = ; + close(H) or do { + print STDERR "$revision: cannot find commit '$parent'!\n"; + return; + }; + chop $rev; + if(length($rev) != 40) { + print STDERR "$revision: cannot find commit '$parent'!\n"; + return; + } + $rev = $branches{($parent eq $opt_o) ? "/" : $parent}{"LAST"}; + if($revision != 1 and not $rev) { + print STDERR "$revision: do not know ancestor for '$parent'!\n"; + return; + } + } else { + $rev = undef; + } + +# if($prev and $prev->action eq "A") { +# if(not $tag) { +# unless(open(H,"> $git_dir/refs/heads/$branch")) { +# print STDERR "$revision: Could not create branch $branch: $!\n"; +# $state=11; +# next; +# } +# print H "$rev\n" +# or die "Could not write branch $branch: $!"; +# close(H) +# or die "Could not write branch $branch: $!"; +# } +# } + if(not defined $rev) { + unlink($git_index); + } elsif ($rev ne $last_rev) { + print "Switching from $last_rev to $rev ($branch)\n" if $opt_v; + system("git-read-tree", $rev); + die "read-tree failed for $rev: $?\n" if $?; + $last_rev = $rev; + } + + while(my($path,$action) = each %$changed_paths) { + if ($action->action eq "A") { + my $f = get_file($revision,$branch,$path); + push(@new,$f) if $f; + } elsif ($action->action eq "D") { + push(@old,$path); + } elsif ($action->action eq "M") { + my $f = get_file($revision,$branch,$path); + push(@new,$f) if $f; + } elsif ($action->action eq "R") { + # refer to a file/tree in an earlier commit + push(@old,$path); # remove any old stuff + + # ... and add any new stuff + my($b,$p) = split_path($revision,$action->oldpath); + open my $F,"-|","git-ls-tree","-r","-z", $branches{$b}{$action->oldrev}, $p; + local $/ = '\0'; + while(<$F>) { + chomp; + my($m,$p) = split(/\t/,$_,2); + my($mode,$type,$sha1) = split(/ /,$m); + next if $type ne "blob"; + push(@new,[$mode,$sha1,$p]); + } + } else { + die "$revision: unknown action '".$action->action."' for $path\n"; + } + } + + if(@old) { + open F, "-│", "git-ls-files", "-z", @old or die $!; + @old = (); + local $/ = '\0'; + while() { + chomp; + push(@old,$_); + } + close(F); + + while(@old) { + my @o2; + if(@old > 55) { + @o2 = splice(@old,0,50); + } else { + @o2 = @old; + @old = (); + } + system("git-update-index","--force-remove","--",@o2); + die "Cannot remove files: $?\n" if $?; + } + } + while(@new) { + my @n2; + if(@new > 12) { + @n2 = splice(@new,0,10); + } else { + @n2 = @new; + @new = (); + } + system("git-update-index","--add", + (map { ('--cacheinfo', @$_) } @n2)); + die "Cannot add files: $?\n" if $?; + } + + my $pid = open(C,"-|"); + die "Cannot fork: $!" unless defined $pid; + unless($pid) { + exec("git-write-tree"); + die "Cannot exec git-write-tree: $!\n"; + } + chomp(my $tree = ); + length($tree) == 40 + or die "Cannot get tree id ($tree): $!\n"; + close(C) + or die "Error running git-write-tree: $?\n"; + print "Tree ID $tree\n" if $opt_v; + + my $pr = IO::Pipe->new() or die "Cannot open pipe: $!\n"; + my $pw = IO::Pipe->new() or die "Cannot open pipe: $!\n"; + $pid = fork(); + die "Fork: $!\n" unless defined $pid; + unless($pid) { + $pr->writer(); + $pw->reader(); + open(OUT,">&STDOUT"); + dup2($pw->fileno(),0); + dup2($pr->fileno(),1); + $pr->close(); + $pw->close(); + + my @par = (); + @par = ("-p",$rev) if defined $rev; + + # loose detection of merges + # based on the commit msg + foreach my $rx (@mergerx) { + if ($message =~ $rx) { + my $mparent = $1; + if ($mparent eq 'HEAD') { $mparent = $opt_o }; + if ( -e "$git_dir/refs/heads/$mparent") { + $mparent = get_headref($mparent, $git_dir); + push @par, '-p', $mparent; + print OUT "Merge parent branch: $mparent\n" if $opt_v; + } + } + } + + exec("env", + "GIT_AUTHOR_NAME=$author_name", + "GIT_AUTHOR_EMAIL=$author_email", + "GIT_AUTHOR_DATE=".strftime("+0000 %Y-%m-%d %H:%M:%S",gmtime($date)), + "GIT_COMMITTER_NAME=$author_name", + "GIT_COMMITTER_EMAIL=$author_email", + "GIT_COMMITTER_DATE=".strftime("+0000 %Y-%m-%d %H:%M:%S",gmtime($date)), + "git-commit-tree", $tree,@par); + die "Cannot exec git-commit-tree: $!\n"; + } + $pw->writer(); + $pr->reader(); + + $message =~ s/[\s\n]+\z//; + + print $pw "$message\n" + or die "Error writing to git-commit-tree: $!\n"; + $pw->close(); + + print "Committed change $revision:$branch ".strftime("%Y-%m-%d %H:%M:%S",gmtime($date)).")\n" if $opt_v; + chomp(my $cid = <$pr>); + length($cid) == 40 + or die "Cannot get commit id ($cid): $!\n"; + print "Commit ID $cid\n" if $opt_v; + $pr->close(); + + waitpid($pid,0); + die "Error running git-commit-tree: $?\n" if $?; + + if(defined $dest) { + print "Writing to refs/heads/$dest\n" if $opt_v; + open(C,">$git_dir/refs/heads/$dest") and + print C ("$cid\n") and + close(C) + or die "Cannot write branch $dest for update: $!\n"; + } else { + print "... no known parent\n" if $opt_v; + } + $branches{$branch}{"LAST"} = $cid; + $branches{$branch}{$revision} = $cid; + $last_rev = $cid; + print BRANCHES "$revision $branch $cid\n"; + print "DONE: $revision $dest $cid\n" if $opt_v; + + if($tag) { + my($in, $out) = ('',''); + $last_rev = "-" if %$changed_paths; + # the tag was 'complex', i.e. did not refer to a "real" revision + + $tag =~ tr/_/\./ if $opt_u; + + my $pid = open2($in, $out, 'git-mktag'); + print $out ("object $cid\n". + "type commit\n". + "tag $tag\n". + "tagger $author_name <$author_email>\n") and + close($out) + or die "Cannot create tag object $tag: $!\n"; + + my $tagobj = <$in>; + chomp $tagobj; + + if ( !close($in) or waitpid($pid, 0) != $pid or + $? != 0 or $tagobj !~ /^[0123456789abcdef]{40}$/ ) { + die "Cannot create tag object $tag: $!\n"; + } + + + open(C,">$git_dir/refs/tags/$tag") + or die "Cannot create tag $tag: $!\n"; + print C "$tagobj\n" + or die "Cannot write tag $tag: $!\n"; + close(C) + or die "Cannot write tag $tag: $!\n"; + + print "Created tag '$tag' on '$branch'\n" if $opt_v; + } +} + +my ($changed_paths, $revision, $author, $date, $message, $pool) = @_; +sub _commit_all { + ($changed_paths, $revision, $author, $date, $message, $pool) = @_; +} +sub commit_all { + my %done; + my @col; + my $pref; + my $branch; + + while(my($path,$action) = each %$changed_paths) { + ($branch,$path) = split_path($revision,$path); + next if not defined $branch; + $done{$branch}{$path} = $action; + } + while(($branch,$changed_paths) = each %done) { + commit($branch, $changed_paths, $revision, $author, $date, $message); + } +} + +while(++$current_rev < $svn->{'maxrev'}) { + $svn->{'svn'}->get_log("/",$current_rev,$current_rev,$current_rev,1,1,\&_commit_all,""); + commit_all(); +} + + +unlink($git_index); + +if (defined $orig_git_index) { + $ENV{GIT_INDEX_FILE} = $orig_git_index; +} else { + delete $ENV{GIT_INDEX_FILE}; +} + +# Now switch back to the branch we were in before all of this happened +if($orig_branch) { + print "DONE\n" if $opt_v; + system("cp","$git_dir/refs/heads/$opt_o","$git_dir/refs/heads/master") + if $forward_master; + unless ($opt_i) { + system('git-read-tree', '-m', '-u', 'SVN2GIT_HEAD', 'HEAD'); + die "read-tree failed: $?\n" if $?; + } +} else { + $orig_branch = "master"; + print "DONE; creating $orig_branch branch\n" if $opt_v; + system("cp","$git_dir/refs/heads/$opt_o","$git_dir/refs/heads/master") + unless -f "$git_dir/refs/heads/master"; + unlink("$git_dir/HEAD"); + symlink("refs/heads/$orig_branch","$git_dir/HEAD"); + unless ($opt_i) { + system('git checkout'); + die "checkout failed: $?\n" if $?; + } +} +unlink("$git_dir/SVN2GIT_HEAD"); +close(BRANCHES); From 2b5e63d1b4a6f1b0ef58755a192ecb2d04e3569d Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Mon, 10 Oct 2005 12:33:22 +0200 Subject: [PATCH 050/254] svn import: add eval() Trying to downlaod a file that's really a subdirectory doesn't work too well. Signed-Off-By: Matthias Urlichs --- git-svnimport.perl | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/git-svnimport.perl b/git-svnimport.perl index 08645f7ebb..920b23e6cb 100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@ -121,12 +121,15 @@ sub file { my ($fh, $name) = tempfile('gitsvn.XXXXXX', DIR => File::Spec->tmpdir(), UNLINK => 1); - $self->{'svn'}->get_file($path,$rev,$fh) or do { + print "... $rev $path ...\n" if $opt_v; + eval { $self->{'svn'}->get_file($path,$rev,$fh); }; + if (defined $@ and $@ !~ /Attempted to get checksum/) { # retry $self->conn(); - $self->{'svn'}->get_file($path,$rev,$fh) - or die "$rev: No file $path at $rev\n"; + eval { $self->{'svn'}->get_file($path,$rev,$fh); }; }; + return () if defined $@ and $@ !~ /Attempted to get checksum/; + die $@ if $@; close ($fh); return ($name, $res); @@ -308,7 +311,8 @@ sub get_file($$$) { } # now get it - my ($name, $res) = $svn->file($svnpath,$rev); + my ($name, $res) = eval { $svn->file($svnpath,$rev); }; + return () unless defined $name; open my $F, '-|', "git-hash-object -w $name" or die "Cannot create object: $!\n"; @@ -343,7 +347,9 @@ sub commit { my($author_name,$author_email,$dest); my(@old,@new); - if ($author =~ /^(.*?)\s+<(.*)>$/) { + if (not defined $author) { + $author_name = $author_email = "unknown"; + } elsif ($author =~ /^(.*?)\s+<(.*)>$/) { ($author_name, $author_email) = ($1, $2); } else { $author =~ s/^<(.*)>$/$1/; From c015bf2bcbdc2021410753b4a024dd35dfef6a33 Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Mon, 10 Oct 2005 12:34:32 +0200 Subject: [PATCH 051/254] SVN import: No modes svn doesn't seem to save file modes: removed the code that analyzes them. Signed-Off-By: Matthias Urlichs --- git-svnimport.perl | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/git-svnimport.perl b/git-svnimport.perl index 920b23e6cb..27d964cab2 100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@ -149,30 +149,6 @@ sub pdate($) { return timegm($6||0,$5,$4,$3,$2-1,$y); } -sub pmode($) { - my($mode) = @_; - my $m = 0; - my $mm = 0; - my $um = 0; - for my $x(split(//,$mode)) { - if($x eq ",") { - $m |= $mm&$um; - $mm = 0; - $um = 0; - } elsif($x eq "u") { $um |= 0700; - } elsif($x eq "g") { $um |= 0070; - } elsif($x eq "o") { $um |= 0007; - } elsif($x eq "r") { $mm |= 0444; - } elsif($x eq "w") { $mm |= 0222; - } elsif($x eq "x") { $mm |= 0111; - } elsif($x eq "=") { # do nothing - } else { die "Unknown mode: $mode\n"; - } - } - $m |= $mm&$um; - return $m; -} - sub getwd() { my $pwd = `pwd`; chomp $pwd; @@ -319,7 +295,6 @@ sub get_file($$$) { my $sha = <$F>; chomp $sha; close $F; - # my $mode = pmode($cvs->{'mode'}); my $mode = "0644"; # SV does not seem to store any file modes return [$mode, $sha, $path]; } From f0daa628a297819ed039e6b61d337fde02d8a6dd Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Mon, 10 Oct 2005 12:41:15 +0200 Subject: [PATCH 052/254] svn import: copy path information Due to a bug in the SVN library, path information is freed as soon as the callback returns, even if it still refers to the data. Workaround: Copy it. (Also fix a wrong-method-name bug while we're at it.) Signed-Off-By: Matthias Urlichs --- git-svnimport.perl | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/git-svnimport.perl b/git-svnimport.perl index 27d964cab2..3844cc50dc 100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@ -346,9 +346,9 @@ sub commit { $dest = $parent; my $prev = $changed_paths->{"/"}; - if($prev and $prev->action eq "A") { + if($prev and $prev->[0] eq "A") { delete $changed_paths->{"/"}; - my $oldpath = $prev->copyfrom_path; + my $oldpath = $prev->[1]; my $rev; if(defined $oldpath) { my $p; @@ -385,7 +385,7 @@ sub commit { $rev = undef; } -# if($prev and $prev->action eq "A") { +# if($prev and $prev->[0] eq "A") { # if(not $tag) { # unless(open(H,"> $git_dir/refs/heads/$branch")) { # print STDERR "$revision: Could not create branch $branch: $!\n"; @@ -408,21 +408,21 @@ sub commit { } while(my($path,$action) = each %$changed_paths) { - if ($action->action eq "A") { + if ($action->[0] eq "A") { my $f = get_file($revision,$branch,$path); push(@new,$f) if $f; - } elsif ($action->action eq "D") { + } elsif ($action->[0] eq "D") { push(@old,$path); - } elsif ($action->action eq "M") { + } elsif ($action->[0] eq "M") { my $f = get_file($revision,$branch,$path); push(@new,$f) if $f; - } elsif ($action->action eq "R") { + } elsif ($action->[0] eq "R") { # refer to a file/tree in an earlier commit push(@old,$path); # remove any old stuff # ... and add any new stuff - my($b,$p) = split_path($revision,$action->oldpath); - open my $F,"-|","git-ls-tree","-r","-z", $branches{$b}{$action->oldrev}, $p; + my($b,$p) = split_path($revision,$action->[1]); + open my $F,"-|","git-ls-tree","-r","-z", $branches{$b}{$action->[2]}, $p; local $/ = '\0'; while(<$F>) { chomp; @@ -432,7 +432,7 @@ sub commit { push(@new,[$mode,$sha1,$p]); } } else { - die "$revision: unknown action '".$action->action."' for $path\n"; + die "$revision: unknown action '".$action->[0]."' for $path\n"; } } @@ -596,7 +596,13 @@ sub commit { my ($changed_paths, $revision, $author, $date, $message, $pool) = @_; sub _commit_all { ($changed_paths, $revision, $author, $date, $message, $pool) = @_; + my %p; + while(my($path,$action) = each %$changed_paths) { + $p{$path} = [ $action->action,$action->copyfrom_path, $action->copyfrom_rev ]; + } + $changed_paths = \%p; } + sub commit_all { my %done; my @col; From 6d281217b930466717d0078285e5431c409b7aec Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Mon, 10 Oct 2005 12:45:46 +0200 Subject: [PATCH 053/254] svn import: fixed two pipe open calls. Perl's magic "different semantics of open() based on the number of arguments" is really annoying at times... Signed-Off-By: Matthias Urlichs --- git-svnimport.perl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/git-svnimport.perl b/git-svnimport.perl index 3844cc50dc..415b50b35a 100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@ -290,7 +290,7 @@ sub get_file($$$) { my ($name, $res) = eval { $svn->file($svnpath,$rev); }; return () unless defined $name; - open my $F, '-|', "git-hash-object -w $name" + open my $F, '-|', "git-hash-object", "-w", $name or die "Cannot create object: $!\n"; my $sha = <$F>; chomp $sha; @@ -437,14 +437,14 @@ sub commit { } if(@old) { - open F, "-│", "git-ls-files", "-z", @old or die $!; + open my $F, "-│", "git-ls-files", "-z", @old or die $!; @old = (); local $/ = '\0'; - while() { + while(<$F>) { chomp; push(@old,$_); } - close(F); + close($F); while(@old) { my @o2; From c6582aba5230301fe826c06d1891a4a8a9d32074 Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Mon, 10 Oct 2005 13:10:01 +0200 Subject: [PATCH 054/254] svn import: add libsvn-core-perl to Debian's control file Added libsvn-core-perl to debian/control, "Recommends:" section. Signed-Off-By: Matthias Urlichs --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 5d75c325e2..0ec89338bf 100644 --- a/debian/control +++ b/debian/control @@ -8,7 +8,7 @@ Standards-Version: 3.6.1 Package: git-core Architecture: any Depends: ${shlibs:Depends}, ${perl:Depends}, ${misc:Depends}, patch, rcs -Recommends: rsync, curl, ssh, libmail-sendmail-perl, libemail-valid-perl, python (>= 2.4.0), less +Recommends: rsync, curl, ssh, libmail-sendmail-perl, libemail-valid-perl, libsvn-core-perl (>= 1.2.1), python (>= 2.4.0), less Suggests: cogito Conflicts: git, cogito (<< 0.13) Description: The git content addressable filesystem From 37dcf6de60498dfedb5d97ad96789b0527493bcd Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Mon, 10 Oct 2005 13:42:48 +0200 Subject: [PATCH 055/254] svn improt needs SVN::Core 1.2.1 or better Die with a warning if Perl's svn module is too old. Signed-Off-By: Matthias Urlichs --- git-svnimport.perl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/git-svnimport.perl b/git-svnimport.perl index 415b50b35a..ef73f364cc 100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@ -26,6 +26,8 @@ use IPC::Open2; use SVN::Core; use SVN::Ra; +die "Need CVN:COre 1.2.1 or better" if $SVN::Core::VERSION lt "1.2.1"; + $SIG{'PIPE'}="IGNORE"; $ENV{'TZ'}="UTC"; From 8cd4177d5ef651c8acb9c1f113a076e6fae2e1c2 Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Mon, 10 Oct 2005 14:14:44 +0200 Subject: [PATCH 056/254] svn import: avoid reconnecting Perl's eval() sets $@ to empts, not undef, when it succeeds. That caused excessive reconnect attempts. Signed-Off-By: Matthias Urlichs --- git-svnimport.perl | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/git-svnimport.perl b/git-svnimport.perl index ef73f364cc..ba9f818a06 100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@ -100,8 +100,6 @@ sub new { $self->{'fullrep'} = $repo; $self->conn(); - $self->{'lines'} = undef; - return $self; } @@ -112,6 +110,7 @@ sub conn { die "SVN connection to $repo: $!\n" unless defined $s; $self->{'svn'} = $s; + print STDERR "*** SVN *** $s ***\n"; $self->{'repo'} = $repo; $self->{'maxrev'} = $s->get_latest_revnum(); } @@ -124,13 +123,15 @@ sub file { DIR => File::Spec->tmpdir(), UNLINK => 1); print "... $rev $path ...\n" if $opt_v; - eval { $self->{'svn'}->get_file($path,$rev,$fh); }; - if (defined $@ and $@ !~ /Attempted to get checksum/) { + my $s = $self->{'svn'}; + print STDERR "*** GET *** $s ***\n"; + eval { $s->get_file($path,$rev,$fh); }; + if ($@ and $@ !~ /Attempted to get checksum/) { # retry $self->conn(); eval { $self->{'svn'}->get_file($path,$rev,$fh); }; }; - return () if defined $@ and $@ !~ /Attempted to get checksum/; + return () if $@ and $@ !~ /Attempted to get checksum/; die $@ if $@; close ($fh); From c7ff5f1d7d6f103802fd6d6b1d4dcdf095e95d5f Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Mon, 10 Oct 2005 14:18:38 +0200 Subject: [PATCH 057/254] svn import: wrong file open mode There are multiple | characters in Unicode. Don't use the wrong one ... Signed-Off-By: Matthias Urlichs --- git-svnimport.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-svnimport.perl b/git-svnimport.perl index ba9f818a06..2686f4a63a 100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@ -440,7 +440,7 @@ sub commit { } if(@old) { - open my $F, "-│", "git-ls-files", "-z", @old or die $!; + open my $F, "-|", "git-ls-files", "-z", @old or die $!; @old = (); local $/ = '\0'; while(<$F>) { From 62d72e4b707d6931787e91f611ed49aaabb14391 Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Mon, 10 Oct 2005 14:19:15 +0200 Subject: [PATCH 058/254] svn import: remove debugging Removed debugging output used to identify the too-many-connections problem. Signed-Off-By: Matthias Urlichs --- git-svnimport.perl | 2 -- 1 file changed, 2 deletions(-) diff --git a/git-svnimport.perl b/git-svnimport.perl index 2686f4a63a..f7bf616e58 100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@ -110,7 +110,6 @@ sub conn { die "SVN connection to $repo: $!\n" unless defined $s; $self->{'svn'} = $s; - print STDERR "*** SVN *** $s ***\n"; $self->{'repo'} = $repo; $self->{'maxrev'} = $s->get_latest_revnum(); } @@ -124,7 +123,6 @@ sub file { print "... $rev $path ...\n" if $opt_v; my $s = $self->{'svn'}; - print STDERR "*** GET *** $s ***\n"; eval { $s->get_file($path,$rev,$fh); }; if ($@ and $@ !~ /Attempted to get checksum/) { # retry From f02b3eba7fc6e3fca25e0063dde6ff149aed2b45 Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Mon, 10 Oct 2005 14:42:59 +0200 Subject: [PATCH 059/254] svn import: Fix tagging. Tagging was 100% broken. :-/ Signed-Off-By: Matthias Urlichs --- git-svnimport.perl | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/git-svnimport.perl b/git-svnimport.perl index f7bf616e58..f977ed2868 100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@ -122,8 +122,7 @@ sub file { DIR => File::Spec->tmpdir(), UNLINK => 1); print "... $rev $path ...\n" if $opt_v; - my $s = $self->{'svn'}; - eval { $s->get_file($path,$rev,$fh); }; + eval { $self->{'svn'}->get_file($path,$rev,$fh); }; if ($@ and $@ !~ /Attempted to get checksum/) { # retry $self->conn(); @@ -544,14 +543,14 @@ sub commit { waitpid($pid,0); die "Error running git-commit-tree: $?\n" if $?; - if(defined $dest) { + if(not defined $dest) { + print "... no known parent\n" if $opt_v; + } elsif(not $tag) { print "Writing to refs/heads/$dest\n" if $opt_v; open(C,">$git_dir/refs/heads/$dest") and print C ("$cid\n") and close(C) or die "Cannot write branch $dest for update: $!\n"; - } else { - print "... no known parent\n" if $opt_v; } $branches{$branch}{"LAST"} = $cid; $branches{$branch}{$revision} = $cid; @@ -564,33 +563,30 @@ sub commit { $last_rev = "-" if %$changed_paths; # the tag was 'complex', i.e. did not refer to a "real" revision - $tag =~ tr/_/\./ if $opt_u; + $dest =~ tr/_/\./ if $opt_u; my $pid = open2($in, $out, 'git-mktag'); print $out ("object $cid\n". "type commit\n". - "tag $tag\n". + "tag $dest\n". "tagger $author_name <$author_email>\n") and close($out) - or die "Cannot create tag object $tag: $!\n"; + or die "Cannot create tag object $dest: $!\n"; my $tagobj = <$in>; chomp $tagobj; if ( !close($in) or waitpid($pid, 0) != $pid or $? != 0 or $tagobj !~ /^[0123456789abcdef]{40}$/ ) { - die "Cannot create tag object $tag: $!\n"; + die "Cannot create tag object $dest: $!\n"; } - - open(C,">$git_dir/refs/tags/$tag") - or die "Cannot create tag $tag: $!\n"; - print C "$tagobj\n" - or die "Cannot write tag $tag: $!\n"; + open(C,">$git_dir/refs/tags/$dest") and + print C ("$tagobj\n") and close(C) - or die "Cannot write tag $tag: $!\n"; + or die "Cannot create tag $branch: $!\n"; - print "Created tag '$tag' on '$branch'\n" if $opt_v; + print "Created tag '$dest' on '$branch'\n" if $opt_v; } } From bf267d99e88410a31452d4d1ccae0b9b4432b11e Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Mon, 10 Oct 2005 14:51:13 +0200 Subject: [PATCH 060/254] svn import: Do not create empty tags If a tag is "clean", do not create a commit for it. Signed-Off-By: Matthias Urlichs --- git-svnimport.perl | 245 +++++++++++++++++++++++---------------------- 1 file changed, 125 insertions(+), 120 deletions(-) diff --git a/git-svnimport.perl b/git-svnimport.perl index f977ed2868..10ffb5477e 100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@ -407,141 +407,146 @@ sub commit { $last_rev = $rev; } - while(my($path,$action) = each %$changed_paths) { - if ($action->[0] eq "A") { - my $f = get_file($revision,$branch,$path); - push(@new,$f) if $f; - } elsif ($action->[0] eq "D") { - push(@old,$path); - } elsif ($action->[0] eq "M") { - my $f = get_file($revision,$branch,$path); - push(@new,$f) if $f; - } elsif ($action->[0] eq "R") { - # refer to a file/tree in an earlier commit - push(@old,$path); # remove any old stuff - - # ... and add any new stuff - my($b,$p) = split_path($revision,$action->[1]); - open my $F,"-|","git-ls-tree","-r","-z", $branches{$b}{$action->[2]}, $p; + my $cid; + if($tag and not %$changed_paths) { + $cid = $rev; + } else { + while(my($path,$action) = each %$changed_paths) { + if ($action->[0] eq "A") { + my $f = get_file($revision,$branch,$path); + push(@new,$f) if $f; + } elsif ($action->[0] eq "D") { + push(@old,$path); + } elsif ($action->[0] eq "M") { + my $f = get_file($revision,$branch,$path); + push(@new,$f) if $f; + } elsif ($action->[0] eq "R") { + # refer to a file/tree in an earlier commit + push(@old,$path); # remove any old stuff + + # ... and add any new stuff + my($b,$p) = split_path($revision,$action->[1]); + open my $F,"-|","git-ls-tree","-r","-z", $branches{$b}{$action->[2]}, $p; + local $/ = '\0'; + while(<$F>) { + chomp; + my($m,$p) = split(/\t/,$_,2); + my($mode,$type,$sha1) = split(/ /,$m); + next if $type ne "blob"; + push(@new,[$mode,$sha1,$p]); + } + } else { + die "$revision: unknown action '".$action->[0]."' for $path\n"; + } + } + + if(@old) { + open my $F, "-|", "git-ls-files", "-z", @old or die $!; + @old = (); local $/ = '\0'; while(<$F>) { chomp; - my($m,$p) = split(/\t/,$_,2); - my($mode,$type,$sha1) = split(/ /,$m); - next if $type ne "blob"; - push(@new,[$mode,$sha1,$p]); + push(@old,$_); + } + close($F); + + while(@old) { + my @o2; + if(@old > 55) { + @o2 = splice(@old,0,50); + } else { + @o2 = @old; + @old = (); + } + system("git-update-index","--force-remove","--",@o2); + die "Cannot remove files: $?\n" if $?; } - } else { - die "$revision: unknown action '".$action->[0]."' for $path\n"; - } - } - - if(@old) { - open my $F, "-|", "git-ls-files", "-z", @old or die $!; - @old = (); - local $/ = '\0'; - while(<$F>) { - chomp; - push(@old,$_); } - close($F); - - while(@old) { - my @o2; - if(@old > 55) { - @o2 = splice(@old,0,50); + while(@new) { + my @n2; + if(@new > 12) { + @n2 = splice(@new,0,10); } else { - @o2 = @old; - @old = (); + @n2 = @new; + @new = (); } - system("git-update-index","--force-remove","--",@o2); - die "Cannot remove files: $?\n" if $?; - } - } - while(@new) { - my @n2; - if(@new > 12) { - @n2 = splice(@new,0,10); - } else { - @n2 = @new; - @new = (); + system("git-update-index","--add", + (map { ('--cacheinfo', @$_) } @n2)); + die "Cannot add files: $?\n" if $?; } - system("git-update-index","--add", - (map { ('--cacheinfo', @$_) } @n2)); - die "Cannot add files: $?\n" if $?; - } - - my $pid = open(C,"-|"); - die "Cannot fork: $!" unless defined $pid; - unless($pid) { - exec("git-write-tree"); - die "Cannot exec git-write-tree: $!\n"; - } - chomp(my $tree = ); - length($tree) == 40 - or die "Cannot get tree id ($tree): $!\n"; - close(C) - or die "Error running git-write-tree: $?\n"; - print "Tree ID $tree\n" if $opt_v; - - my $pr = IO::Pipe->new() or die "Cannot open pipe: $!\n"; - my $pw = IO::Pipe->new() or die "Cannot open pipe: $!\n"; - $pid = fork(); - die "Fork: $!\n" unless defined $pid; - unless($pid) { - $pr->writer(); - $pw->reader(); - open(OUT,">&STDOUT"); - dup2($pw->fileno(),0); - dup2($pr->fileno(),1); - $pr->close(); - $pw->close(); - my @par = (); - @par = ("-p",$rev) if defined $rev; - - # loose detection of merges - # based on the commit msg - foreach my $rx (@mergerx) { - if ($message =~ $rx) { - my $mparent = $1; - if ($mparent eq 'HEAD') { $mparent = $opt_o }; - if ( -e "$git_dir/refs/heads/$mparent") { - $mparent = get_headref($mparent, $git_dir); - push @par, '-p', $mparent; - print OUT "Merge parent branch: $mparent\n" if $opt_v; - } - } + my $pid = open(C,"-|"); + die "Cannot fork: $!" unless defined $pid; + unless($pid) { + exec("git-write-tree"); + die "Cannot exec git-write-tree: $!\n"; } + chomp(my $tree = ); + length($tree) == 40 + or die "Cannot get tree id ($tree): $!\n"; + close(C) + or die "Error running git-write-tree: $?\n"; + print "Tree ID $tree\n" if $opt_v; + + my $pr = IO::Pipe->new() or die "Cannot open pipe: $!\n"; + my $pw = IO::Pipe->new() or die "Cannot open pipe: $!\n"; + $pid = fork(); + die "Fork: $!\n" unless defined $pid; + unless($pid) { + $pr->writer(); + $pw->reader(); + open(OUT,">&STDOUT"); + dup2($pw->fileno(),0); + dup2($pr->fileno(),1); + $pr->close(); + $pw->close(); + + my @par = (); + @par = ("-p",$rev) if defined $rev; + + # loose detection of merges + # based on the commit msg + foreach my $rx (@mergerx) { + if ($message =~ $rx) { + my $mparent = $1; + if ($mparent eq 'HEAD') { $mparent = $opt_o }; + if ( -e "$git_dir/refs/heads/$mparent") { + $mparent = get_headref($mparent, $git_dir); + push @par, '-p', $mparent; + print OUT "Merge parent branch: $mparent\n" if $opt_v; + } + } + } - exec("env", - "GIT_AUTHOR_NAME=$author_name", - "GIT_AUTHOR_EMAIL=$author_email", - "GIT_AUTHOR_DATE=".strftime("+0000 %Y-%m-%d %H:%M:%S",gmtime($date)), - "GIT_COMMITTER_NAME=$author_name", - "GIT_COMMITTER_EMAIL=$author_email", - "GIT_COMMITTER_DATE=".strftime("+0000 %Y-%m-%d %H:%M:%S",gmtime($date)), - "git-commit-tree", $tree,@par); - die "Cannot exec git-commit-tree: $!\n"; - } - $pw->writer(); - $pr->reader(); + exec("env", + "GIT_AUTHOR_NAME=$author_name", + "GIT_AUTHOR_EMAIL=$author_email", + "GIT_AUTHOR_DATE=".strftime("+0000 %Y-%m-%d %H:%M:%S",gmtime($date)), + "GIT_COMMITTER_NAME=$author_name", + "GIT_COMMITTER_EMAIL=$author_email", + "GIT_COMMITTER_DATE=".strftime("+0000 %Y-%m-%d %H:%M:%S",gmtime($date)), + "git-commit-tree", $tree,@par); + die "Cannot exec git-commit-tree: $!\n"; + } + $pw->writer(); + $pr->reader(); - $message =~ s/[\s\n]+\z//; + $message =~ s/[\s\n]+\z//; - print $pw "$message\n" - or die "Error writing to git-commit-tree: $!\n"; - $pw->close(); + print $pw "$message\n" + or die "Error writing to git-commit-tree: $!\n"; + $pw->close(); - print "Committed change $revision:$branch ".strftime("%Y-%m-%d %H:%M:%S",gmtime($date)).")\n" if $opt_v; - chomp(my $cid = <$pr>); - length($cid) == 40 - or die "Cannot get commit id ($cid): $!\n"; - print "Commit ID $cid\n" if $opt_v; - $pr->close(); + print "Committed change $revision:$branch ".strftime("%Y-%m-%d %H:%M:%S",gmtime($date)).")\n" if $opt_v; + chomp($cid = <$pr>); + length($cid) == 40 + or die "Cannot get commit id ($cid): $!\n"; + print "Commit ID $cid\n" if $opt_v; + $pr->close(); - waitpid($pid,0); - die "Error running git-commit-tree: $?\n" if $?; + waitpid($pid,0); + die "Error running git-commit-tree: $?\n" if $?; + } if(not defined $dest) { print "... no known parent\n" if $opt_v; From 7ee74a99b2b710b5f5adc22db2fe0aca8a74c809 Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Mon, 10 Oct 2005 15:14:21 +0200 Subject: [PATCH 061/254] svn import: skip initial revisions Add a flag to skip initial revisions: some SVN repositories have initial setup cruft in their logs which we might want to ignore. Signed-Off-By: Matthias Urlichs --- Documentation/git-svnimport.txt | 7 ++++++- git-svnimport.perl | 12 ++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Documentation/git-svnimport.txt b/Documentation/git-svnimport.txt index be03a65f81..a144c6c31c 100644 --- a/Documentation/git-svnimport.txt +++ b/Documentation/git-svnimport.txt @@ -12,7 +12,7 @@ SYNOPSIS 'git-svnimport' [ -o ] [ -h ] [ -v ] [ -C ] [ -i ] [ -u ] [ -b branch_subdir ] [ -t trunk_subdir ] [ -T tag_subdir ] - [ -m ] [ -M regex ] [ ] + [ -s start_chg ] [ -m ] [ -M regex ] [ ] DESCRIPTION @@ -36,6 +36,11 @@ OPTIONS The GIT repository to import to. If the directory doesn't exist, it will be created. Default is the current directory. +-s :: + Start importing at this SVN change number. The default is 1. ++ +When importing incementally, you might need to edit the .git/svn2git file. + -i:: Import-only: don't perform a checkout after importing. This option ensures the working directory and cache remain untouched and will diff --git a/git-svnimport.perl b/git-svnimport.perl index 10ffb5477e..896222ba74 100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@ -31,19 +31,19 @@ die "Need CVN:COre 1.2.1 or better" if $SVN::Core::VERSION lt "1.2.1"; $SIG{'PIPE'}="IGNORE"; $ENV{'TZ'}="UTC"; -our($opt_h,$opt_o,$opt_v,$opt_u,$opt_C,$opt_i,$opt_m,$opt_M,$opt_t,$opt_T,$opt_b); +our($opt_h,$opt_o,$opt_v,$opt_u,$opt_C,$opt_i,$opt_m,$opt_M,$opt_t,$opt_T,$opt_b,$opt_s); sub usage() { print STDERR < $opt_s and defined $parent) { open(H,"git-rev-parse --verify $parent |"); $rev = ; close(H) or do { @@ -377,7 +377,7 @@ sub commit { return; } $rev = $branches{($parent eq $opt_o) ? "/" : $parent}{"LAST"}; - if($revision != 1 and not $rev) { + if($revision != $opt_s and not $rev) { print STDERR "$revision: do not know ancestor for '$parent'!\n"; return; } From e7e477dfacecaf362f08a65644d806da5231a9f0 Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Mon, 10 Oct 2005 15:28:00 +0200 Subject: [PATCH 062/254] svn import: incremental imports Incremental imports skipped a revision. Also improve interrupt safety -- ^C while writing a tag caused the tag to be skipped. Signed-Off-By: Matthias Urlichs --- git-svnimport.perl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/git-svnimport.perl b/git-svnimport.perl index 896222ba74..00f563daec 100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@ -244,7 +244,7 @@ EOM my($num,$branch,$ref) = split; $branches{$branch}{$num} = $ref; $branches{$branch}{"LAST"} = $ref; - $current_rev = $num+1 if $current_rev < $num+1; + $current_rev = $num if $current_rev < $num; } close($B); } @@ -557,11 +557,6 @@ sub commit { close(C) or die "Cannot write branch $dest for update: $!\n"; } - $branches{$branch}{"LAST"} = $cid; - $branches{$branch}{$revision} = $cid; - $last_rev = $cid; - print BRANCHES "$revision $branch $cid\n"; - print "DONE: $revision $dest $cid\n" if $opt_v; if($tag) { my($in, $out) = ('',''); @@ -593,6 +588,11 @@ sub commit { print "Created tag '$dest' on '$branch'\n" if $opt_v; } + $branches{$branch}{"LAST"} = $cid; + $branches{$branch}{$revision} = $cid; + $last_rev = $cid; + print BRANCHES "$revision $branch $cid\n"; + print "DONE: $revision $dest $cid\n" if $opt_v; } my ($changed_paths, $revision, $author, $date, $message, $pool) = @_; From 3ef378a67b5b39441837700ab4dfb800eb443c5a Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Mon, 10 Oct 2005 18:45:00 +0200 Subject: [PATCH 063/254] svn import: Add a loop limit option The svn library has a serious memory leak. Added a new option (-l NUM) which causes git-svnimport to exit cleanly after fetching that many changes, in order to . Signed-Off-By: Matthias Urlichs --- Documentation/git-svnimport.txt | 11 ++++++++++- git-svnimport.perl | 15 ++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Documentation/git-svnimport.txt b/Documentation/git-svnimport.txt index a144c6c31c..047f8f3346 100644 --- a/Documentation/git-svnimport.txt +++ b/Documentation/git-svnimport.txt @@ -10,7 +10,7 @@ git-svnimport - Import a SVN repository into git SYNOPSIS -------- 'git-svnimport' [ -o ] [ -h ] [ -v ] - [ -C ] [ -i ] [ -u ] + [ -C ] [ -i ] [ -u ] [-l limit_nr_changes] [ -b branch_subdir ] [ -t trunk_subdir ] [ -T tag_subdir ] [ -s start_chg ] [ -m ] [ -M regex ] [ ] @@ -70,6 +70,15 @@ When importing incementally, you might need to edit the .git/svn2git file. regex. It can be used with -m to also see the default regexes. You must escape forward slashes. +-l :: + Limit the number of SVN changesets we pull before quitting. + This option is necessary because the SVN library has serious memory + leaks; the recommended value for nontrivial imports is 100. + + git-svnimport will still exit with a zero exit code. You can check + the size of the file ".git/svn2git" to determine whether to call + the importer again. + -v:: Verbosity: let 'svnimport' report what it is doing. diff --git a/git-svnimport.perl b/git-svnimport.perl index 00f563daec..b880297e0c 100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@ -31,19 +31,19 @@ die "Need CVN:COre 1.2.1 or better" if $SVN::Core::VERSION lt "1.2.1"; $SIG{'PIPE'}="IGNORE"; $ENV{'TZ'}="UTC"; -our($opt_h,$opt_o,$opt_v,$opt_u,$opt_C,$opt_i,$opt_m,$opt_M,$opt_t,$opt_T,$opt_b,$opt_s); +our($opt_h,$opt_o,$opt_v,$opt_u,$opt_C,$opt_i,$opt_m,$opt_M,$opt_t,$opt_T,$opt_b,$opt_s,$opt_l); sub usage() { print STDERR <{'maxrev'}) { $svn->{'svn'}->get_log("/",$current_rev,$current_rev,$current_rev,1,1,\&_commit_all,""); commit_all(); + if($opt_l and not --$opt_l) { + print STDERR "Exiting due to a memory leak. Repeat, please.\n"; + last; + } } @@ -637,7 +642,7 @@ if (defined $orig_git_index) { # Now switch back to the branch we were in before all of this happened if($orig_branch) { - print "DONE\n" if $opt_v; + print "DONE\n" if $opt_v and (not defined $opt_l or $opt_l > 0); system("cp","$git_dir/refs/heads/$opt_o","$git_dir/refs/heads/master") if $forward_master; unless ($opt_i) { @@ -646,7 +651,7 @@ if($orig_branch) { } } else { $orig_branch = "master"; - print "DONE; creating $orig_branch branch\n" if $opt_v; + print "DONE; creating $orig_branch branch\n" if $opt_v and (not defined $opt_l or $opt_l > 0); system("cp","$git_dir/refs/heads/$opt_o","$git_dir/refs/heads/master") unless -f "$git_dir/refs/heads/master"; unlink("$git_dir/HEAD"); From 22dcbb75129b3124a9fd71ed449030b79093b634 Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Mon, 10 Oct 2005 18:54:53 +0200 Subject: [PATCH 064/254] svn import: unlink downlaoded files Actually removing the files that have been checked out of SVN, after checking them into git of course, is a good idea... Signed-Off-By: Matthias Urlichs --- git-svnimport.perl | 1 + 1 file changed, 1 insertion(+) diff --git a/git-svnimport.perl b/git-svnimport.perl index b880297e0c..102fa6e339 100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@ -296,6 +296,7 @@ sub get_file($$$) { my $sha = <$F>; chomp $sha; close $F; + unlink $name; my $mode = "0644"; # SV does not seem to store any file modes return [$mode, $sha, $path]; } From 8470b7f3a3cd5a70ff0b05486e335d351843890f Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Mon, 10 Oct 2005 20:10:48 +0200 Subject: [PATCH 065/254] svn import: get all revisions Not skipping the last revision is generally seen as Good Thing. ;-) Signed-Off-By: Matthias Urlichs --- git-svnimport.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-svnimport.perl b/git-svnimport.perl index 102fa6e339..f9318c85cd 100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@ -623,7 +623,7 @@ sub commit_all { } } -while(++$current_rev < $svn->{'maxrev'}) { +while(++$current_rev <= $svn->{'maxrev'}) { $svn->{'svn'}->get_log("/",$current_rev,$current_rev,$current_rev,1,1,\&_commit_all,""); commit_all(); if($opt_l and not --$opt_l) { From 4769948afe7c502d37746edc2ee2c084c9dcb325 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 10 Oct 2005 13:50:01 -0700 Subject: [PATCH 066/254] Deal with $(bindir) and friends with whitespaces. ... using HPA's shellquote macro. Signed-off-by: Junio C Hamano --- Makefile | 34 ++++++++++++++++++++-------------- git-merge-recursive.py | 2 +- t/Makefile | 8 +++++++- templates/Makefile | 10 ++++++++-- 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/Makefile b/Makefile index ac384c7dc4..f7eee4708a 100644 --- a/Makefile +++ b/Makefile @@ -163,6 +163,12 @@ LIB_OBJS = \ LIBS = $(LIB_FILE) LIBS += -lz +# Shell quote; +# Result of this needs to be placed inside '' +shq = $(subst ','\'',$(1)) +# This has surrounding '' +shellquote = '$(call shq,$(1))' + # # Platform specific tweaks # @@ -235,7 +241,7 @@ ifndef NO_OPENSSL OPENSSL_LINK = endif else - DEFINES += '-DNO_OPENSSL' + DEFINES += -DNO_OPENSSL MOZILLA_SHA1 = 1 OPENSSL_LIBSSL = endif @@ -294,7 +300,7 @@ endif endif endif -DEFINES += '-DSHA1_HEADER=$(SHA1_HEADER)' +DEFINES += -DSHA1_HEADER=$(call shellquote,$(SHA1_HEADER)) SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ $(patsubst %.perl,%,$(SCRIPT_PERL)) \ @@ -311,7 +317,7 @@ all: git: git.sh Makefile rm -f $@+ $@ - sed -e '1s|#!.*/sh|#!$(SHELL_PATH)|' \ + sed -e '1s|#!.*/sh|#!$(call shq,$(SHELL_PATH))|' \ -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ -e 's/@@X@@/$(X)/g' \ $(GIT_LIST_TWEAK) <$@.sh >$@+ @@ -320,22 +326,22 @@ git: git.sh Makefile $(filter-out git,$(patsubst %.sh,%,$(SCRIPT_SH))) : % : %.sh rm -f $@ - sed -e '1s|#!.*/sh|#!$(SHELL_PATH)|' \ + sed -e '1s|#!.*/sh|#!$(call shq,$(SHELL_PATH))|' \ -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ $@.sh >$@ chmod +x $@ $(patsubst %.perl,%,$(SCRIPT_PERL)) : % : %.perl rm -f $@ - sed -e '1s|#!.*perl|#!$(PERL_PATH)|' \ + sed -e '1s|#!.*perl|#!$(call shq,$(PERL_PATH))|' \ -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ $@.perl >$@ chmod +x $@ $(patsubst %.py,%,$(SCRIPT_PYTHON)) : % : %.py rm -f $@ - sed -e '1s|#!.*python|#!$(PYTHON_PATH)|' \ - -e 's|@@GIT_PYTHON_PATH@@|$(GIT_PYTHON_DIR)|g' \ + sed -e '1s|#!.*python|#!$(call shq,$(PYTHON_PATH))|' \ + -e 's|@@GIT_PYTHON_PATH@@|$(call shq,$(GIT_PYTHON_DIR))|g' \ -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ $@.py >$@ chmod +x $@ @@ -365,7 +371,7 @@ git-rev-list$X: LIBS += $(OPENSSL_LIBSSL) init-db.o: init-db.c $(CC) -c $(ALL_CFLAGS) \ - -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir)"' $*.c + -DDEFAULT_GIT_TEMPLATE_DIR=$(call shellquote,"$(template_dir)") $*.c $(LIB_OBJS): $(LIB_H) $(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) @@ -397,13 +403,13 @@ check: ### Installation rules install: $(PROGRAMS) $(SCRIPTS) - $(INSTALL) -d -m755 $(DESTDIR)$(bindir) - $(INSTALL) $(PROGRAMS) $(SCRIPTS) $(DESTDIR)$(bindir) - $(INSTALL) git-revert $(DESTDIR)$(bindir)/git-cherry-pick - sh ./cmd-rename.sh $(DESTDIR)$(bindir) + $(INSTALL) -d -m755 $(call shellquote,$(DESTDIR)$(bindir)) + $(INSTALL) $(PROGRAMS) $(SCRIPTS) $(call shellquote,$(DESTDIR)$(bindir)) + $(INSTALL) git-revert $(call shellquote,$(DESTDIR)$(bindir)/git-cherry-pick) + sh ./cmd-rename.sh $(call shellquote,$(DESTDIR)$(bindir)) $(MAKE) -C templates install - $(INSTALL) -d -m755 $(DESTDIR)$(GIT_PYTHON_DIR) - $(INSTALL) $(PYMODULES) $(DESTDIR)$(GIT_PYTHON_DIR) + $(INSTALL) -d -m755 $(call shellquote,$(DESTDIR)$(GIT_PYTHON_DIR)) + $(INSTALL) $(PYMODULES) $(call shellquote,$(DESTDIR)$(GIT_PYTHON_DIR)) install-doc: $(MAKE) -C Documentation install diff --git a/git-merge-recursive.py b/git-merge-recursive.py index b80a860357..626d85493a 100755 --- a/git-merge-recursive.py +++ b/git-merge-recursive.py @@ -4,7 +4,7 @@ import sys, math, random, os, re, signal, tempfile, stat, errno, traceback from heapq import heappush, heappop from sets import Set -sys.path.append('@@GIT_PYTHON_PATH@@') +sys.path.append('''@@GIT_PYTHON_PATH@@''') from gitMergeCommon import * originalIndexFile = os.environ.get('GIT_INDEX_FILE', diff --git a/t/Makefile b/t/Makefile index e71da7782e..5c76afff83 100644 --- a/t/Makefile +++ b/t/Makefile @@ -7,10 +7,16 @@ SHELL_PATH ?= $(SHELL) TAR ?= $(TAR) +# Shell quote; +# Result of this needs to be placed inside '' +shq = $(subst ','\'',$(1)) +# This has surrounding '' +shellquote = '$(call shq,$(1))' + T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh) all: - @$(foreach t,$T,echo "*** $t ***"; $(SHELL_PATH) $t $(GIT_TEST_OPTS) || exit; ) + @$(foreach t,$T,echo "*** $t ***"; $(call shellquote,$(SHELL_PATH)) $t $(GIT_TEST_OPTS) || exit; ) @rm -fr trash clean: diff --git a/templates/Makefile b/templates/Makefile index c23aee866d..07e928e56d 100644 --- a/templates/Makefile +++ b/templates/Makefile @@ -6,6 +6,12 @@ prefix ?= $(HOME) template_dir ?= $(prefix)/share/git-core/templates/ # DESTDIR= +# Shell quote; +# Result of this needs to be placed inside '' +shq = $(subst ','\'',$(1)) +# This has surrounding '' +shellquote = '$(call shq,$(1))' + all: boilerplates.made custom find blt @@ -38,6 +44,6 @@ clean: rm -rf blt boilerplates.made install: all - $(INSTALL) -d -m755 $(DESTDIR)$(template_dir) + $(INSTALL) -d -m755 $(call shellquote,$(DESTDIR)$(template_dir)) (cd blt && $(TAR) cf - .) | \ - (cd $(DESTDIR)$(template_dir) && $(TAR) xf -) + (cd $(call shellquote,$(DESTDIR)$(template_dir)) && $(TAR) xf -) From 77d604c30974587a2e0d36d92c48cef87f6e8e4d Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 10 Oct 2005 14:46:10 -0700 Subject: [PATCH 067/254] Enhanced sq_quote() Create function to sq_quote into a buffer Handle !'s for csh-based shells Signed-off-by: H. Peter Anvin Signed-off-by: Junio C Hamano --- quote.c | 56 ++++++++++++++++++++++++++++++++++---------------------- quote.h | 11 +++++++++-- 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/quote.c b/quote.c index 5e6fda311c..9d5d0bcb0f 100644 --- a/quote.c +++ b/quote.c @@ -2,40 +2,52 @@ #include "quote.h" /* Help to copy the thing properly quoted for the shell safety. - * any single quote is replaced with '\'', and the caller is - * expected to enclose the result within a single quote pair. + * any single quote is replaced with '\'', any exclamation point + * is replaced with '\!', and the whole thing is enclosed in a * * E.g. * original sq_quote result * name ==> name ==> 'name' * a b ==> a b ==> 'a b' * a'b ==> a'\''b ==> 'a'\''b' + * a!b ==> a'\!'b ==> 'a'\!'b' */ -char *sq_quote(const char *src) -{ - static char *buf = NULL; - int cnt, c; - const char *cp; - char *bp; +#define EMIT(x) ( (++len < n) && (*bp++ = (x)) ) - /* count bytes needed to store the quoted string. */ - for (cnt = 3, cp = src; *cp; cnt++, cp++) - if (*cp == '\'') - cnt += 3; +size_t sq_quote_buf(char *dst, size_t n, const char *src) +{ + char c; + char *bp = dst; + size_t len = 0; - buf = xmalloc(cnt); - bp = buf; - *bp++ = '\''; + EMIT('\''); while ((c = *src++)) { - if (c != '\'') - *bp++ = c; - else { - bp = strcpy(bp, "'\\''"); - bp += 4; + if (c == '\'' || c == '!') { + EMIT('\''); + EMIT('\\'); + EMIT(c); + EMIT('\''); + } else { + EMIT(c); } } - *bp++ = '\''; - *bp = 0; + EMIT('\''); + + if ( n ) + *bp = 0; + + return len; +} + +char *sq_quote(const char *src) +{ + char *buf; + size_t cnt; + + cnt = sq_quote_buf(NULL, 0, src) + 1; + buf = xmalloc(cnt); + sq_quote_buf(buf, cnt, src); + return buf; } diff --git a/quote.h b/quote.h index c8cfb3a124..50ce1df976 100644 --- a/quote.h +++ b/quote.h @@ -1,10 +1,12 @@ #ifndef QUOTE_H #define QUOTE_H +#include /* Help to copy the thing properly quoted for the shell safety. - * any single quote is replaced with '\'', and the whole thing - * is enclosed in a single quote pair. + * any single quote is replaced with '\'', any exclamation point + * is replaced with '\!', and the whole thing is enclosed in a + * single quote pair. * * For example, if you are passing the result to system() as an * argument: @@ -19,8 +21,13 @@ * * Note that the above examples leak memory! Remember to free result from * sq_quote() in a real application. + * + * sq_quote_buf() writes to an existing buffer of specified size; it + * will return the number of characters that would have been written + * excluding the final null regardless of the buffer size. */ char *sq_quote(const char *src); +size_t sq_quote_buf(char *dst, size_t n, const char *src); #endif From 977ed47d86c40683a1b84f5226d589e924e95785 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 10 Oct 2005 14:46:12 -0700 Subject: [PATCH 068/254] Trivial optimization GIT_DIR_ENVIRONMENT is always a string literal Signed-off-by: Junio C Hamano --- rsh.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rsh.c b/rsh.c index bad5cff2c2..dde6f9ce9d 100644 --- a/rsh.c +++ b/rsh.c @@ -109,8 +109,7 @@ int setup_connection(int *fd_in, int *fd_out, const char *remote_prog, posn = command; of = 0; of |= add_to_string(&posn, &sizen, "env ", 0); - of |= add_to_string(&posn, &sizen, GIT_DIR_ENVIRONMENT, 0); - of |= add_to_string(&posn, &sizen, "=", 0); + of |= add_to_string(&posn, &sizen, GIT_DIR_ENVIRONMENT "=", 0); of |= add_to_string(&posn, &sizen, path, 1); of |= add_to_string(&posn, &sizen, " ", 0); of |= add_to_string(&posn, &sizen, remote_prog, 1); From f336af1711f86e8b00e85eec3b3f73f7a8e4bed0 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 10 Oct 2005 14:46:14 -0700 Subject: [PATCH 069/254] Make rsh.c use sq_quote_buf() Make rsh.c use sq_quote_buf() Signed-off-by: Junio C Hamano --- rsh.c | 46 +++++----------------------------------------- 1 file changed, 5 insertions(+), 41 deletions(-) diff --git a/rsh.c b/rsh.c index dde6f9ce9d..64c48091cb 100644 --- a/rsh.c +++ b/rsh.c @@ -1,52 +1,16 @@ -#include "rsh.h" - #include #include #include +#include "rsh.h" +#include "quote.h" #include "cache.h" #define COMMAND_SIZE 4096 /* - * Write a shell-quoted version of a string into a buffer, and - * return bytes that ought to be output excluding final null. - */ -static int shell_quote(char *buf, int nmax, const char *str) -{ - char ch; - int nq; - int oc = 0; - - while ( (ch = *str++) ) { - nq = 0; - if ( strchr(" !\"#$%&\'()*;<=>?[\\]^`{|}", ch) ) - nq = 1; - - if ( nq ) { - if ( nmax > 1 ) { - *buf++ = '\\'; - nmax--; - } - oc++; - } - - if ( nmax > 1 ) { - *buf++ = ch; - nmax--; - } - oc++; - } - - if ( nmax ) - *buf = '\0'; - - return oc; -} - -/* - * Append a string to a string buffer, with or without quoting. Return true - * if the buffer overflowed. + * Append a string to a string buffer, with or without shell quoting. + * Return true if the buffer overflowed. */ static int add_to_string(char **ptrp, int *sizep, const char *str, int quote) { @@ -56,7 +20,7 @@ static int add_to_string(char **ptrp, int *sizep, const char *str, int quote) int err = 0; if ( quote ) { - oc = shell_quote(p, size, str); + oc = sq_quote_buf(p, size, str); } else { oc = strlen(str); memcpy(p, str, (oc >= size) ? size-1 : oc); From 98438bd0e893c23186fb82ea8b04964c0f1ef9d1 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 10 Oct 2005 14:49:52 -0700 Subject: [PATCH 070/254] Remove the version tags from the manpages Signed-off-by: Christian Meder Signed-off-by: Junio C Hamano --- Documentation/cvs-migration.txt | 1 - Documentation/git-apply.txt | 1 - Documentation/git-cat-file.txt | 1 - Documentation/git-checkout-index.txt | 1 - Documentation/git-cherry-pick.txt | 1 - Documentation/git-clone-pack.txt | 1 - Documentation/git-clone.txt | 1 - Documentation/git-commit-tree.txt | 1 - Documentation/git-commit.txt | 1 - Documentation/git-convert-objects.txt | 1 - Documentation/git-cvsimport.txt | 1 - Documentation/git-diff-files.txt | 1 - Documentation/git-diff-index.txt | 1 - Documentation/git-diff-stages.txt | 1 - Documentation/git-diff-tree.txt | 1 - Documentation/git-fetch-pack.txt | 1 - Documentation/git-fetch.txt | 1 - Documentation/git-fsck-objects.txt | 1 - Documentation/git-grep.txt | 1 - Documentation/git-hash-object.txt | 1 - Documentation/git-http-fetch.txt | 1 - Documentation/git-init-db.txt | 1 - Documentation/git-local-fetch.txt | 1 - Documentation/git-log.txt | 1 - Documentation/git-ls-remote.txt | 1 - Documentation/git-ls-tree.txt | 1 - Documentation/git-merge-base.txt | 1 - Documentation/git-merge-index.txt | 1 - Documentation/git-merge-one-file.txt | 1 - Documentation/git-merge.txt | 1 - Documentation/git-mktag.txt | 1 - Documentation/git-octopus.txt | 1 - Documentation/git-pack-objects.txt | 1 - Documentation/git-peek-remote.txt | 1 - Documentation/git-prune-packed.txt | 1 - Documentation/git-prune.txt | 1 - Documentation/git-pull.txt | 1 - Documentation/git-read-tree.txt | 1 - Documentation/git-receive-pack.txt | 1 - Documentation/git-rename.txt | 1 - Documentation/git-repack.txt | 1 - Documentation/git-resolve.txt | 1 - Documentation/git-rev-list.txt | 1 - Documentation/git-send-email.txt | 1 - Documentation/git-send-pack.txt | 1 - Documentation/git-shortlog.txt | 1 - Documentation/git-show-branch.txt | 1 - Documentation/git-show-index.txt | 1 - Documentation/git-ssh-fetch.txt | 1 - Documentation/git-ssh-upload.txt | 1 - Documentation/git-status.txt | 1 - Documentation/git-tar-tree.txt | 1 - Documentation/git-unpack-file.txt | 1 - Documentation/git-unpack-objects.txt | 1 - Documentation/git-update-server-info.txt | 1 - Documentation/git-upload-pack.txt | 1 - Documentation/git-var.txt | 1 - Documentation/git-verify-pack.txt | 1 - Documentation/git-whatchanged.txt | 1 - Documentation/git-write-tree.txt | 1 - Documentation/git.txt | 1 - Documentation/hooks.txt | 1 - Documentation/repository-layout.txt | 1 - Documentation/tutorial.txt | 1 - 64 files changed, 64 deletions(-) diff --git a/Documentation/cvs-migration.txt b/Documentation/cvs-migration.txt index 4361278dab..02bdd6f446 100644 --- a/Documentation/cvs-migration.txt +++ b/Documentation/cvs-migration.txt @@ -1,6 +1,5 @@ Git for CVS users ================= -v0.99.5, Aug 2005 Ok, so you're a CVS user. That's ok, it's a treatable condition, and the first step to recovery is admitting you have a problem. The fact that diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt index e095f93c08..5e157ac7cd 100644 --- a/Documentation/git-apply.txt +++ b/Documentation/git-apply.txt @@ -1,6 +1,5 @@ git-apply(1) ============ -v0.1, June 2005 NAME ---- diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt index f21a6e06aa..ab4dcae21c 100644 --- a/Documentation/git-cat-file.txt +++ b/Documentation/git-cat-file.txt @@ -1,6 +1,5 @@ git-cat-file(1) =============== -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-checkout-index.txt b/Documentation/git-checkout-index.txt index 1ba6fb2d9c..613dfabe71 100644 --- a/Documentation/git-checkout-index.txt +++ b/Documentation/git-checkout-index.txt @@ -1,6 +1,5 @@ git-checkout-index(1) ===================== -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt index 8462e06853..26e0467797 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.txt @@ -1,6 +1,5 @@ git-cherry-pick(1) ================== -v0.99.5 Aug 2005 NAME ---- diff --git a/Documentation/git-clone-pack.txt b/Documentation/git-clone-pack.txt index a7868e53d7..1fb5280772 100644 --- a/Documentation/git-clone-pack.txt +++ b/Documentation/git-clone-pack.txt @@ -1,6 +1,5 @@ git-clone-pack(1) ================= -v0.1, July 2005 NAME ---- diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index 7d713c7385..5b8c6e8be3 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -1,6 +1,5 @@ git-clone(1) ============ -v0.1, July 2005 NAME ---- diff --git a/Documentation/git-commit-tree.txt b/Documentation/git-commit-tree.txt index 9aba868fa4..d9b0ab0717 100644 --- a/Documentation/git-commit-tree.txt +++ b/Documentation/git-commit-tree.txt @@ -1,6 +1,5 @@ git-commit-tree(1) ================== -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index 790a8eb0dd..236f7c4f32 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -1,6 +1,5 @@ git-commit(1) ============= -v0.99.4, Aug 2005 NAME ---- diff --git a/Documentation/git-convert-objects.txt b/Documentation/git-convert-objects.txt index 6ce62dc672..e6bda270cd 100644 --- a/Documentation/git-convert-objects.txt +++ b/Documentation/git-convert-objects.txt @@ -1,6 +1,5 @@ git-convert-objects(1) ====================== -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-cvsimport.txt b/Documentation/git-cvsimport.txt index b5753a46dc..4cae8b85b8 100644 --- a/Documentation/git-cvsimport.txt +++ b/Documentation/git-cvsimport.txt @@ -1,6 +1,5 @@ git-cvsimport(1) ================ -v0.1, July 2005 NAME ---- diff --git a/Documentation/git-diff-files.txt b/Documentation/git-diff-files.txt index eb9fb74259..e3873888f2 100644 --- a/Documentation/git-diff-files.txt +++ b/Documentation/git-diff-files.txt @@ -1,6 +1,5 @@ git-diff-files(1) ================= -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-diff-index.txt b/Documentation/git-diff-index.txt index 8b6a953c03..2fc3eed710 100644 --- a/Documentation/git-diff-index.txt +++ b/Documentation/git-diff-index.txt @@ -1,6 +1,5 @@ git-diff-index(1) ================= -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-diff-stages.txt b/Documentation/git-diff-stages.txt index 276d7bdc43..28c60fc7e4 100644 --- a/Documentation/git-diff-stages.txt +++ b/Documentation/git-diff-stages.txt @@ -1,6 +1,5 @@ git-diff-stages(1) ================== -v0.1, June 2005 NAME ---- diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt index 339a92287a..dcfb9e18c7 100644 --- a/Documentation/git-diff-tree.txt +++ b/Documentation/git-diff-tree.txt @@ -1,6 +1,5 @@ git-diff-tree(1) ================ -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt index 1d281820cf..a996b8f4f3 100644 --- a/Documentation/git-fetch-pack.txt +++ b/Documentation/git-fetch-pack.txt @@ -1,6 +1,5 @@ git-fetch-pack(1) ================= -v0.1, July 2005 NAME ---- diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.txt index 1fa9f4dbf4..c0b5aac5f2 100644 --- a/Documentation/git-fetch.txt +++ b/Documentation/git-fetch.txt @@ -1,6 +1,5 @@ git-fetch(1) ============ -v0.99.5, Aug 2005 NAME ---- diff --git a/Documentation/git-fsck-objects.txt b/Documentation/git-fsck-objects.txt index ba251a5152..8f76acf161 100644 --- a/Documentation/git-fsck-objects.txt +++ b/Documentation/git-fsck-objects.txt @@ -1,6 +1,5 @@ git-fsck-objects(1) =================== -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt index 5f082167c1..0175793483 100644 --- a/Documentation/git-grep.txt +++ b/Documentation/git-grep.txt @@ -1,6 +1,5 @@ git-grep(1) =========== -v0.99.6, Sep 2005 NAME ---- diff --git a/Documentation/git-hash-object.txt b/Documentation/git-hash-object.txt index 935cc66b38..9239f11135 100644 --- a/Documentation/git-hash-object.txt +++ b/Documentation/git-hash-object.txt @@ -1,6 +1,5 @@ git-hash-object(1) ================== -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-http-fetch.txt b/Documentation/git-http-fetch.txt index c034272568..d7b5919e1b 100644 --- a/Documentation/git-http-fetch.txt +++ b/Documentation/git-http-fetch.txt @@ -1,6 +1,5 @@ git-http-fetch(1) ================= -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-init-db.txt b/Documentation/git-init-db.txt index ef2d04a612..ef1826ae67 100644 --- a/Documentation/git-init-db.txt +++ b/Documentation/git-init-db.txt @@ -1,6 +1,5 @@ git-init-db(1) ============== -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-local-fetch.txt b/Documentation/git-local-fetch.txt index ccf9735924..afd400a8af 100644 --- a/Documentation/git-local-fetch.txt +++ b/Documentation/git-local-fetch.txt @@ -1,6 +1,5 @@ git-local-fetch(1) ================== -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt index 2a0e5aceab..16f48295c2 100644 --- a/Documentation/git-log.txt +++ b/Documentation/git-log.txt @@ -1,6 +1,5 @@ git-log(1) ========== -v0.99.4, Aug 2005 NAME ---- diff --git a/Documentation/git-ls-remote.txt b/Documentation/git-ls-remote.txt index 89bd609d65..c0a80d4089 100644 --- a/Documentation/git-ls-remote.txt +++ b/Documentation/git-ls-remote.txt @@ -1,6 +1,5 @@ git-ls-remote(1) ================ -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-ls-tree.txt b/Documentation/git-ls-tree.txt index 0d159fd5cc..cdc5654a99 100644 --- a/Documentation/git-ls-tree.txt +++ b/Documentation/git-ls-tree.txt @@ -1,6 +1,5 @@ git-ls-tree(1) ============== -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-merge-base.txt b/Documentation/git-merge-base.txt index e4692163ea..d1d56f194a 100644 --- a/Documentation/git-merge-base.txt +++ b/Documentation/git-merge-base.txt @@ -1,6 +1,5 @@ git-merge-base(1) ================= -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-merge-index.txt b/Documentation/git-merge-index.txt index 5caee90adc..d072fdaa4f 100644 --- a/Documentation/git-merge-index.txt +++ b/Documentation/git-merge-index.txt @@ -1,6 +1,5 @@ git-merge-index(1) ================== -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-merge-one-file.txt b/Documentation/git-merge-one-file.txt index 712739777b..86aad37c6a 100644 --- a/Documentation/git-merge-one-file.txt +++ b/Documentation/git-merge-one-file.txt @@ -1,6 +1,5 @@ git-merge-one-file(1) ===================== -v0.99.4, Aug 2005 NAME ---- diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt index dca363dd5e..a007a8b15a 100644 --- a/Documentation/git-merge.txt +++ b/Documentation/git-merge.txt @@ -1,6 +1,5 @@ git-merge(1) ============ -v0.99.6, Sep 2005 NAME ---- diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt index 44ed4b5408..2860a3d1ba 100644 --- a/Documentation/git-mktag.txt +++ b/Documentation/git-mktag.txt @@ -1,6 +1,5 @@ git-mktag(1) ============ -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-octopus.txt b/Documentation/git-octopus.txt index 881c317ac5..6e32ea347c 100644 --- a/Documentation/git-octopus.txt +++ b/Documentation/git-octopus.txt @@ -1,6 +1,5 @@ git-octopus(1) ============== -v0.99.5, Aug 2005 NAME ---- diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt index 44aba940d7..694c787df1 100644 --- a/Documentation/git-pack-objects.txt +++ b/Documentation/git-pack-objects.txt @@ -1,6 +1,5 @@ git-pack-objects(1) =================== -v0.1, July 2005 NAME ---- diff --git a/Documentation/git-peek-remote.txt b/Documentation/git-peek-remote.txt index c1527f1bcf..bd5a8817c3 100644 --- a/Documentation/git-peek-remote.txt +++ b/Documentation/git-peek-remote.txt @@ -1,6 +1,5 @@ git-peek-remote(1) ================== -v0.1, July 2005 NAME ---- diff --git a/Documentation/git-prune-packed.txt b/Documentation/git-prune-packed.txt index 5c48a0937a..28a1500d39 100644 --- a/Documentation/git-prune-packed.txt +++ b/Documentation/git-prune-packed.txt @@ -1,6 +1,5 @@ git-prune-packed(1) ===================== -v0.1, August 2005 NAME ---- diff --git a/Documentation/git-prune.txt b/Documentation/git-prune.txt index d1676cbfc8..3367c9b214 100644 --- a/Documentation/git-prune.txt +++ b/Documentation/git-prune.txt @@ -1,6 +1,5 @@ git-prune(1) ============ -v0.99.5, Aug 2005 NAME ---- diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt index c35d2eb54c..952779292b 100644 --- a/Documentation/git-pull.txt +++ b/Documentation/git-pull.txt @@ -1,6 +1,5 @@ git-pull(1) =========== -v0.99.4, Aug 2005 NAME ---- diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt index 5653baccaf..7db5fb5795 100644 --- a/Documentation/git-read-tree.txt +++ b/Documentation/git-read-tree.txt @@ -1,6 +1,5 @@ git-read-tree(1) ================ -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt index fb4b76b6c2..8afde14373 100644 --- a/Documentation/git-receive-pack.txt +++ b/Documentation/git-receive-pack.txt @@ -1,6 +1,5 @@ git-receive-pack(1) =================== -v0.1, July 2005 NAME ---- diff --git a/Documentation/git-rename.txt b/Documentation/git-rename.txt index 21928dc071..583cb0315e 100644 --- a/Documentation/git-rename.txt +++ b/Documentation/git-rename.txt @@ -1,6 +1,5 @@ git-rename(1) ============= -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt index bd830ada27..0c1ae49ed7 100644 --- a/Documentation/git-repack.txt +++ b/Documentation/git-repack.txt @@ -1,6 +1,5 @@ git-repack(1) ============= -v0.99.5, August 2005 NAME ---- diff --git a/Documentation/git-resolve.txt b/Documentation/git-resolve.txt index 7d3eb79033..db38e2407a 100644 --- a/Documentation/git-resolve.txt +++ b/Documentation/git-resolve.txt @@ -1,6 +1,5 @@ git-resolve(1) ============== -v0.99.5, Aug 2005 NAME ---- diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt index f386a3a79b..7dbb7c6607 100644 --- a/Documentation/git-rev-list.txt +++ b/Documentation/git-rev-list.txt @@ -1,6 +1,5 @@ git-rev-list(1) =============== -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt index b95e33db52..b9bec55e53 100644 --- a/Documentation/git-send-email.txt +++ b/Documentation/git-send-email.txt @@ -1,6 +1,5 @@ git-send-email(1) ================= -v0.1, July 2005 NAME ---- diff --git a/Documentation/git-send-pack.txt b/Documentation/git-send-pack.txt index 219dfc2ef6..577f06a214 100644 --- a/Documentation/git-send-pack.txt +++ b/Documentation/git-send-pack.txt @@ -1,6 +1,5 @@ git-send-pack(1) ================ -v0.1, July 2005 NAME ---- diff --git a/Documentation/git-shortlog.txt b/Documentation/git-shortlog.txt index a852e9b865..696a4245b5 100644 --- a/Documentation/git-shortlog.txt +++ b/Documentation/git-shortlog.txt @@ -1,6 +1,5 @@ git-shortlog(1) =============== -v0.99.4, Aug 2005 NAME ---- diff --git a/Documentation/git-show-branch.txt b/Documentation/git-show-branch.txt index 5b80d5aa2a..32da5ba330 100644 --- a/Documentation/git-show-branch.txt +++ b/Documentation/git-show-branch.txt @@ -1,6 +1,5 @@ git-show-branch(1) ================== -v0.99.5, Aug 2005 NAME ---- diff --git a/Documentation/git-show-index.txt b/Documentation/git-show-index.txt index 72720ada22..9605d676b0 100644 --- a/Documentation/git-show-index.txt +++ b/Documentation/git-show-index.txt @@ -1,6 +1,5 @@ git-show-index(1) ================= -v0.1, July 2005 NAME ---- diff --git a/Documentation/git-ssh-fetch.txt b/Documentation/git-ssh-fetch.txt index e3887ace09..b7116b30e0 100644 --- a/Documentation/git-ssh-fetch.txt +++ b/Documentation/git-ssh-fetch.txt @@ -1,6 +1,5 @@ git-ssh-fetch(1) ================ -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-ssh-upload.txt b/Documentation/git-ssh-upload.txt index b625019812..702674e45d 100644 --- a/Documentation/git-ssh-upload.txt +++ b/Documentation/git-ssh-upload.txt @@ -1,6 +1,5 @@ git-ssh-upload(1) ================= -v0.1, Jun 2005 NAME ---- diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt index 6d49a5aa0d..89a4f38203 100644 --- a/Documentation/git-status.txt +++ b/Documentation/git-status.txt @@ -1,6 +1,5 @@ git-status(1) ============= -v0.99.4, Aug 2005 NAME ---- diff --git a/Documentation/git-tar-tree.txt b/Documentation/git-tar-tree.txt index 480a0cf0ba..2139b6ff8c 100644 --- a/Documentation/git-tar-tree.txt +++ b/Documentation/git-tar-tree.txt @@ -1,6 +1,5 @@ git-tar-tree(1) =============== -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-unpack-file.txt b/Documentation/git-unpack-file.txt index 3903b2d99b..213dc8196b 100644 --- a/Documentation/git-unpack-file.txt +++ b/Documentation/git-unpack-file.txt @@ -1,6 +1,5 @@ git-unpack-file(1) ================== -v0.1, May 2005 NAME ---- diff --git a/Documentation/git-unpack-objects.txt b/Documentation/git-unpack-objects.txt index 9b982d996f..b716ba1ad3 100644 --- a/Documentation/git-unpack-objects.txt +++ b/Documentation/git-unpack-objects.txt @@ -1,6 +1,5 @@ git-unpack-objects(1) ===================== -v0.1, July 2005 NAME ---- diff --git a/Documentation/git-update-server-info.txt b/Documentation/git-update-server-info.txt index 2efd5400a7..3d0dea07fb 100644 --- a/Documentation/git-update-server-info.txt +++ b/Documentation/git-update-server-info.txt @@ -1,6 +1,5 @@ git-update-server-info(1) ========================= -v0.1, July 2005 NAME ---- diff --git a/Documentation/git-upload-pack.txt b/Documentation/git-upload-pack.txt index 98815b6a10..3d8f8ef667 100644 --- a/Documentation/git-upload-pack.txt +++ b/Documentation/git-upload-pack.txt @@ -1,6 +1,5 @@ git-upload-pack(1) ================== -v0.1, July 2005 NAME ---- diff --git a/Documentation/git-var.txt b/Documentation/git-var.txt index c1c7172088..c22d34f5fb 100644 --- a/Documentation/git-var.txt +++ b/Documentation/git-var.txt @@ -1,6 +1,5 @@ git-var(1) ========== -v0.1, July 2005 NAME ---- diff --git a/Documentation/git-verify-pack.txt b/Documentation/git-verify-pack.txt index b100aa765a..9b3946614f 100644 --- a/Documentation/git-verify-pack.txt +++ b/Documentation/git-verify-pack.txt @@ -1,6 +1,5 @@ git-verify-pack(1) ================== -v0.1, June 2005 NAME ---- diff --git a/Documentation/git-whatchanged.txt b/Documentation/git-whatchanged.txt index 056a9697c6..118a3fdb9e 100644 --- a/Documentation/git-whatchanged.txt +++ b/Documentation/git-whatchanged.txt @@ -1,6 +1,5 @@ git-whatchanged(1) ================== -v0.99.4, Aug 2005 NAME ---- diff --git a/Documentation/git-write-tree.txt b/Documentation/git-write-tree.txt index 71e16d128a..51be44d1f2 100644 --- a/Documentation/git-write-tree.txt +++ b/Documentation/git-write-tree.txt @@ -1,6 +1,5 @@ git-write-tree(1) ================= -v0.1, May 2005 NAME ---- diff --git a/Documentation/git.txt b/Documentation/git.txt index e141021279..f8dd76ac24 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -1,6 +1,5 @@ git(7) ====== -v0.99.6, Sep 2005 NAME ---- diff --git a/Documentation/hooks.txt b/Documentation/hooks.txt index 57f4720871..c324e17db0 100644 --- a/Documentation/hooks.txt +++ b/Documentation/hooks.txt @@ -1,6 +1,5 @@ Hooks used by GIT ================= -v0.99.6, Sep 2005 Hooks are little scripts you can place in `$GIT_DIR/hooks` directory to trigger action at certain points. When diff --git a/Documentation/repository-layout.txt b/Documentation/repository-layout.txt index d20fa80d87..352253555f 100644 --- a/Documentation/repository-layout.txt +++ b/Documentation/repository-layout.txt @@ -1,6 +1,5 @@ GIT repository layout ===================== -v0.99.5, Sep 2005 You may find these things in your git repository (`.git` directory for a repository associated with your working tree, or diff --git a/Documentation/tutorial.txt b/Documentation/tutorial.txt index 36f42e051c..619acc48bb 100644 --- a/Documentation/tutorial.txt +++ b/Documentation/tutorial.txt @@ -1,6 +1,5 @@ A short git tutorial ==================== -v0.99.5, Aug 2005 Introduction ------------ From 72e9340cfde90189d76ef3c8a4793ea7764ff8ee Mon Sep 17 00:00:00 2001 From: Christian Meder Date: Mon, 10 Oct 2005 16:01:31 -0700 Subject: [PATCH 071/254] Convert usage of GIT and Git into git Convert usage of GIT and Git into git. Signed-off-by: Christian Meder Signed-off-by: Junio C Hamano --- Documentation/cvs-migration.txt | 14 +++++++------- Documentation/diff-format.txt | 2 +- Documentation/diffcore.txt | 2 +- Documentation/git-apply.txt | 2 +- Documentation/git-archimport.txt | 8 ++++---- Documentation/git-clone-pack.txt | 2 +- Documentation/git-convert-objects.txt | 4 ++-- Documentation/git-cvsimport.txt | 4 ++-- Documentation/git-daemon.txt | 2 +- Documentation/git-fetch-pack.txt | 2 +- Documentation/git-fsck-objects.txt | 10 +++++----- Documentation/git-http-fetch.txt | 4 ++-- Documentation/git-local-fetch.txt | 4 ++-- Documentation/git-pack-objects.txt | 2 +- Documentation/git-peek-remote.txt | 2 +- Documentation/git-rev-parse.txt | 2 +- Documentation/git-show-index.txt | 2 +- Documentation/git-verify-pack.txt | 4 ++-- Documentation/git.txt | 10 +++++----- Documentation/glossary.txt | 2 +- Documentation/hooks.txt | 2 +- Documentation/pull-fetch-param.txt | 2 +- Documentation/repository-layout.txt | 4 ++-- Documentation/tutorial.txt | 18 +++++++++--------- 24 files changed, 55 insertions(+), 55 deletions(-) diff --git a/Documentation/cvs-migration.txt b/Documentation/cvs-migration.txt index 02bdd6f446..57436f0078 100644 --- a/Documentation/cvs-migration.txt +++ b/Documentation/cvs-migration.txt @@ -1,4 +1,4 @@ -Git for CVS users +git for CVS users ================= Ok, so you're a CVS user. That's ok, it's a treatable condition, and the @@ -7,7 +7,7 @@ you are reading this file means that you may be well on that path already. The thing about CVS is that it absolutely sucks as a source control -manager, and you'll thus be happy with almost anything else. Git, +manager, and you'll thus be happy with almost anything else. git, however, may be a bit 'too' different (read: "good") for your taste, and does a lot of things differently. @@ -15,7 +15,7 @@ One particular suckage of CVS is very hard to work around: CVS is basically a tool for tracking 'file' history, while git is a tool for tracking 'project' history. This sometimes causes problems if you are used to doing very strange things in CVS, in particular if you're doing -things like making branches of just a subset of the project. Git can't +things like making branches of just a subset of the project. git can't track that, since git never tracks things on the level of an individual file, only on the whole project level. @@ -32,7 +32,7 @@ and notes on converting from CVS to git. Second: CVS has the notion of a "repository" as opposed to the thing that you're actually working in (your working directory, or your -"checked out tree"). Git does not have that notion at all, and all git +"checked out tree"). git does not have that notion at all, and all git working directories 'are' the repositories. However, you can easily emulate the CVS model by having one special "global repository", which people can synchronize with. See details later, but in the meantime @@ -49,7 +49,7 @@ gone through the git tutorial, and generally familiarized yourself with how to commit stuff etc in git) is to create a git'ified version of your CVS archive. -Happily, that's very easy indeed. Git will do it for you, although git +Happily, that's very easy indeed. git will do it for you, although git will need the help of a program called "cvsps": http://www.cobite.com/cvsps/ @@ -135,7 +135,7 @@ technically possible, and there are at least two specialized scripts out there that can be used to get equivalent information (see the git mailing list archives for details). -Git has a couple of alternatives, though, that you may find sufficient +git has a couple of alternatives, though, that you may find sufficient or even superior depending on your use. One is called "git-whatchanged" (for obvious reasons) and the other one is called "pickaxe" ("a tool for the software archeologist"). @@ -208,7 +208,7 @@ show anything for commits that do not touch this "if" statement. Also, in the original context, the same statement might have appeared at first in a different file and later the file was renamed to "a-file.c". CVS annotate would not help you to go -back across such a rename, but GIT would still help you in such +back across such a rename, but git would still help you in such a situation. For that, you can give the -C flag to git-diff-tree, like this: diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt index dacd8fb534..bfe634dcd3 100644 --- a/Documentation/diff-format.txt +++ b/Documentation/diff-format.txt @@ -106,7 +106,7 @@ For a path that is unmerged, 'GIT_EXTERNAL_DIFF' is called with 1 parameter, . -Git specific extension to diff format +git specific extension to diff format ------------------------------------- What -p option produces is slightly different from the diff --git a/Documentation/diffcore.txt b/Documentation/diffcore.txt index 9d20a4ff19..7c2168a992 100644 --- a/Documentation/diffcore.txt +++ b/Documentation/diffcore.txt @@ -250,7 +250,7 @@ pattern. Filepairs that match a glob pattern on an earlier line in the file are output before ones that match a later line, and filepairs that do not match any glob pattern are output last. -As an example, typical orderfile for the core GIT probably +As an example, typical orderfile for the core git probably would look like this: ------------------------------------------------ diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt index 5e157ac7cd..61d9dacc6f 100644 --- a/Documentation/git-apply.txt +++ b/Documentation/git-apply.txt @@ -3,7 +3,7 @@ git-apply(1) NAME ---- -git-apply - Apply patch on a GIT index file and a work tree +git-apply - Apply patch on a git index file and a work tree SYNOPSIS diff --git a/Documentation/git-archimport.txt b/Documentation/git-archimport.txt index b6793cf55e..fcda0125af 100644 --- a/Documentation/git-archimport.txt +++ b/Documentation/git-archimport.txt @@ -3,7 +3,7 @@ git-archimport(1) NAME ---- -git-archimport - Import an Arch repository into GIT +git-archimport - Import an Arch repository into git SYNOPSIS @@ -40,14 +40,14 @@ incremental imports. MERGES ------ -Patch merge data from Arch is used to mark merges in GIT as well. GIT +Patch merge data from Arch is used to mark merges in git as well. git does not care much about tracking patches, and only considers a merge when a branch incorporates all the commits since the point they forked. The end result -is that GIT will have a good idea of how far branches have diverged. So the +is that git will have a good idea of how far branches have diverged. So the import process does lose some patch-trading metadata. Fortunately, when you try and merge branches imported from Arch, -GIT will find a good merge base, and it has a good chance of identifying +git will find a good merge base, and it has a good chance of identifying patches that have been traded out-of-sequence between the branches. OPTIONS diff --git a/Documentation/git-clone-pack.txt b/Documentation/git-clone-pack.txt index 1fb5280772..87c0e460d4 100644 --- a/Documentation/git-clone-pack.txt +++ b/Documentation/git-clone-pack.txt @@ -28,7 +28,7 @@ OPTIONS remote side, if it is not found on your $PATH. Installations of sshd ignore the user's environment setup scripts for login shells (e.g. .bash_profile) and - your privately installed GIT may not be found on the system + your privately installed git may not be found on the system default $PATH. Another workaround suggested is to set up your $PATH in ".bashrc", but this flag is for people who do not want to pay the overhead for non-interactive diff --git a/Documentation/git-convert-objects.txt b/Documentation/git-convert-objects.txt index e6bda270cd..b1220c06e1 100644 --- a/Documentation/git-convert-objects.txt +++ b/Documentation/git-convert-objects.txt @@ -3,7 +3,7 @@ git-convert-objects(1) NAME ---- -git-convert-objects - Converts old-style GIT repository +git-convert-objects - Converts old-style git repository SYNOPSIS @@ -12,7 +12,7 @@ SYNOPSIS DESCRIPTION ----------- -Converts old-style GIT repository to the latest format +Converts old-style git repository to the latest format Author diff --git a/Documentation/git-cvsimport.txt b/Documentation/git-cvsimport.txt index 4cae8b85b8..f5248c91cb 100644 --- a/Documentation/git-cvsimport.txt +++ b/Documentation/git-cvsimport.txt @@ -10,7 +10,7 @@ SYNOPSIS -------- 'git-cvsimport' [ -o ] [ -h ] [ -v ] [ -d ] [ -p ] - [ -C ] [ -i ] [ -k ] + [ -C ] [ -i ] [ -k ] [ -s ] [ -m ] [ -M regex ] [ ] @@ -30,7 +30,7 @@ OPTIONS are supported. -C :: - The GIT repository to import to. If the directory doesn't + The git repository to import to. If the directory doesn't exist, it will be created. Default is the current directory. -i:: diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt index 065f2aa721..a013a58a7f 100644 --- a/Documentation/git-daemon.txt +++ b/Documentation/git-daemon.txt @@ -3,7 +3,7 @@ git-daemon(1) NAME ---- -git-daemon - A really simple server for GIT repositories. +git-daemon - A really simple server for git repositories. SYNOPSIS -------- diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt index a996b8f4f3..ea6faab059 100644 --- a/Documentation/git-fetch-pack.txt +++ b/Documentation/git-fetch-pack.txt @@ -34,7 +34,7 @@ OPTIONS remote side, if is not found on your $PATH. Installations of sshd ignores the user's environment setup scripts for login shells (e.g. .bash_profile) and - your privately installed GIT may not be found on the system + your privately installed git may not be found on the system default $PATH. Another workaround suggested is to set up your $PATH in ".bashrc", but this flag is for people who do not want to pay the overhead for non-interactive diff --git a/Documentation/git-fsck-objects.txt b/Documentation/git-fsck-objects.txt index 8f76acf161..5dc9dbdd78 100644 --- a/Documentation/git-fsck-objects.txt +++ b/Documentation/git-fsck-objects.txt @@ -41,22 +41,22 @@ index file and all SHA1 references in .git/refs/* as heads. ($GIT_DIR/objects), making sure that it is consistent and complete without referring to objects found in alternate object pools listed in GIT_ALTERNATE_OBJECT_DIRECTORIES, - nor packed GIT archives found in $GIT_DIR/objects/pack; + nor packed git archives found in $GIT_DIR/objects/pack; cannot be used with --full. --full:: Check not just objects in GIT_OBJECT_DIRECTORY ($GIT_DIR/objects), but also the ones found in alternate object pools listed in GIT_ALTERNATE_OBJECT_DIRECTORIES, - and in packed GIT archives found in $GIT_DIR/objects/pack + and in packed git archives found in $GIT_DIR/objects/pack and corresponding pack subdirectories in alternate object pools; cannot be used with --standalone. --strict:: Enable more strict checking, namely to catch a file mode recorded with g+w bit set, which was created by older - versions of GIT. Existing repositories, including the - Linux kernel, GIT itself, and sparse repository have old + versions of git. Existing repositories, including the + Linux kernel, git itself, and sparse repository have old objects that triggers this check, but it is recommended to check new projects with this flag. @@ -80,7 +80,7 @@ Any corrupt objects you will have to find in backups or other archives the hopes that somebody else has the object you have corrupted). Of course, "valid tree" doesn't mean that it wasn't generated by some -evil person, and the end result might be crap. Git is a revision +evil person, and the end result might be crap. git is a revision tracking system, not a quality assurance system ;) Extracted Diagnostics diff --git a/Documentation/git-http-fetch.txt b/Documentation/git-http-fetch.txt index d7b5919e1b..088624f6cc 100644 --- a/Documentation/git-http-fetch.txt +++ b/Documentation/git-http-fetch.txt @@ -3,7 +3,7 @@ git-http-fetch(1) NAME ---- -git-http-fetch - Downloads a remote GIT repository via HTTP +git-http-fetch - Downloads a remote git repository via HTTP SYNOPSIS @@ -12,7 +12,7 @@ SYNOPSIS DESCRIPTION ----------- -Downloads a remote GIT repository via HTTP. +Downloads a remote git repository via HTTP. -c:: Get the commit objects. diff --git a/Documentation/git-local-fetch.txt b/Documentation/git-local-fetch.txt index afd400a8af..87abec1c4e 100644 --- a/Documentation/git-local-fetch.txt +++ b/Documentation/git-local-fetch.txt @@ -3,7 +3,7 @@ git-local-fetch(1) NAME ---- -git-local-fetch - Duplicates another GIT repository on a local system +git-local-fetch - Duplicates another git repository on a local system SYNOPSIS @@ -12,7 +12,7 @@ SYNOPSIS DESCRIPTION ----------- -Duplicates another GIT repository on a local system. +Duplicates another git repository on a local system. OPTIONS ------- diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt index 694c787df1..caf5d0d1ee 100644 --- a/Documentation/git-pack-objects.txt +++ b/Documentation/git-pack-objects.txt @@ -30,7 +30,7 @@ transport by their peers. Placing both in the pack/ subdirectory of $GIT_OBJECT_DIRECTORY (or any of the directories on $GIT_ALTERNATE_OBJECT_DIRECTORIES) -enables GIT to read from such an archive. +enables git to read from such an archive. OPTIONS diff --git a/Documentation/git-peek-remote.txt b/Documentation/git-peek-remote.txt index bd5a8817c3..915d3f8a06 100644 --- a/Documentation/git-peek-remote.txt +++ b/Documentation/git-peek-remote.txt @@ -22,7 +22,7 @@ OPTIONS remote side, if it is not found on your $PATH. Some installations of sshd ignores the user's environment setup scripts for login shells (e.g. .bash_profile) and - your privately installed GIT may not be found on the system + your privately installed git may not be found on the system default $PATH. Another workaround suggested is to set up your $PATH in ".bashrc", but this flag is for people who do not want to pay the overhead for non-interactive diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt index 99fd90e376..694f3a09d4 100644 --- a/Documentation/git-rev-parse.txt +++ b/Documentation/git-rev-parse.txt @@ -91,7 +91,7 @@ what is called an 'extended SHA1' syntax. * A symbolic ref name. E.g. 'master' typically means the commit object referenced by $GIT_DIR/refs/heads/master. If you happen to have both heads/master and tags/master, you can - explicitly say 'heads/master' to tell GIT which one you mean. + explicitly say 'heads/master' to tell git which one you mean. * A suffix '{caret}' to a revision parameter means the first parent of that commit object. '{caret}' means the th parent (i.e. diff --git a/Documentation/git-show-index.txt b/Documentation/git-show-index.txt index 9605d676b0..be09b62beb 100644 --- a/Documentation/git-show-index.txt +++ b/Documentation/git-show-index.txt @@ -13,7 +13,7 @@ SYNOPSIS DESCRIPTION ----------- -Reads given idx file for packed GIT archive created with +Reads given idx file for packed git archive created with git-pack-objects command, and dumps its contents. The information it outputs is subset of what you can get from diff --git a/Documentation/git-verify-pack.txt b/Documentation/git-verify-pack.txt index 9b3946614f..cd74ffd391 100644 --- a/Documentation/git-verify-pack.txt +++ b/Documentation/git-verify-pack.txt @@ -3,7 +3,7 @@ git-verify-pack(1) NAME ---- -git-verify-pack - Validate packed GIT archive files. +git-verify-pack - Validate packed git archive files. SYNOPSIS @@ -13,7 +13,7 @@ SYNOPSIS DESCRIPTION ----------- -Reads given idx file for packed GIT archive created with +Reads given idx file for packed git archive created with git-pack-objects command and verifies idx file and the corresponding pack file. diff --git a/Documentation/git.txt b/Documentation/git.txt index f8dd76ac24..243c00a178 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -146,7 +146,7 @@ gitlink:git-var[1]:: Displays a git logical variable gitlink:git-verify-pack[1]:: - Validates packed GIT archive files + Validates packed git archive files The interrogate commands may create files - and you can force them to touch the working file set - but in general they don't @@ -163,11 +163,11 @@ gitlink:git-fetch-pack[1]:: Updates from a remote repository. gitlink:git-http-fetch[1]:: - Downloads a remote GIT repository via HTTP + Downloads a remote git repository via HTTP Previously this command was known as git-http-pull. gitlink:git-local-fetch[1]:: - Duplicates another GIT repository on a local system + Duplicates another git repository on a local system Previously this command was known as git-local-pull. gitlink:git-peek-remote[1]:: @@ -322,7 +322,7 @@ gitlink:git-archimport[1]:: Previously this command was known as git-archimport-script. gitlink:git-convert-objects[1]:: - Converts old-style GIT repository + Converts old-style git repository Previously this command was known as git-convert-cache. gitlink:git-cvsimport[1]:: @@ -360,7 +360,7 @@ gitlink:git-count-objects[1]:: Previously this command was known as git-count-objects-script. gitlink:git-daemon[1]:: - A really simple server for GIT repositories. + A really simple server for git repositories. gitlink:git-get-tar-commit-id[1]:: Extract commit ID from an archive created using git-tar-tree. diff --git a/Documentation/glossary.txt b/Documentation/glossary.txt index a069b7bb0c..eb7b471024 100644 --- a/Documentation/glossary.txt +++ b/Documentation/glossary.txt @@ -1,5 +1,5 @@ object:: - The unit of storage in GIT. It is uniquely identified by + The unit of storage in git. It is uniquely identified by the SHA1 of its contents. Consequently, an object can not be changed. diff --git a/Documentation/hooks.txt b/Documentation/hooks.txt index c324e17db0..7ee3571bc0 100644 --- a/Documentation/hooks.txt +++ b/Documentation/hooks.txt @@ -1,4 +1,4 @@ -Hooks used by GIT +Hooks used by git ================= Hooks are little scripts you can place in `$GIT_DIR/hooks` diff --git a/Documentation/pull-fetch-param.txt b/Documentation/pull-fetch-param.txt index 8dbddbf63f..51222b6f3f 100644 --- a/Documentation/pull-fetch-param.txt +++ b/Documentation/pull-fetch-param.txt @@ -6,7 +6,7 @@ =============================================================== - Rsync URL: rsync://remote.machine/path/to/repo.git/ - HTTP(s) URL: http://remote.machine/path/to/repo.git/ -- GIT URL: git://remote.machine/path/to/repo.git/ +- git URL: git://remote.machine/path/to/repo.git/ or remote.machine:/path/to/repo.git/ - Local directory: /path/to/repo.git/ =============================================================== diff --git a/Documentation/repository-layout.txt b/Documentation/repository-layout.txt index 352253555f..1b5f228241 100644 --- a/Documentation/repository-layout.txt +++ b/Documentation/repository-layout.txt @@ -1,4 +1,4 @@ -GIT repository layout +git repository layout ===================== You may find these things in your git repository (`.git` @@ -119,7 +119,7 @@ info/grafts:: info/exclude:: This file, by convention among Porcelains, stores the exclude pattern list. `git status` looks at it, but - otherwise it is not looked at by any of the core GIT + otherwise it is not looked at by any of the core git commands. remotes:: diff --git a/Documentation/tutorial.txt b/Documentation/tutorial.txt index 619acc48bb..19da3e243e 100644 --- a/Documentation/tutorial.txt +++ b/Documentation/tutorial.txt @@ -160,7 +160,7 @@ you'll have to use the object name, not the filename of the object: git-cat-file -t 557db03de997c86a4a028e1ebd3a1ceb225be238 where the `-t` tells `git-cat-file` to tell you what the "type" of the -object is. Git will tell you that you have a "blob" object (ie just a +object is. git will tell you that you have a "blob" object (ie just a regular file), and you can see the contents with git-cat-file "blob" 557db03 @@ -377,7 +377,7 @@ come from the working tree or not. This is not hard to understand, as soon as you realize that git simply never knows (or cares) about files that it is not told about -explicitly. Git will never go *looking* for files to compare, it +explicitly. git will never go *looking* for files to compare, it expects you to tell it what the files are, and that's what the index is there for. ================ @@ -543,7 +543,7 @@ name for the state at that point. Copying repositories -------------------- -Git repositories are normally totally self-sufficient, and it's worth noting +git repositories are normally totally self-sufficient, and it's worth noting that unlike CVS, for example, there is no separate notion of "repository" and "working tree". A git repository normally *is* the working tree, with the local git information hidden in the `.git` @@ -950,7 +950,7 @@ This transport is the same as SSH transport but uses `sh` to run both ends on the local machine instead of running other end on the remote machine via `ssh`. -GIT Native:: +git Native:: `git://remote.machine/path/to/repo.git/` + This transport was designed for anonymous downloading. Like SSH @@ -971,13 +971,13 @@ necessary objects. Because of this behaviour, they are sometimes also called 'commit walkers'. + The 'commit walkers' are sometimes also called 'dumb -transports', because they do not require any GIT aware smart -server like GIT Native transport does. Any stock HTTP server +transports', because they do not require any git aware smart +server like git Native transport does. Any stock HTTP server would suffice. + There are (confusingly enough) `git-ssh-fetch` and `git-ssh-upload` programs, which are 'commit walkers'; they outlived their -usefulness when GIT Native and SSH transports were introduced, +usefulness when git Native and SSH transports were introduced, and not used by `git pull` or `git push` scripts. Once you fetch from the remote repository, you `resolve` that @@ -1081,7 +1081,7 @@ done only once. on the remote machine. The communication between the two over the network internally uses an SSH connection. -Your private repository's GIT directory is usually `.git`, but +Your private repository's git directory is usually `.git`, but your public repository is often named after the project name, i.e. `.git`. Let's create such a public repository for project `my-git`. After logging into the remote machine, create @@ -1089,7 +1089,7 @@ an empty directory: mkdir my-git.git -Then, make that directory into a GIT repository by running +Then, make that directory into a git repository by running `git init-db`, but this time, since its name is not the usual `.git`, we do things slightly differently: From cc1621e2a02ed2a408571ed6f6ba84de2166e334 Mon Sep 17 00:00:00 2001 From: Christian Meder Date: Mon, 10 Oct 2005 16:01:32 -0700 Subject: [PATCH 072/254] The synopsis of the manpages should use the hyphenated version The synopsis of the manpages should use the hyphenated version of the git commands. Adapt the remaining offenders. Signed-off-by: Christian Meder Signed-off-by: Junio C Hamano --- Documentation/git-clone.txt | 2 +- Documentation/git-commit.txt | 2 +- Documentation/git-log.txt | 2 +- Documentation/git-resolve.txt | 2 +- Documentation/git-shortlog.txt | 2 +- Documentation/git-show-branch.txt | 2 +- Documentation/git-status.txt | 2 +- Documentation/git-whatchanged.txt | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index 5b8c6e8be3..dd92cdefc2 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -8,7 +8,7 @@ git-clone - Clones a repository. SYNOPSIS -------- -'git clone' [-l [-s]] [-q] [-n] [-u ] +'git-clone' [-l [-s]] [-q] [-n] [-u ] DESCRIPTION ----------- diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index 236f7c4f32..1edc278c64 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -7,7 +7,7 @@ git-commit - Record your changes SYNOPSIS -------- -'git commit' [-a] [-s] [-v] [(-c | -C) | -F | -m ] [-e] ... +'git-commit' [-a] [-s] [-v] [(-c | -C) | -F | -m ] [-e] ... DESCRIPTION ----------- diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt index 16f48295c2..13a3998302 100644 --- a/Documentation/git-log.txt +++ b/Documentation/git-log.txt @@ -8,7 +8,7 @@ git-log - Show commit logs SYNOPSIS -------- -'git log'