From 1775451793b4538e27047dfdb2feec4b46b766a9 Mon Sep 17 00:00:00 2001 From: hpa Date: Wed, 28 Sep 2005 16:37:37 -0700 Subject: Options to compile on Cygwin --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Makefile') 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 -- cgit v1.3-5-g9baa From 49744d63e9c5ffdfb4677bd3aaeafb3371c3fdc1 Mon Sep 17 00:00:00 2001 From: hpa Date: Wed, 28 Sep 2005 16:52:21 -0700 Subject: Call it NO_IPV6 rather than hard-coding __CYGWIN__ --- Makefile | 12 +++++++++++- connect.c | 6 +++--- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'Makefile') 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. -- cgit v1.3-5-g9baa From 6573faff34eb002535843bbb59365be4ad58a120 Mon Sep 17 00:00:00 2001 From: Peter Anvin Date: Wed, 28 Sep 2005 17:26:44 -0700 Subject: NO_IPV6 support for git daemon --- Makefile | 2 +- connect.c | 2 +- daemon.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 77 insertions(+), 18 deletions(-) (limited to 'Makefile') 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); } -- cgit v1.3-5-g9baa From dc4afa57ce3e07645690bec1e4c20ab59e8a9bd0 Mon Sep 17 00:00:00 2001 From: Peter Anvin Date: Wed, 28 Sep 2005 18:00:24 -0700 Subject: Remove *.exe for Cygwin's benefit --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') 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) -- cgit v1.3-5-g9baa From a23cd8ece70262fac2a80ef3e454c1cf1c63605a Mon Sep 17 00:00:00 2001 From: Peter Anvin Date: Wed, 28 Sep 2005 19:08:37 -0700 Subject: Handle Cygwin .exe extensions --- Makefile | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'Makefile') 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) -- cgit v1.3-5-g9baa From bb8c91d617e8a2ab4a78712086d1574da6e24e68 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 28 Sep 2005 23:31:18 -0700 Subject: Just explicitly add $(X) to most programs. --- Makefile | 55 +++++++++++++++++++++++++------------------------------ 1 file changed, 25 insertions(+), 30 deletions(-) (limited to 'Makefile') 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) -- cgit v1.3-5-g9baa From fef1ef8e1b87f28f019bf973547644e41f4be7cd Mon Sep 17 00:00:00 2001 From: hpa Date: Thu, 29 Sep 2005 10:38:26 -0700 Subject: git-http-fetch needs $(X) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') 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 -- cgit v1.3-5-g9baa From 2f29dd521832540450610893319561a5a136b3fb Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 30 Sep 2005 10:46:25 -0700 Subject: Change $(X) -> $X to be less annoying. --- Makefile | 66 ++++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) (limited to 'Makefile') 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: -- cgit v1.3-5-g9baa From 039c6f162a63e9d91f360e2e6138e21a4015c543 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 30 Sep 2005 11:02:26 -0700 Subject: Better handling of exec extension in the git wrapper script --- Makefile | 3 ++- git.sh | 16 +++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) (limited to 'Makefile') 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]" -- cgit v1.3-5-g9baa From baaac6a7143ad07de62926421f8740cd640c241c Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 2 Oct 2005 16:37:27 -0700 Subject: Post 0.99.8 master branch Signed-off-by: Junio C Hamano --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') 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) -- cgit v1.3-5-g9baa From c8c5b21a3714db3272f869c82f3ce862ed9c2cc6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 3 Oct 2005 16:05:50 -0700 Subject: [PATCH] Merging the Cygwin changes Fix mismerge typo. Signed-off-by: Junio C Hamano --- Makefile | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'Makefile') 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 $@+ $@ -- cgit v1.3-5-g9baa From 4514385edd913f6c10fa03c828effc5ba974369e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 3 Oct 2005 19:05:01 -0700 Subject: 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(+) (limited to 'Makefile') 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 -- cgit v1.3-5-g9baa From 3ff8cbeda635422f4740d325d56288dfdea10179 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 4 Oct 2005 12:41:35 -0700 Subject: 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(-) (limited to 'Makefile') 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) -- cgit v1.3-5-g9baa From d1c5f2a42d7b5c0e3d3862212dea1f09809c4963 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 7 Oct 2005 03:44:18 -0700 Subject: 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 (limited to 'Makefile') 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" -- cgit v1.3-5-g9baa From 730d48a2ef88a7fb7aa4409d40b1e6964a93267f Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 8 Oct 2005 15:54:36 -0700 Subject: [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 (limited to 'Makefile') 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 -- cgit v1.3-5-g9baa From d2b8593fd3754cf2e0b9a121fe6ba63bfefa3a47 Mon Sep 17 00:00:00 2001 From: Kai Ruemmler Date: Sat, 8 Oct 2005 15:54:37 -0700 Subject: 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(-) (limited to 'Makefile') 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) -- cgit v1.3-5-g9baa From f7c153431b4049e7697664dee4a3d71013422f9d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 9 Oct 2005 12:52:35 -0700 Subject: 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(-) (limited to 'Makefile') 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 -- cgit v1.3-5-g9baa From eaf718f3ece277462de4e47391e5a965bbbaa297 Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Mon, 10 Oct 2005 11:40:43 +0200 Subject: 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 (limited to 'Makefile') 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); -- cgit v1.3-5-g9baa From 4769948afe7c502d37746edc2ee2c084c9dcb325 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 10 Oct 2005 13:50:01 -0700 Subject: 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(-) (limited to 'Makefile') 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 -) -- cgit v1.3-5-g9baa From 17712991a59824a8d22d5115c0c154d3122fc17b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 10 Oct 2005 16:31:08 -0700 Subject: Add ".git/config" file parser This is a first cut at a very simple parser for a git config file. The format of the file is a simple ini-file like thing, with simple variable/value pairs. You can (and should) make the variables have a simple single-level scope, ie a valid file looks something like this: # # This is the config file, and # a '#' or ';' character indicates # a comment # ; core variables [core] ; Don't trust file modes filemode = false ; Our diff algorithm [diff] external = "/usr/local/bin/gnu-diff -u" renames = true which parses into three variables: "core.filemode" is associated with the string "false", and "diff.external" gets the appropriate quoted value. Right now we only react to one variable: "core.filemode" is a boolean that decides if we should care about the 0100 (user-execute) bit of the stat information. Even that is just a parsing demonstration - this doesn't actually implement that st_mode compare logic itself. Different programs can react to different config options, although they should always fall back to calling "git_default_config()" on any config option name that they don't recognize. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- Makefile | 2 +- cache.h | 8 +++ config.c | 222 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff-files.c | 1 + diff-tree.c | 1 + read-cache.c | 1 + 6 files changed, 234 insertions(+), 1 deletion(-) create mode 100644 config.c (limited to 'Makefile') diff --git a/Makefile b/Makefile index 0ca8e8d270..c31af7b3c3 100644 --- a/Makefile +++ b/Makefile @@ -158,7 +158,7 @@ LIB_OBJS = \ object.o pack-check.o patch-delta.o path.o pkt-line.o \ quote.o read-cache.o refs.o run-command.o \ server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \ - tag.o tree.o usage.o $(DIFF_OBJS) + tag.o tree.o usage.o config.o $(DIFF_OBJS) LIBS = $(LIB_FILE) LIBS += -lz diff --git a/cache.h b/cache.h index 5987d4c125..0571282e8c 100644 --- a/cache.h +++ b/cache.h @@ -178,6 +178,8 @@ extern int hold_index_file_for_update(struct cache_file *, const char *path); extern int commit_index_file(struct cache_file *); extern void rollback_index_file(struct cache_file *); +extern int trust_executable_bit; + #define MTIME_CHANGED 0x0001 #define CTIME_CHANGED 0x0002 #define OWNER_CHANGED 0x0004 @@ -372,4 +374,10 @@ extern int gitfakemunmap(void *start, size_t length); #endif +typedef int (*config_fn_t)(const char *, const char *); +extern int git_default_config(const char *, const char *); +extern int git_config(config_fn_t fn); +extern int git_config_int(const char *, const char *); +extern int git_config_bool(const char *, const char *); + #endif /* CACHE_H */ diff --git a/config.c b/config.c new file mode 100644 index 0000000000..f3c4fa42ac --- /dev/null +++ b/config.c @@ -0,0 +1,222 @@ +#include + +#include "cache.h" + +#define MAXNAME (256) + +static FILE *config_file; +static int config_linenr; +static int get_next_char(void) +{ + int c; + FILE *f; + + c = '\n'; + if ((f = config_file) != NULL) { + c = fgetc(f); + if (c == '\n') + config_linenr++; + if (c == EOF) { + config_file = NULL; + c = '\n'; + } + } + return c; +} + +static char *parse_value(void) +{ + static char value[1024]; + int quote = 0, comment = 0, len = 0, space = 0; + + for (;;) { + int c = get_next_char(); + if (len >= sizeof(value)) + return NULL; + if (c == '\n') { + if (quote) + return NULL; + value[len] = 0; + return value; + } + if (comment) + continue; + if (isspace(c) && !quote) { + space = 1; + continue; + } + if (space) { + if (len) + value[len++] = ' '; + space = 0; + } + if (c == '\\') { + c = get_next_char(); + switch (c) { + case '\n': + continue; + case 't': + c = '\t'; + break; + case 'b': + c = '\b'; + break; + case 'n': + c = '\n'; + break; + return NULL; + } + value[len++] = c; + continue; + } + if (c == '"') { + quote = 1-quote; + continue; + } + if (!quote) { + if (c == ';' || c == '#') { + comment = 1; + continue; + } + } + value[len++] = c; + } +} + +static int get_value(config_fn_t fn, char *name, unsigned int len) +{ + int c; + char *value; + + /* Get the full name */ + for (;;) { + c = get_next_char(); + if (c == EOF) + break; + if (!isalnum(c)) + break; + name[len++] = tolower(c); + if (len >= MAXNAME) + return -1; + } + name[len] = 0; + while (c == ' ' || c == '\t') + c = get_next_char(); + + value = NULL; + if (c != '\n') { + if (c != '=') + return -1; + value = parse_value(); + if (!value) + return -1; + } + return fn(name, value); +} + +static int get_base_var(char *name) +{ + int baselen = 0; + + for (;;) { + int c = get_next_char(); + if (c == EOF) + return -1; + if (c == ']') + return baselen; + if (!isalnum(c)) + return -1; + if (baselen > MAXNAME / 2) + return -1; + name[baselen++] = tolower(c); + } +} + +static int git_parse_file(config_fn_t fn) +{ + int comment = 0; + int baselen = 0; + static char var[MAXNAME]; + + for (;;) { + int c = get_next_char(); + if (c == '\n') { + /* EOF? */ + if (!config_file) + return 0; + comment = 0; + continue; + } + if (comment || isspace(c)) + continue; + if (c == '#' || c == ';') { + comment = 1; + continue; + } + if (c == '[') { + baselen = get_base_var(var); + if (baselen <= 0) + break; + var[baselen++] = '.'; + var[baselen] = 0; + continue; + } + if (!isalpha(c)) + break; + var[baselen] = c; + if (get_value(fn, var, baselen+1) < 0) + break; + } + die("bad config file line %d", config_linenr); +} + +int git_config_int(const char *name, const char *value) +{ + if (value && *value) { + char *end; + int val = strtol(value, &end, 0); + if (!*end) + return val; + } + die("bad config value for '%s'", name); +} + +int git_config_bool(const char *name, const char *value) +{ + if (!value) + return 1; + if (!*value) + return 0; + if (!strcasecmp(value, "true")) + return 1; + if (!strcasecmp(value, "false")) + return 0; + return git_config_int(name, value) != 0; +} + +int git_default_config(const char *var, const char *value) +{ + /* This needs a better name */ + if (!strcmp(var, "core.filemode")) { + trust_executable_bit = git_config_bool(var, value); + return 0; + } + + /* Add other config variables here.. */ + return 0; +} + +int git_config(config_fn_t fn) +{ + int ret; + FILE *f = fopen(git_path("config"), "r"); + + ret = -1; + if (f) { + config_file = f; + config_linenr = 1; + ret = git_parse_file(fn); + fclose(f); + } + return ret; +} diff --git a/diff-files.c b/diff-files.c index 5e598322ff..96d2c7f19f 100644 --- a/diff-files.c +++ b/diff-files.c @@ -38,6 +38,7 @@ int main(int argc, const char **argv) const char *prefix = setup_git_directory(); int entries, i; + git_config(git_default_config); diff_setup(&diff_options); while (1 < argc && argv[1][0] == '-') { if (!strcmp(argv[1], "-q")) diff --git a/diff-tree.c b/diff-tree.c index b2d74eb1d1..2203fa56d0 100644 --- a/diff-tree.c +++ b/diff-tree.c @@ -408,6 +408,7 @@ int main(int argc, const char **argv) unsigned char sha1[2][20]; const char *prefix = setup_git_directory(); + git_config(git_default_config); nr_sha1 = 0; diff_setup(&diff_options); diff --git a/read-cache.c b/read-cache.c index d2aebdd6bc..c7f3b26862 100644 --- a/read-cache.c +++ b/read-cache.c @@ -5,6 +5,7 @@ */ #include "cache.h" +int trust_executable_bit = 1; struct cache_entry **active_cache = NULL; unsigned int active_nr = 0, active_alloc = 0, active_cache_changed = 0; -- cgit v1.3-5-g9baa From f2d6a256272b71f4509e4501a86a0f6c46ee65ad Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 11 Oct 2005 15:22:47 -0700 Subject: Support custom build options in config.mak With this patch, it is possible to store configuration options like NO_CURL=YesPlease or NO_OPENSSL=YesPlease into a file named config.mak, which will be included in the Makefile. [jc: redone with suggestion from Daniel Barkalow to just use -include] Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Makefile | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Makefile') diff --git a/Makefile b/Makefile index c31af7b3c3..8697d52de7 100644 --- a/Makefile +++ b/Makefile @@ -210,6 +210,8 @@ ifneq (,$(findstring arm,$(uname_M))) ARM_SHA1 = YesPlease endif +-include config.mak + ifndef NO_CURL ifdef CURLDIR # This is still problematic -- gcc does not want -R. -- cgit v1.3-5-g9baa From ec2d15118bd6aa24e9323302e9aaa71dd54bc028 Mon Sep 17 00:00:00 2001 From: Tom Prince Date: Tue, 11 Oct 2005 18:47:33 -0700 Subject: Export template_dir in Makefile. If somebody set template_dir in config.mak. Then git-init-db would be compiled with the correct location but the templates would be installed in the default location. Fix it. Signed-off-by: Tom Prince Signed-off-by: Junio C Hamano --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 8697d52de7..d345c5d116 100644 --- a/Makefile +++ b/Makefile @@ -310,7 +310,7 @@ SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ $(patsubst %.py,%,$(SCRIPT_PYTHON)) \ gitk -export prefix TAR INSTALL DESTDIR SHELL_PATH +export prefix TAR INSTALL DESTDIR SHELL_PATH template_dir ### Build rules all: $(PROGRAMS) $(SCRIPTS) -- cgit v1.3-5-g9baa From e1b10391eabdaaa4c89c53099dd96d5f9d978719 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 11 Oct 2005 18:47:34 -0700 Subject: Use git config file for committer name and email info This starts using the "user.name" and "user.email" config variables if they exist as the default name and email when committing. This means that you don't have to use the GIT_COMMITTER_EMAIL environment variable to override your email - you can just edit the config file instead. The patch looks bigger than it is because it makes the default name and email information non-static and renames it appropriately. And it moves the common git environment variables into a new library file, so that you can link against libgit.a and get the git environment without having to link in zlib and libcrypt. In short, most of it is renaming and moving, the real change core is just a few new lines in "git_default_config()" that copies the user config values to the new base. It also changes "git-var -l" to list the config variables. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- Makefile | 2 +- cache.h | 4 ++++ commit-tree.c | 4 +++- config.c | 10 ++++++++ environment.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ident.c | 30 +++++++++++------------- read-cache.c | 1 - sha1_file.c | 59 ---------------------------------------------- var.c | 11 +++++++++ 9 files changed, 118 insertions(+), 78 deletions(-) create mode 100644 environment.c (limited to 'Makefile') diff --git a/Makefile b/Makefile index d345c5d116..5e7d0555ea 100644 --- a/Makefile +++ b/Makefile @@ -158,7 +158,7 @@ LIB_OBJS = \ object.o pack-check.o patch-delta.o path.o pkt-line.o \ quote.o read-cache.o refs.o run-command.o \ server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \ - tag.o tree.o usage.o config.o $(DIFF_OBJS) + tag.o tree.o usage.o config.o environment.o $(DIFF_OBJS) LIBS = $(LIB_FILE) LIBS += -lz diff --git a/cache.h b/cache.h index 41cc22c1a1..1a7e047d76 100644 --- a/cache.h +++ b/cache.h @@ -382,4 +382,8 @@ extern int git_config(config_fn_t fn); extern int git_config_int(const char *, const char *); extern int git_config_bool(const char *, const char *); +#define MAX_GITNAME (1000) +extern char git_default_email[MAX_GITNAME]; +extern char git_default_name[MAX_GITNAME]; + #endif /* CACHE_H */ diff --git a/commit-tree.c b/commit-tree.c index b1ef0b590a..030fb704e5 100644 --- a/commit-tree.c +++ b/commit-tree.c @@ -89,6 +89,9 @@ int main(int argc, char **argv) char *buffer; unsigned int size; + setup_ident(); + git_config(git_default_config); + if (argc < 2 || get_sha1_hex(argv[1], tree_sha1) < 0) usage(commit_tree_usage); @@ -104,7 +107,6 @@ int main(int argc, char **argv) } if (!parents) fprintf(stderr, "Committing initial tree %s\n", argv[1]); - setup_ident(); init_buffer(&buffer, &size); add_buffer(&buffer, &size, "tree %s\n", sha1_to_hex(tree_sha1)); diff --git a/config.c b/config.c index 510456ceb5..cf803580c9 100644 --- a/config.c +++ b/config.c @@ -207,6 +207,16 @@ int git_default_config(const char *var, const char *value) return 0; } + if (!strcmp(var, "user.name")) { + strncpy(git_default_name, value, sizeof(git_default_name)); + return 0; + } + + if (!strcmp(var, "user.email")) { + strncpy(git_default_email, value, sizeof(git_default_email)); + return 0; + } + /* Add other config variables here.. */ return 0; } diff --git a/environment.c b/environment.c new file mode 100644 index 0000000000..1dc7af56cf --- /dev/null +++ b/environment.c @@ -0,0 +1,75 @@ +/* + * We put all the git config variables in this same object + * file, so that programs can link against the config parser + * without having to link against all the rest of git. + * + * In particular, no need to bring in libz etc unless needed, + * even if you might want to know where the git directory etc + * are. + */ +#include "cache.h" + +char git_default_email[MAX_GITNAME]; +char git_default_name[MAX_GITNAME]; +int trust_executable_bit = 1; + +static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir, + *git_graft_file; +static void setup_git_env(void) +{ + git_dir = getenv(GIT_DIR_ENVIRONMENT); + if (!git_dir) + git_dir = DEFAULT_GIT_DIR_ENVIRONMENT; + git_object_dir = getenv(DB_ENVIRONMENT); + if (!git_object_dir) { + git_object_dir = xmalloc(strlen(git_dir) + 9); + sprintf(git_object_dir, "%s/objects", git_dir); + } + git_refs_dir = xmalloc(strlen(git_dir) + 6); + sprintf(git_refs_dir, "%s/refs", git_dir); + git_index_file = getenv(INDEX_ENVIRONMENT); + if (!git_index_file) { + git_index_file = xmalloc(strlen(git_dir) + 7); + sprintf(git_index_file, "%s/index", git_dir); + } + git_graft_file = getenv(GRAFT_ENVIRONMENT); + if (!git_graft_file) + git_graft_file = strdup(git_path("info/grafts")); +} + +char *get_git_dir(void) +{ + if (!git_dir) + setup_git_env(); + return git_dir; +} + +char *get_object_directory(void) +{ + if (!git_object_dir) + setup_git_env(); + return git_object_dir; +} + +char *get_refs_directory(void) +{ + if (!git_refs_dir) + setup_git_env(); + return git_refs_dir; +} + +char *get_index_file(void) +{ + if (!git_index_file) + setup_git_env(); + return git_index_file; +} + +char *get_graft_file(void) +{ + if (!git_graft_file) + setup_git_env(); + return git_graft_file; +} + + diff --git a/ident.c b/ident.c index 562f5f1816..7a9f5672eb 100644 --- a/ident.c +++ b/ident.c @@ -11,9 +11,7 @@ #include #include -static char real_email[1000]; -static char real_name[1000]; -static char real_date[50]; +static char git_default_date[50]; static void copy_gecos(struct passwd *w, char *name, int sz) { @@ -58,22 +56,22 @@ int setup_ident(void) die("You don't exist. Go away!"); /* Get the name ("gecos") */ - copy_gecos(pw, real_name, sizeof(real_name)); + copy_gecos(pw, git_default_name, sizeof(git_default_name)); /* Make up a fake email address (name + '@' + hostname [+ '.' + domainname]) */ len = strlen(pw->pw_name); - if (len > sizeof(real_email)/2) + if (len > sizeof(git_default_email)/2) die("Your sysadmin must hate you!"); - memcpy(real_email, pw->pw_name, len); - real_email[len++] = '@'; - gethostname(real_email + len, sizeof(real_email) - len); - if (!strchr(real_email+len, '.')) { - len = strlen(real_email); - real_email[len++] = '.'; - getdomainname(real_email+len, sizeof(real_email)-len); + memcpy(git_default_email, pw->pw_name, len); + git_default_email[len++] = '@'; + gethostname(git_default_email + len, sizeof(git_default_email) - len); + if (!strchr(git_default_email+len, '.')) { + len = strlen(git_default_email); + git_default_email[len++] = '.'; + getdomainname(git_default_email+len, sizeof(git_default_email)-len); } /* And set the default date */ - datestamp(real_date, sizeof(real_date)); + datestamp(git_default_date, sizeof(git_default_date)); return 0; } @@ -159,10 +157,10 @@ char *get_ident(const char *name, const char *email, const char *date_str) int i; if (!name) - name = real_name; + name = git_default_name; if (!email) - email = real_email; - strcpy(date, real_date); + email = git_default_email; + strcpy(date, git_default_date); if (date_str) parse_date(date_str, date, sizeof(date)); diff --git a/read-cache.c b/read-cache.c index 4ed369acf8..6932736203 100644 --- a/read-cache.c +++ b/read-cache.c @@ -5,7 +5,6 @@ */ #include "cache.h" -int trust_executable_bit = 1; struct cache_entry **active_cache = NULL; unsigned int active_nr = 0, active_alloc = 0, active_cache_changed = 0; diff --git a/sha1_file.c b/sha1_file.c index 6e3ea232ee..f059004909 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -48,65 +48,6 @@ int get_sha1_hex(const char *hex, unsigned char *sha1) return 0; } -static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir, - *git_graft_file; -static void setup_git_env(void) -{ - git_dir = getenv(GIT_DIR_ENVIRONMENT); - if (!git_dir) - git_dir = DEFAULT_GIT_DIR_ENVIRONMENT; - git_object_dir = getenv(DB_ENVIRONMENT); - if (!git_object_dir) { - git_object_dir = xmalloc(strlen(git_dir) + 9); - sprintf(git_object_dir, "%s/objects", git_dir); - } - git_refs_dir = xmalloc(strlen(git_dir) + 6); - sprintf(git_refs_dir, "%s/refs", git_dir); - git_index_file = getenv(INDEX_ENVIRONMENT); - if (!git_index_file) { - git_index_file = xmalloc(strlen(git_dir) + 7); - sprintf(git_index_file, "%s/index", git_dir); - } - git_graft_file = getenv(GRAFT_ENVIRONMENT); - if (!git_graft_file) - git_graft_file = strdup(git_path("info/grafts")); -} - -char *get_git_dir(void) -{ - if (!git_dir) - setup_git_env(); - return git_dir; -} - -char *get_object_directory(void) -{ - if (!git_object_dir) - setup_git_env(); - return git_object_dir; -} - -char *get_refs_directory(void) -{ - if (!git_refs_dir) - setup_git_env(); - return git_refs_dir; -} - -char *get_index_file(void) -{ - if (!git_index_file) - setup_git_env(); - return git_index_file; -} - -char *get_graft_file(void) -{ - if (!git_graft_file) - setup_git_env(); - return git_graft_file; -} - int safe_create_leading_directories(char *path) { char *pos = path; diff --git a/var.c b/var.c index 3f13126cb8..51cf86a584 100644 --- a/var.c +++ b/var.c @@ -42,6 +42,15 @@ static const char *read_var(const char *var) return val; } +static int show_config(const char *var, const char *value) +{ + if (value) + printf("%s=%s\n", var, value); + else + printf("%s\n", var); + return git_default_config(var, value); +} + int main(int argc, char **argv) { const char *val; @@ -52,9 +61,11 @@ int main(int argc, char **argv) val = NULL; if (strcmp(argv[1], "-l") == 0) { + git_config(show_config); list_vars(); return 0; } + git_config(git_default_config); val = read_var(argv[1]); if (!val) usage(var_usage); -- cgit v1.3-5-g9baa From 9cf6d3357aaaaa89dd86cc156221b7b604e9358c Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Wed, 12 Oct 2005 12:01:31 -0700 Subject: Add git-index-pack utility git-index-pack builds a pack index file for an existing packed archive. With this utility a packed archive which was transferred without the corresponding pack index can be added to objects/pack/ without repacking. Signed-off-by: Sergey Vlasov Signed-off-by: Junio C Hamano --- Documentation/git-index-pack.txt | 44 ++++ Documentation/git.txt | 3 + Makefile | 2 +- index-pack.c | 451 +++++++++++++++++++++++++++++++++++++++ t/t5300-pack-object.sh | 18 ++ 5 files changed, 517 insertions(+), 1 deletion(-) create mode 100644 Documentation/git-index-pack.txt create mode 100644 index-pack.c (limited to 'Makefile') diff --git a/Documentation/git-index-pack.txt b/Documentation/git-index-pack.txt new file mode 100644 index 0000000000..71ce557276 --- /dev/null +++ b/Documentation/git-index-pack.txt @@ -0,0 +1,44 @@ +git-index-pack(1) +================= + +NAME +---- +git-index-pack - Build pack index file for an existing packed archive + + +SYNOPSIS +-------- +'git-index-pack' [-o ] + + +DESCRIPTION +----------- +Reads a packed archive (.pack) from the specified file, and +builds a pack index file (.idx) for it. The packed archive +together with the pack index can then be placed in the +objects/pack/ directory of a git repository. + + +OPTIONS +------- +-o :: + Write the generated pack index into the specified + file. Without this option the name of pack index + file is constructed from the name of packed archive + file by replacing .pack with .idx (and the program + fails if the name of packed archive does not end + with .pack). + + +Author +------ +Written by Sergey Vlasov + +Documentation +------------- +Documentation by Sergey Vlasov + +GIT +--- +Part of the gitlink:git[7] suite + diff --git a/Documentation/git.txt b/Documentation/git.txt index 243c00a178..796c4f61ea 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -68,6 +68,9 @@ gitlink:git-commit-tree[1]:: gitlink:git-hash-object[1]:: Computes the object ID from a file. +gitlink:git-index-pack.html[1]:: + Build pack index file for an existing packed archive. + gitlink:git-init-db[1]:: Creates an empty git object database diff --git a/Makefile b/Makefile index 5e7d0555ea..7c8f6474a3 100644 --- a/Makefile +++ b/Makefile @@ -110,7 +110,7 @@ PROGRAMS = \ 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-hash-object$X git-index-pack$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 \ diff --git a/index-pack.c b/index-pack.c new file mode 100644 index 0000000000..badbeab70e --- /dev/null +++ b/index-pack.c @@ -0,0 +1,451 @@ +#include "cache.h" +#include "delta.h" +#include "pack.h" +#include "csum-file.h" + +static const char index_pack_usage[] = +"git-index-pack [-o index-file] pack-file"; + +struct object_entry +{ + unsigned long offset; + enum object_type type; + enum object_type real_type; + unsigned char sha1[20]; +}; + +struct delta_entry +{ + struct object_entry *obj; + unsigned char base_sha1[20]; +}; + +static const char *pack_name; +static unsigned char *pack_base; +static unsigned long pack_size; +static struct object_entry *objects; +static struct delta_entry *deltas; +static int nr_objects; +static int nr_deltas; + +static void open_pack_file(void) +{ + int fd; + struct stat st; + + fd = open(pack_name, O_RDONLY); + if (fd < 0) + die("cannot open packfile '%s': %s", pack_name, + strerror(errno)); + if (fstat(fd, &st)) { + int err = errno; + close(fd); + die("cannot fstat packfile '%s': %s", pack_name, + strerror(err)); + } + pack_size = st.st_size; + pack_base = mmap(NULL, pack_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (pack_base == MAP_FAILED) { + int err = errno; + close(fd); + die("cannot mmap packfile '%s': %s", pack_name, + strerror(err)); + } + close(fd); +} + +static void parse_pack_header(void) +{ + const struct pack_header *hdr; + unsigned char sha1[20]; + SHA_CTX ctx; + + /* Ensure there are enough bytes for the header and final SHA1 */ + if (pack_size < sizeof(struct pack_header) + 20) + die("packfile '%s' is too small", pack_name); + + /* Header consistency check */ + hdr = (void *)pack_base; + if (hdr->hdr_signature != htonl(PACK_SIGNATURE)) + die("packfile '%s' signature mismatch", pack_name); + if (hdr->hdr_version != htonl(PACK_VERSION)) + die("packfile '%s' version %d different from ours %d", + pack_name, ntohl(hdr->hdr_version), PACK_VERSION); + + nr_objects = ntohl(hdr->hdr_entries); + + /* Check packfile integrity */ + SHA1_Init(&ctx); + SHA1_Update(&ctx, pack_base, pack_size - 20); + SHA1_Final(sha1, &ctx); + if (memcmp(sha1, pack_base + pack_size - 20, 20)) + die("packfile '%s' SHA1 mismatch", pack_name); +} + +static void bad_object(unsigned long offset, const char *format, + ...) NORETURN __attribute__((format (printf, 2, 3))); + +static void bad_object(unsigned long offset, const char *format, ...) +{ + va_list params; + char buf[1024]; + + va_start(params, format); + vsnprintf(buf, sizeof(buf), format, params); + va_end(params); + die("packfile '%s': bad object at offset %lu: %s", + pack_name, offset, buf); +} + +static void *unpack_entry_data(unsigned long offset, + unsigned long *current_pos, unsigned long size) +{ + unsigned long pack_limit = pack_size - 20; + unsigned long pos = *current_pos; + z_stream stream; + void *buf = xmalloc(size); + + memset(&stream, 0, sizeof(stream)); + stream.next_out = buf; + stream.avail_out = size; + stream.next_in = pack_base + pos; + stream.avail_in = pack_limit - pos; + inflateInit(&stream); + + for (;;) { + int ret = inflate(&stream, 0); + if (ret == Z_STREAM_END) + break; + if (ret != Z_OK) + bad_object(offset, "inflate returned %d", ret); + } + inflateEnd(&stream); + if (stream.total_out != size) + bad_object(offset, "size mismatch (expected %lu, got %lu)", + size, stream.total_out); + *current_pos = pack_limit - stream.avail_in; + return buf; +} + +static void *unpack_raw_entry(unsigned long offset, + enum object_type *obj_type, + unsigned long *obj_size, + unsigned char *delta_base, + unsigned long *next_obj_offset) +{ + unsigned long pack_limit = pack_size - 20; + unsigned long pos = offset; + unsigned char c; + unsigned long size; + unsigned shift; + enum object_type type; + void *data; + + c = pack_base[pos++]; + type = (c >> 4) & 7; + size = (c & 15); + shift = 4; + while (c & 0x80) { + if (pos >= pack_limit) + bad_object(offset, "object extends past end of pack"); + c = pack_base[pos++]; + size += (c & 0x7fUL) << shift; + shift += 7; + } + + switch (type) { + case OBJ_DELTA: + if (pos + 20 >= pack_limit) + bad_object(offset, "object extends past end of pack"); + memcpy(delta_base, pack_base + pos, 20); + pos += 20; + /* fallthru */ + case OBJ_COMMIT: + case OBJ_TREE: + case OBJ_BLOB: + case OBJ_TAG: + data = unpack_entry_data(offset, &pos, size); + break; + default: + bad_object(offset, "bad object type %d", type); + } + + *obj_type = type; + *obj_size = size; + *next_obj_offset = pos; + return data; +} + +static int find_delta(const unsigned char *base_sha1) +{ + int first = 0, last = nr_deltas; + + while (first < last) { + int next = (first + last) / 2; + struct delta_entry *delta = &deltas[next]; + int cmp; + + cmp = memcmp(base_sha1, delta->base_sha1, 20); + if (!cmp) + return next; + if (cmp < 0) { + last = next; + continue; + } + first = next+1; + } + return -first-1; +} + +static int find_deltas_based_on_sha1(const unsigned char *base_sha1, + int *first_index, int *last_index) +{ + int first = find_delta(base_sha1); + int last = first; + int end = nr_deltas - 1; + + if (first < 0) + return -1; + while (first > 0 && !memcmp(deltas[first-1].base_sha1, base_sha1, 20)) + --first; + while (last < end && !memcmp(deltas[last+1].base_sha1, base_sha1, 20)) + ++last; + *first_index = first; + *last_index = last; + return 0; +} + +static void sha1_object(const void *data, unsigned long size, + enum object_type type, unsigned char *sha1) +{ + SHA_CTX ctx; + char header[50]; + int header_size; + const char *type_str; + + switch (type) { + case OBJ_COMMIT: type_str = "commit"; break; + case OBJ_TREE: type_str = "tree"; break; + case OBJ_BLOB: type_str = "blob"; break; + case OBJ_TAG: type_str = "tag"; break; + default: + die("bad type %d", type); + } + + header_size = sprintf(header, "%s %lu", type_str, size) + 1; + + SHA1_Init(&ctx); + SHA1_Update(&ctx, header, header_size); + SHA1_Update(&ctx, data, size); + SHA1_Final(sha1, &ctx); +} + +static void resolve_delta(struct delta_entry *delta, void *base_data, + unsigned long base_size, enum object_type type) +{ + struct object_entry *obj = delta->obj; + void *delta_data; + unsigned long delta_size; + void *result; + unsigned long result_size; + enum object_type delta_type; + unsigned char base_sha1[20]; + unsigned long next_obj_offset; + int j, first, last; + + obj->real_type = type; + delta_data = unpack_raw_entry(obj->offset, &delta_type, + &delta_size, base_sha1, + &next_obj_offset); + result = patch_delta(base_data, base_size, delta_data, delta_size, + &result_size); + free(delta_data); + if (!result) + bad_object(obj->offset, "failed to apply delta"); + sha1_object(result, result_size, type, obj->sha1); + if (!find_deltas_based_on_sha1(obj->sha1, &first, &last)) { + for (j = first; j <= last; j++) + resolve_delta(&deltas[j], result, result_size, type); + } + free(result); +} + +static int compare_delta_entry(const void *a, const void *b) +{ + const struct delta_entry *delta_a = a; + const struct delta_entry *delta_b = b; + return memcmp(delta_a->base_sha1, delta_b->base_sha1, 20); +} + +static void parse_pack_objects(void) +{ + int i; + unsigned long offset = sizeof(struct pack_header); + unsigned char base_sha1[20]; + void *data; + unsigned long data_size; + + /* + * First pass: + * - find locations of all objects; + * - calculate SHA1 of all non-delta objects; + * - remember base SHA1 for all deltas. + */ + for (i = 0; i < nr_objects; i++) { + struct object_entry *obj = &objects[i]; + obj->offset = offset; + data = unpack_raw_entry(offset, &obj->type, &data_size, + base_sha1, &offset); + obj->real_type = obj->type; + if (obj->type == OBJ_DELTA) { + struct delta_entry *delta = &deltas[nr_deltas++]; + delta->obj = obj; + memcpy(delta->base_sha1, base_sha1, 20); + } else + sha1_object(data, data_size, obj->type, obj->sha1); + free(data); + } + if (offset != pack_size - 20) + die("packfile '%s' has junk at the end", pack_name); + + /* Sort deltas by base SHA1 for fast searching */ + qsort(deltas, nr_deltas, sizeof(struct delta_entry), + compare_delta_entry); + + /* + * Second pass: + * - for all non-delta objects, look if it is used as a base for + * deltas; + * - if used as a base, uncompress the object and apply all deltas, + * recursively checking if the resulting object is used as a base + * for some more deltas. + */ + for (i = 0; i < nr_objects; i++) { + struct object_entry *obj = &objects[i]; + int j, first, last; + + if (obj->type == OBJ_DELTA) + continue; + if (find_deltas_based_on_sha1(obj->sha1, &first, &last)) + continue; + data = unpack_raw_entry(obj->offset, &obj->type, &data_size, + base_sha1, &offset); + for (j = first; j <= last; j++) + resolve_delta(&deltas[j], data, data_size, obj->type); + free(data); + } + + /* Check for unresolved deltas */ + for (i = 0; i < nr_deltas; i++) { + if (deltas[i].obj->real_type == OBJ_DELTA) + die("packfile '%s' has unresolved deltas", pack_name); + } +} + +static int sha1_compare(const void *_a, const void *_b) +{ + struct object_entry *a = *(struct object_entry **)_a; + struct object_entry *b = *(struct object_entry **)_b; + return memcmp(a->sha1, b->sha1, 20); +} + +static void write_index_file(const char *index_name) +{ + struct sha1file *f; + struct object_entry **sorted_by_sha = + xcalloc(nr_objects, sizeof(struct object_entry *)); + struct object_entry **list = sorted_by_sha; + struct object_entry **last = sorted_by_sha + nr_objects; + unsigned int array[256]; + int i; + + for (i = 0; i < nr_objects; ++i) + sorted_by_sha[i] = &objects[i]; + qsort(sorted_by_sha, nr_objects, sizeof(sorted_by_sha[0]), + sha1_compare); + + unlink(index_name); + f = sha1create("%s", index_name); + + /* + * Write the first-level table (the list is sorted, + * but we use a 256-entry lookup to be able to avoid + * having to do eight extra binary search iterations). + */ + for (i = 0; i < 256; i++) { + struct object_entry **next = list; + while (next < last) { + struct object_entry *obj = *next; + if (obj->sha1[0] != i) + break; + next++; + } + array[i] = htonl(next - sorted_by_sha); + list = next; + } + sha1write(f, array, 256 * sizeof(int)); + + /* + * Write the actual SHA1 entries.. + */ + list = sorted_by_sha; + for (i = 0; i < nr_objects; i++) { + struct object_entry *obj = *list++; + unsigned int offset = htonl(obj->offset); + sha1write(f, &offset, 4); + sha1write(f, obj->sha1, 20); + } + sha1write(f, pack_base + pack_size - 20, 20); + sha1close(f, NULL, 1); + free(sorted_by_sha); +} + +int main(int argc, char **argv) +{ + int i; + char *index_name = NULL; + char *index_name_buf = NULL; + + for (i = 1; i < argc; i++) { + const char *arg = argv[i]; + + if (*arg == '-') { + if (!strcmp(arg, "-o")) { + if (index_name || (i+1) >= argc) + usage(index_pack_usage); + index_name = argv[++i]; + } else + usage(index_pack_usage); + continue; + } + + if (pack_name) + usage(index_pack_usage); + pack_name = arg; + } + + if (!pack_name) + usage(index_pack_usage); + if (!index_name) { + int len = strlen(pack_name); + if (len < 5 || strcmp(pack_name + len - 5, ".pack")) + die("packfile name '%s' does not end with '.pack'", + pack_name); + index_name_buf = xmalloc(len - 1); + memcpy(index_name_buf, pack_name, len - 5); + strcpy(index_name_buf + len - 5, ".idx"); + index_name = index_name_buf; + } + + open_pack_file(); + parse_pack_header(); + objects = xcalloc(nr_objects, sizeof(struct object_entry)); + deltas = xcalloc(nr_objects, sizeof(struct delta_entry)); + parse_pack_objects(); + free(deltas); + write_index_file(index_name); + free(objects); + free(index_name_buf); + + return 0; +} diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh index bb62336f26..96db98b65c 100755 --- a/t/t5300-pack-object.sh +++ b/t/t5300-pack-object.sh @@ -165,4 +165,22 @@ test_expect_success \ :' +test_expect_success \ + 'build pack index for an existing pack' \ + 'cp test-1-${packname_1}.pack test-3.pack && + git-index-pack -o tmp.idx test-3.pack && + cmp tmp.idx test-1-${packname_1}.idx && + + git-index-pack test-3.pack && + cmp test-3.idx test-1-${packname_1}.idx && + + cp test-2-${packname_2}.pack test-3.pack && + git-index-pack -o tmp.idx test-2-${packname_2}.pack && + cmp tmp.idx test-2-${packname_2}.idx && + + git-index-pack test-3.pack && + cmp test-3.idx test-2-${packname_2}.idx && + + :' + test_done -- cgit v1.3-5-g9baa From 8af12741ee0e35f43b3180b435cd33642c183e97 Mon Sep 17 00:00:00 2001 From: Martin Langhoff Date: Thu, 13 Oct 2005 10:47:42 -0700 Subject: Add findtags - reworked A short perl script that will walk the tag refs, tag objects, and even commit objects in its quest to figure out whether the given SHA1 (for a commit or tree) was ever tagged. This version is reworked incorporating sanity, feature and style fixes from Junio. Usage: git-findtags.perl [ -t ] Signed-off-by: Martin Langhoff Signed-off-by: Junio C Hamano --- Makefile | 3 +- git-findtags.perl | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) create mode 100755 git-findtags.perl (limited to 'Makefile') diff --git a/Makefile b/Makefile index 7c8f6474a3..e2e87f6beb 100644 --- a/Makefile +++ b/Makefile @@ -93,7 +93,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-findtags.perl SCRIPT_PYTHON = \ git-merge-recursive.py diff --git a/git-findtags.perl b/git-findtags.perl new file mode 100755 index 0000000000..745affe3a6 --- /dev/null +++ b/git-findtags.perl @@ -0,0 +1,94 @@ +#!/usr/bin/perl -w +# +# Copyright (c) 2005 Martin Langhoff +# +# Walk the tags and find if they match a commit +# expects a SHA1 of a commit. Option -t enables +# searching trees too. +# + +use strict; +use File::Basename; +use File::Find; +use Getopt::Std; + +my $git_dir = $ENV{GIT_DIR} || '.git'; +$git_dir =~ s|/$||; # chomp trailing slash + +# options +our $opt_t; +getopts("t") || usage(); + +my @tagfiles = `find $git_dir/refs/tags -follow -type f`; # haystack +my $target = shift @ARGV; # needle +unless ($target) { + usage(); +} + +# drive the processing from the find hook +# slower, safer (?) than the find utility +find( { wanted => \&process, + no_chdir => 1, + follow => 1, + }, "$git_dir/refs/tags"); + + +sub process { + my ($dev,$ino,$mode,$nlink,$uid,$gid); + + # process only regular files + unless ((($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) && -f _) { + return 1; # ignored anyway + } + + my $tagfile = $_; + chomp $tagfile; + my $tagname = substr($tagfile, length($git_dir.'/refs/tags/')); + + my $tagid = quickread($tagfile); + chomp $tagid; + + # is it just a soft tag? + if ($tagid eq $target) { + print "$tagname\n"; + return 1; # done with this tag + } + + # grab the first 2 lines (the whole tag could be large) + my $tagobj = `git-cat-file tag $tagid | head -n2 `; + if ($tagobj =~ m/^type commit$/m) { # only deal with commits + + if ($tagobj =~ m/^object $target$/m) { # match on the commit + print "$tagname\n"; + + } elsif ( $opt_t && # follow the commit + $tagobj =~ m/^object (\S+)$/m) { # and try to match trees + my $commitid = $1; + my $commitobj = `git-cat-file commit $commitid | head -n1`; + chomp $commitobj; + $commitobj =~ m/^tree (\S+)$/; + my $treeid = $1; + if ($target eq $treeid) { + print "$tagname\n"; + } + } + } +} + +sub quickread { + my $file = shift; + local $/; # undef: slurp mode + open FILE, "<$file" + or die "Cannot open $file : $!"; + my $content = ; + close FILE; + return $content; +} + +sub usage { + print STDERR < +END + exit(1); +} -- cgit v1.3-5-g9baa From 4546738b58a0134eef154231b07d60fc174d56e3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 13 Oct 2005 11:03:18 -0700 Subject: Unlocalized isspace and friends Do our own ctype.h, just to get the sane semantics: we want locale-independence, _and_ we want the right signed behaviour. Plus we only use a very small subset of ctype.h anyway (isspace, isalpha, isdigit and isalnum). Signed-off-by: Junio C Hamano --- Makefile | 3 ++- apply.c | 1 - cache.h | 26 ++++++++++++++++++++++++++ commit-tree.c | 1 - commit.c | 1 - config.c | 1 - convert-objects.c | 1 - ctype.c | 23 +++++++++++++++++++++++ date.c | 1 - diff-tree.c | 1 - ident.c | 1 - mailsplit.c | 1 - pack-objects.c | 1 - patch-id.c | 1 - refs.c | 1 - update-ref.c | 1 - 16 files changed, 51 insertions(+), 14 deletions(-) create mode 100644 ctype.c (limited to 'Makefile') diff --git a/Makefile b/Makefile index e2e87f6beb..9fe65ba2be 100644 --- a/Makefile +++ b/Makefile @@ -159,7 +159,8 @@ LIB_OBJS = \ object.o pack-check.o patch-delta.o path.o pkt-line.o \ quote.o read-cache.o refs.o run-command.o \ server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \ - tag.o tree.o usage.o config.o environment.o $(DIFF_OBJS) + tag.o tree.o usage.o config.o environment.o ctype.o \ + $(DIFF_OBJS) LIBS = $(LIB_FILE) LIBS += -lz diff --git a/apply.c b/apply.c index 155fbe84da..f4d00f2835 100644 --- a/apply.c +++ b/apply.c @@ -6,7 +6,6 @@ * This applies patches on top of some (arbitrary) version of the SCM. * */ -#include #include #include "cache.h" diff --git a/cache.h b/cache.h index 328658235b..f1d15ab3c9 100644 --- a/cache.h +++ b/cache.h @@ -387,4 +387,30 @@ extern int git_config_bool(const char *, const char *); extern char git_default_email[MAX_GITNAME]; extern char git_default_name[MAX_GITNAME]; +/* Sane ctype - no locale, and works with signed chars */ +#undef isspace +#undef isdigit +#undef isalpha +#undef isalnum +#undef tolower +#undef toupper +extern unsigned char sane_ctype[256]; +#define GIT_SPACE 0x01 +#define GIT_DIGIT 0x02 +#define GIT_ALPHA 0x04 +#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0) +#define isspace(x) sane_istest(x,GIT_SPACE) +#define isdigit(x) sane_istest(x,GIT_DIGIT) +#define isalpha(x) sane_istest(x,GIT_ALPHA) +#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT) +#define tolower(x) sane_case((unsigned char)(x), 0x20) +#define toupper(x) sane_case((unsigned char)(x), 0) + +static inline int sane_case(int x, int high) +{ + if (sane_istest(x, GIT_ALPHA)) + x = (x & ~0x20) | high; + return x; +} + #endif /* CACHE_H */ diff --git a/commit-tree.c b/commit-tree.c index 030fb704e5..ea0fdd44e2 100644 --- a/commit-tree.c +++ b/commit-tree.c @@ -7,7 +7,6 @@ #include #include -#include #define BLOCKING (1ul << 14) diff --git a/commit.c b/commit.c index f735f981bb..8f403180e5 100644 --- a/commit.c +++ b/commit.c @@ -1,4 +1,3 @@ -#include #include "tag.h" #include "commit.h" #include "cache.h" diff --git a/config.c b/config.c index 9b7c6f2942..519fecfee4 100644 --- a/config.c +++ b/config.c @@ -1,4 +1,3 @@ -#include #include "cache.h" diff --git a/convert-objects.c b/convert-objects.c index 9ad0c77678..a892013f0f 100644 --- a/convert-objects.c +++ b/convert-objects.c @@ -1,6 +1,5 @@ #define _XOPEN_SOURCE /* glibc2 needs this */ #include -#include #include "cache.h" struct entry { diff --git a/ctype.c b/ctype.c new file mode 100644 index 0000000000..56bdffa636 --- /dev/null +++ b/ctype.c @@ -0,0 +1,23 @@ +/* + * Sane locale-independent, ASCII ctype. + * + * No surprises, and works with signed and unsigned chars. + */ +#include "cache.h" + +#define SS GIT_SPACE +#define AA GIT_ALPHA +#define DD GIT_DIGIT + +unsigned char sane_ctype[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, SS, SS, 0, 0, SS, 0, 0, /* 0-15 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16-15 */ + SS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 32-15 */ + DD, DD, DD, DD, DD, DD, DD, DD, DD, DD, 0, 0, 0, 0, 0, 0, /* 48-15 */ + 0, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, /* 64-15 */ + AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, 0, 0, 0, 0, 0, /* 80-15 */ + 0, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, /* 96-15 */ + AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, AA, 0, 0, 0, 0, 0, /* 112-15 */ + /* Nothing in the 128.. range */ +}; + diff --git a/date.c b/date.c index b21cadc4d6..63f5a09197 100644 --- a/date.c +++ b/date.c @@ -4,7 +4,6 @@ * Copyright (C) Linus Torvalds, 2005 */ -#include #include #include "cache.h" diff --git a/diff-tree.c b/diff-tree.c index 2203fa56d0..851722037d 100644 --- a/diff-tree.c +++ b/diff-tree.c @@ -1,4 +1,3 @@ -#include #include "cache.h" #include "diff.h" #include "commit.h" diff --git a/ident.c b/ident.c index 7a9f5672eb..1bfbc6ff35 100644 --- a/ident.c +++ b/ident.c @@ -9,7 +9,6 @@ #include #include -#include static char git_default_date[50]; diff --git a/mailsplit.c b/mailsplit.c index 0f8100dcca..189f4ed724 100644 --- a/mailsplit.c +++ b/mailsplit.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include "cache.h" diff --git a/pack-objects.c b/pack-objects.c index 8a1ee746e0..b3e6152033 100644 --- a/pack-objects.c +++ b/pack-objects.c @@ -1,4 +1,3 @@ -#include #include "cache.h" #include "object.h" #include "delta.h" diff --git a/patch-id.c b/patch-id.c index 960e7cedf9..edbc4aa3e8 100644 --- a/patch-id.c +++ b/patch-id.c @@ -1,4 +1,3 @@ -#include #include "cache.h" static void flush_current_id(int patchlen, unsigned char *id, SHA_CTX *c) diff --git a/refs.c b/refs.c index 5a8cbd4ef3..42240d2769 100644 --- a/refs.c +++ b/refs.c @@ -2,7 +2,6 @@ #include "cache.h" #include -#include /* We allow "recursive" symbolic refs. Only within reason, though */ #define MAXDEPTH 5 diff --git a/update-ref.c b/update-ref.c index 4a1704c1a5..65dc3d6385 100644 --- a/update-ref.c +++ b/update-ref.c @@ -1,6 +1,5 @@ #include "cache.h" #include "refs.h" -#include static const char git_update_ref_usage[] = "git-update-ref []"; -- cgit v1.3-5-g9baa From 03feddd6e8e779086ac2d131ded325f8e5601653 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 13 Oct 2005 18:57:39 -0700 Subject: git-check-ref-format: reject funny ref names. Update check_ref_format() function to reject ref names that: * has a path component that begins with a ".", or * has a double dots "..", or * has ASCII control character, "~", "^", ":" or SP, anywhere, or * ends with a "/". Use it in 'git-checkout -b', 'git-branch', and 'git-tag' to make sure that newly created refs are well-formed. Signed-off-by: Junio C Hamano --- Makefile | 2 +- check-ref-format.c | 17 +++++++++++++++ git-branch.sh | 63 ++++++++++++++++++++++++++++++------------------------ git-checkout.sh | 2 ++ git-tag.sh | 2 ++ refs.c | 55 +++++++++++++++++++++++++++++++++++++++-------- 6 files changed, 103 insertions(+), 38 deletions(-) create mode 100644 check-ref-format.c (limited to 'Makefile') diff --git a/Makefile b/Makefile index 9fe65ba2be..523985566c 100644 --- a/Makefile +++ b/Makefile @@ -121,7 +121,7 @@ PROGRAMS = \ 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 git-symbolic-ref$X \ + git-update-ref$X git-symbolic-ref$X git-check-ref-format$X \ $(SIMPLE_PROGRAMS) # Backward compatibility -- to be removed after 1.0 diff --git a/check-ref-format.c b/check-ref-format.c new file mode 100644 index 0000000000..a0adb3dcb3 --- /dev/null +++ b/check-ref-format.c @@ -0,0 +1,17 @@ +/* + * GIT - The information manager from hell + */ + +#include "cache.h" +#include "refs.h" + +#include + +int main(int ac, char **av) +{ + if (ac != 2) + usage("git-check-ref-format refname"); + if (check_ref_format(av[1])) + exit(1); + return 0; +} diff --git a/git-branch.sh b/git-branch.sh index 074229c206..e2db9063d4 100755 --- a/git-branch.sh +++ b/git-branch.sh @@ -13,38 +13,42 @@ If two arguments, create a new branch based off of . } delete_branch () { - option="$1" branch_name="$2" + option="$1" + shift headref=$(GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD | sed -e 's|^refs/heads/||') - case ",$headref," in - ",$branch_name,") - die "Cannot delete the branch you are on." ;; - ,,) - die "What branch are you on anyway?" ;; - esac - branch=$(cat "$GIT_DIR/refs/heads/$branch_name") && - branch=$(git-rev-parse --verify "$branch^0") || - die "Seriously, what branch are you talking about?" - case "$option" in - -D) - ;; - *) - mbs=$(git-merge-base -a "$branch" HEAD | tr '\012' ' ') - case " $mbs " in - *' '$branch' '*) - # the merge base of branch and HEAD contains branch -- - # which means that the HEAD contains everything in the HEAD. + for branch_name + do + case ",$headref," in + ",$branch_name,") + die "Cannot delete the branch you are on." ;; + ,,) + die "What branch are you on anyway?" ;; + esac + branch=$(cat "$GIT_DIR/refs/heads/$branch_name") && + branch=$(git-rev-parse --verify "$branch^0") || + die "Seriously, what branch are you talking about?" + case "$option" in + -D) ;; *) - echo >&2 "The branch '$branch_name' is not a strict subset of your current HEAD. -If you are sure you want to delete it, run 'git branch -D $branch_name'." - exit 1 + mbs=$(git-merge-base -a "$branch" HEAD | tr '\012' ' ') + case " $mbs " in + *' '$branch' '*) + # the merge base of branch and HEAD contains branch -- + # which means that the HEAD contains everything in the HEAD. + ;; + *) + echo >&2 "The branch '$branch_name' is not a strict subset of your current HEAD. + If you are sure you want to delete it, run 'git branch -D $branch_name'." + exit 1 + ;; + esac ;; esac - ;; - esac - rm -f "$GIT_DIR/refs/heads/$branch_name" - echo "Deleted branch $branch_name." + rm -f "$GIT_DIR/refs/heads/$branch_name" + echo "Deleted branch $branch_name." + done exit 0 } @@ -52,7 +56,7 @@ while case "$#,$1" in 0,*) break ;; *,-*) ;; *) break ;; esac do case "$1" in -d | -D) - delete_branch "$1" "$2" + delete_branch "$@" exit ;; --) @@ -93,6 +97,9 @@ branchname="$1" rev=$(git-rev-parse --verify "$head") || exit -[ -e "$GIT_DIR/refs/heads/$branchname" ] && die "$branchname already exists" +[ -e "$GIT_DIR/refs/heads/$branchname" ] && + die "$branchname already exists." +git-check-ref-format "heads/$branchname" || + die "we do not like '$branchname' as a branch name." echo $rev > "$GIT_DIR/refs/heads/$branchname" diff --git a/git-checkout.sh b/git-checkout.sh index c3825904b6..2c053a33c3 100755 --- a/git-checkout.sh +++ b/git-checkout.sh @@ -17,6 +17,8 @@ while [ "$#" != "0" ]; do die "git checkout: -b needs a branch name" [ -e "$GIT_DIR/refs/heads/$newbranch" ] && die "git checkout: branch $newbranch already exists" + git-check-ref-format "heads/$newbranch" || + die "we do not like '$newbranch' as a branch name." ;; "-f") force=1 diff --git a/git-tag.sh b/git-tag.sh index 25c1a0e88e..faa766799d 100755 --- a/git-tag.sh +++ b/git-tag.sh @@ -53,6 +53,8 @@ if [ -e "$GIT_DIR/refs/tags/$name" -a -z "$force" ]; then die "tag '$name' already exists" fi shift +git-check-ref-format "tags/$name" || + die "we do not like '$name' as a tag name." object=$(git-rev-parse --verify --default HEAD "$@") || exit 1 type=$(git-cat-file -t $object) || exit 1 diff --git a/refs.c b/refs.c index 42240d2769..97506a4ebd 100644 --- a/refs.c +++ b/refs.c @@ -334,17 +334,54 @@ int write_ref_sha1(const char *ref, int fd, const unsigned char *sha1) return retval; } +/* + * Make sure "ref" is something reasonable to have under ".git/refs/"; + * We do not like it if: + * + * - any path component of it begins with ".", or + * - it has double dots "..", or + * - it has ASCII control character, "~", "^", ":" or SP, anywhere, or + * - it ends with a "/". + */ + +static inline int bad_ref_char(int ch) +{ + return (((unsigned) ch) <= ' ' || + ch == '~' || ch == '^' || ch == ':'); +} + int check_ref_format(const char *ref) { - char *middle; - if (ref[0] == '.' || ref[0] == '/') - return -1; - middle = strchr(ref, '/'); - if (!middle || !middle[1]) - return -1; - if (strchr(middle + 1, '/')) - return -1; - return 0; + int ch, level; + const char *cp = ref; + + level = 0; + while (1) { + while ((ch = *cp++) == '/') + ; /* tolerate duplicated slashes */ + if (!ch) + return -1; /* should not end with slashes */ + + /* we are at the beginning of the path component */ + if (ch == '.' || bad_ref_char(ch)) + return -1; + + /* scan the rest of the path component */ + while ((ch = *cp++) != 0) { + if (bad_ref_char(ch)) + return -1; + if (ch == '/') + break; + if (ch == '.' && *cp == '.') + return -1; + } + level++; + if (!ch) { + if (level < 2) + return -1; /* at least of form "heads/blah" */ + return 0; + } + } } int write_ref_sha1_unlocked(const char *ref, const unsigned char *sha1) -- cgit v1.3-5-g9baa From f005dba7c15af5de74e05f8667da4e5d27cf6d1b Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 16 Oct 2005 19:37:25 +0200 Subject: Makefile entry for git-svnimport contained a small typo. Signed-Off-By: Matthias Urlichs --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 30fda9ec7e..13b949b099 100644 --- a/Makefile +++ b/Makefile @@ -92,7 +92,7 @@ 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-svnimport-perl + git-svnimport.perl SCRIPT_PYTHON = \ git-merge-recursive.py -- cgit v1.3-5-g9baa From 4eba0f3763e2f4bbf614c99ae3a5b299e8d61aff Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 20 Oct 2005 17:13:24 +0200 Subject: Make git-cherry-pick in target "all" Since git-cherry-pick is simply a copy of git-revert, it can be created before installing (so that it can be used without installing, too). Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- .gitignore | 1 + Makefile | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'Makefile') diff --git a/.gitignore b/.gitignore index 975e773fec..52cb9e2c08 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ git-check-ref-format git-checkout git-checkout-index git-cherry +git-cherry-pick git-clone git-clone-pack git-commit diff --git a/Makefile b/Makefile index 5ee72bc924..903c57cdaf 100644 --- a/Makefile +++ b/Makefile @@ -310,7 +310,7 @@ DEFINES += -DSHA1_HEADER=$(call shellquote,$(SHA1_HEADER)) SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ $(patsubst %.perl,%,$(SCRIPT_PERL)) \ $(patsubst %.py,%,$(SCRIPT_PYTHON)) \ - gitk + gitk git-cherry-pick export prefix TAR INSTALL DESTDIR SHELL_PATH template_dir ### Build rules @@ -351,6 +351,9 @@ $(patsubst %.py,%,$(SCRIPT_PYTHON)) : % : %.py $@.py >$@ chmod +x $@ +git-cherry-pick: git-revert + cp $< $@ + %.o: %.c $(CC) -o $*.o -c $(ALL_CFLAGS) $< %.o: %.S @@ -410,7 +413,6 @@ check: install: $(PROGRAMS) $(SCRIPTS) $(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 $(call shellquote,$(DESTDIR)$(GIT_PYTHON_DIR)) -- cgit v1.3-5-g9baa From ac1b3d1248f36b26c2eab55022b9a54bde36b1ee Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 20 Oct 2005 21:05:05 -0700 Subject: Split up tree diff functions into tree-diff.c library This makes the tree diff functionality independent of the "git-diff-tree" program, by splitting the core functionality up into a library file. This will be needed for when we teach git-rev-list to only follow a specified set of pathnames, rather than the global revision history. Most of it is a fairly straightforward code move, but it also involves some calling convention cleanup, and moving some of the static variables from diff-tree.c into the options structure. The actual tree change callback routines also become paramterized by the diff_options structure, allowing the library functionality to do something else than just show the diff on stdout. Right now the only user of this functionality remains git-diff-tree itself. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- Makefile | 2 +- diff-tree.c | 282 +++--------------------------------------------------------- diff.c | 3 + diff.h | 29 +++++++ tree-diff.c | 270 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 317 insertions(+), 269 deletions(-) create mode 100644 tree-diff.c (limited to 'Makefile') diff --git a/Makefile b/Makefile index 903c57cdaf..7eacf61b3f 100644 --- a/Makefile +++ b/Makefile @@ -151,7 +151,7 @@ LIB_H = \ DIFF_OBJS = \ diff.o diffcore-break.o diffcore-order.o diffcore-pathspec.o \ - diffcore-pickaxe.o diffcore-rename.o + diffcore-pickaxe.o diffcore-rename.o tree-diff.o LIB_OBJS = \ blob.o commit.o connect.o count-delta.o csum-file.o \ diff --git a/diff-tree.c b/diff-tree.c index 851722037d..382011a2a6 100644 --- a/diff-tree.c +++ b/diff-tree.c @@ -5,256 +5,13 @@ static int show_root_diff = 0; static int verbose_header = 0; static int ignore_merges = 1; -static int recursive = 0; -static int show_tree_entry_in_recursive = 0; static int read_stdin = 0; -static struct diff_options diff_options; - static const char *header = NULL; static const char *header_prefix = ""; static enum cmit_fmt commit_format = CMIT_FMT_RAW; -// What paths are we interested in? -static int nr_paths = 0; -static const char **paths = NULL; -static int *pathlens = NULL; - -static int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const char *base); - -static void update_tree_entry(void **bufp, unsigned long *sizep) -{ - void *buf = *bufp; - unsigned long size = *sizep; - int len = strlen(buf) + 1 + 20; - - if (size < len) - die("corrupt tree file"); - *bufp = buf + len; - *sizep = size - len; -} - -static const unsigned char *extract(void *tree, unsigned long size, const char **pathp, unsigned int *modep) -{ - int len = strlen(tree)+1; - const unsigned char *sha1 = tree + len; - const char *path = strchr(tree, ' '); - unsigned int mode; - - if (!path || size < len + 20 || sscanf(tree, "%o", &mode) != 1) - die("corrupt tree file"); - *pathp = path+1; - *modep = DIFF_FILE_CANON_MODE(mode); - return sha1; -} - -static char *malloc_base(const char *base, const char *path, int pathlen) -{ - int baselen = strlen(base); - char *newbase = xmalloc(baselen + pathlen + 2); - memcpy(newbase, base, baselen); - memcpy(newbase + baselen, path, pathlen); - memcpy(newbase + baselen + pathlen, "/", 2); - return newbase; -} - -static void show_file(const char *prefix, void *tree, unsigned long size, const char *base); -static void show_tree(const char *prefix, void *tree, unsigned long size, const char *base); - -/* A file entry went away or appeared */ -static void show_file(const char *prefix, void *tree, unsigned long size, const char *base) -{ - unsigned mode; - const char *path; - const unsigned char *sha1 = extract(tree, size, &path, &mode); - - if (recursive && S_ISDIR(mode)) { - char type[20]; - unsigned long size; - char *newbase = malloc_base(base, path, strlen(path)); - void *tree; - - tree = read_sha1_file(sha1, type, &size); - if (!tree || strcmp(type, "tree")) - die("corrupt tree sha %s", sha1_to_hex(sha1)); - - show_tree(prefix, tree, size, newbase); - - free(tree); - free(newbase); - return; - } - - diff_addremove(&diff_options, prefix[0], mode, sha1, base, path); -} - -static int compare_tree_entry(void *tree1, unsigned long size1, void *tree2, unsigned long size2, const char *base) -{ - unsigned mode1, mode2; - const char *path1, *path2; - const unsigned char *sha1, *sha2; - int cmp, pathlen1, pathlen2; - - sha1 = extract(tree1, size1, &path1, &mode1); - sha2 = extract(tree2, size2, &path2, &mode2); - - pathlen1 = strlen(path1); - pathlen2 = strlen(path2); - cmp = base_name_compare(path1, pathlen1, mode1, path2, pathlen2, mode2); - if (cmp < 0) { - show_file("-", tree1, size1, base); - return -1; - } - if (cmp > 0) { - show_file("+", tree2, size2, base); - return 1; - } - if (!diff_options.find_copies_harder && - !memcmp(sha1, sha2, 20) && mode1 == mode2) - return 0; - - /* - * If the filemode has changed to/from a directory from/to a regular - * file, we need to consider it a remove and an add. - */ - if (S_ISDIR(mode1) != S_ISDIR(mode2)) { - show_file("-", tree1, size1, base); - show_file("+", tree2, size2, base); - return 0; - } - - if (recursive && S_ISDIR(mode1)) { - int retval; - char *newbase = malloc_base(base, path1, pathlen1); - if (show_tree_entry_in_recursive) - diff_change(&diff_options, mode1, mode2, - sha1, sha2, base, path1); - retval = diff_tree_sha1(sha1, sha2, newbase); - free(newbase); - return retval; - } - - diff_change(&diff_options, mode1, mode2, sha1, sha2, base, path1); - return 0; -} - -static int interesting(void *tree, unsigned long size, const char *base) -{ - const char *path; - unsigned mode; - int i; - int baselen, pathlen; - - if (!nr_paths) - return 1; - - (void)extract(tree, size, &path, &mode); - - pathlen = strlen(path); - baselen = strlen(base); - - for (i=0; i < nr_paths; i++) { - const char *match = paths[i]; - int matchlen = pathlens[i]; - - if (baselen >= matchlen) { - /* If it doesn't match, move along... */ - if (strncmp(base, match, matchlen)) - continue; - - /* The base is a subdirectory of a path which was specified. */ - return 1; - } - - /* Does the base match? */ - if (strncmp(base, match, baselen)) - continue; - - match += baselen; - matchlen -= baselen; - - if (pathlen > matchlen) - continue; - - if (matchlen > pathlen) { - if (match[pathlen] != '/') - continue; - if (!S_ISDIR(mode)) - continue; - } - - if (strncmp(path, match, pathlen)) - continue; - - return 1; - } - return 0; /* No matches */ -} - -/* A whole sub-tree went away or appeared */ -static void show_tree(const char *prefix, void *tree, unsigned long size, const char *base) -{ - while (size) { - if (interesting(tree, size, base)) - show_file(prefix, tree, size, base); - update_tree_entry(&tree, &size); - } -} - -static int diff_tree(void *tree1, unsigned long size1, void *tree2, unsigned long size2, const char *base) -{ - while (size1 | size2) { - if (nr_paths && size1 && !interesting(tree1, size1, base)) { - update_tree_entry(&tree1, &size1); - continue; - } - if (nr_paths && size2 && !interesting(tree2, size2, base)) { - update_tree_entry(&tree2, &size2); - continue; - } - if (!size1) { - show_file("+", tree2, size2, base); - update_tree_entry(&tree2, &size2); - continue; - } - if (!size2) { - show_file("-", tree1, size1, base); - update_tree_entry(&tree1, &size1); - continue; - } - switch (compare_tree_entry(tree1, size1, tree2, size2, base)) { - case -1: - update_tree_entry(&tree1, &size1); - continue; - case 0: - update_tree_entry(&tree1, &size1); - /* Fallthrough */ - case 1: - update_tree_entry(&tree2, &size2); - continue; - } - die("git-diff-tree: internal error"); - } - return 0; -} - -static int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const char *base) -{ - void *tree1, *tree2; - unsigned long size1, size2; - int retval; - - tree1 = read_object_with_reference(old, "tree", &size1, NULL); - if (!tree1) - die("unable to read source tree (%s)", sha1_to_hex(old)); - tree2 = read_object_with_reference(new, "tree", &size2, NULL); - if (!tree2) - die("unable to read destination tree (%s)", sha1_to_hex(new)); - retval = diff_tree(tree1, size1, tree2, size2, base); - free(tree1); - free(tree2); - return retval; -} +static struct diff_options diff_options; static void call_diff_setup_done(void) { @@ -285,7 +42,7 @@ static int diff_tree_sha1_top(const unsigned char *old, int ret; call_diff_setup_done(); - ret = diff_tree_sha1(old, new, base); + ret = diff_tree_sha1(old, new, base, &diff_options); call_diff_flush(); return ret; } @@ -294,13 +51,17 @@ static int diff_root_tree(const unsigned char *new, const char *base) { int retval; void *tree; - unsigned long size; + struct tree_desc empty, real; call_diff_setup_done(); - tree = read_object_with_reference(new, "tree", &size, NULL); + tree = read_object_with_reference(new, "tree", &real.size, NULL); if (!tree) die("unable to read root tree (%s)", sha1_to_hex(new)); - retval = diff_tree("", 0, tree, size, base); + real.buf = tree; + + empty.buf = ""; + empty.size = 0; + retval = diff_tree(&empty, &real, base, &diff_options); free(tree); call_diff_flush(); return retval; @@ -387,14 +148,6 @@ static int diff_tree_stdin(char *line) return diff_tree_commit(commit, line); } -static int count_paths(const char **paths) -{ - int i = 0; - while (*paths++) - i++; - return i; -} - static const char diff_tree_usage[] = "git-diff-tree [--stdin] [-m] [-s] [-v] [--pretty] [-t] " "[] " @@ -445,11 +198,12 @@ int main(int argc, const char **argv) break; } if (!strcmp(arg, "-r")) { - recursive = 1; + diff_options.recursive = 1; continue; } if (!strcmp(arg, "-t")) { - recursive = show_tree_entry_in_recursive = 1; + diff_options.recursive = 1; + diff_options.tree_in_recursive = 1; continue; } if (!strcmp(arg, "-m")) { @@ -478,17 +232,9 @@ int main(int argc, const char **argv) usage(diff_tree_usage); } if (diff_options.output_format == DIFF_FORMAT_PATCH) - recursive = 1; + diff_options.recursive = 1; - paths = get_pathspec(prefix, argv); - if (paths) { - int i; - - nr_paths = count_paths(paths); - pathlens = xmalloc(nr_paths * sizeof(int)); - for (i=0; iline_termination = '\n'; options->break_opt = -1; options->rename_limit = -1; + + options->change = diff_change; + options->add_remove = diff_addremove; } int diff_setup_done(struct diff_options *options) diff --git a/diff.h b/diff.h index 2f4a7b463b..51155479a4 100644 --- a/diff.h +++ b/diff.h @@ -8,11 +8,31 @@ (S_ISREG(mode) ? (S_IFREG | ce_permissions(mode)) : \ S_ISLNK(mode) ? S_IFLNK : S_IFDIR) +struct tree_desc { + void *buf; + unsigned long size; +}; + +struct diff_options; + +typedef void (*change_fn_t)(struct diff_options *options, + unsigned old_mode, unsigned new_mode, + const unsigned char *old_sha1, + const unsigned char *new_sha1, + const char *base, const char *path); + +typedef void (*add_remove_fn_t)(struct diff_options *options, + int addremove, unsigned mode, + const unsigned char *sha1, + const char *base, const char *path); + struct diff_options { const char **paths; const char *filter; const char *orderfile; const char *pickaxe; + unsigned recursive:1, + tree_in_recursive:1; int break_opt; int detect_rename; int find_copies_harder; @@ -23,8 +43,17 @@ struct diff_options { int reverse_diff; int rename_limit; int setup; + + change_fn_t change; + add_remove_fn_t add_remove; }; +extern void diff_tree_setup_paths(const char **paths); +extern int diff_tree(struct tree_desc *t1, struct tree_desc *t2, + const char *base, struct diff_options *opt); +extern int diff_tree_sha1(const unsigned char *old, const unsigned char *new, + const char *base, struct diff_options *opt); + extern void diff_addremove(struct diff_options *, int addremove, unsigned mode, diff --git a/tree-diff.c b/tree-diff.c new file mode 100644 index 0000000000..0ef06a9e36 --- /dev/null +++ b/tree-diff.c @@ -0,0 +1,270 @@ +/* + * Helper functions for tree diff generation + */ +#include "cache.h" +#include "diff.h" + +// What paths are we interested in? +static int nr_paths = 0; +static const char **paths = NULL; +static int *pathlens = NULL; + +static void update_tree_entry(struct tree_desc *desc) +{ + void *buf = desc->buf; + unsigned long size = desc->size; + int len = strlen(buf) + 1 + 20; + + if (size < len) + die("corrupt tree file"); + desc->buf = buf + len; + desc->size = size - len; +} + +static const unsigned char *extract(struct tree_desc *desc, const char **pathp, unsigned int *modep) +{ + void *tree = desc->buf; + unsigned long size = desc->size; + int len = strlen(tree)+1; + const unsigned char *sha1 = tree + len; + const char *path = strchr(tree, ' '); + unsigned int mode; + + if (!path || size < len + 20 || sscanf(tree, "%o", &mode) != 1) + die("corrupt tree file"); + *pathp = path+1; + *modep = DIFF_FILE_CANON_MODE(mode); + return sha1; +} + +static char *malloc_base(const char *base, const char *path, int pathlen) +{ + int baselen = strlen(base); + char *newbase = xmalloc(baselen + pathlen + 2); + memcpy(newbase, base, baselen); + memcpy(newbase + baselen, path, pathlen); + memcpy(newbase + baselen + pathlen, "/", 2); + return newbase; +} + +static int show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base); + +static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt) +{ + unsigned mode1, mode2; + const char *path1, *path2; + const unsigned char *sha1, *sha2; + int cmp, pathlen1, pathlen2; + + sha1 = extract(t1, &path1, &mode1); + sha2 = extract(t2, &path2, &mode2); + + pathlen1 = strlen(path1); + pathlen2 = strlen(path2); + cmp = base_name_compare(path1, pathlen1, mode1, path2, pathlen2, mode2); + if (cmp < 0) { + show_entry(opt, "-", t1, base); + return -1; + } + if (cmp > 0) { + show_entry(opt, "+", t2, base); + return 1; + } + if (!opt->find_copies_harder && + !memcmp(sha1, sha2, 20) && mode1 == mode2) + return 0; + + /* + * If the filemode has changed to/from a directory from/to a regular + * file, we need to consider it a remove and an add. + */ + if (S_ISDIR(mode1) != S_ISDIR(mode2)) { + show_entry(opt, "-", t1, base); + show_entry(opt, "+", t2, base); + return 0; + } + + if (opt->recursive && S_ISDIR(mode1)) { + int retval; + char *newbase = malloc_base(base, path1, pathlen1); + if (opt->tree_in_recursive) + opt->change(opt, mode1, mode2, + sha1, sha2, base, path1); + retval = diff_tree_sha1(sha1, sha2, newbase, opt); + free(newbase); + return retval; + } + + opt->change(opt, mode1, mode2, sha1, sha2, base, path1); + return 0; +} + +static int interesting(struct tree_desc *desc, const char *base) +{ + const char *path; + unsigned mode; + int i; + int baselen, pathlen; + + if (!nr_paths) + return 1; + + (void)extract(desc, &path, &mode); + + pathlen = strlen(path); + baselen = strlen(base); + + for (i=0; i < nr_paths; i++) { + const char *match = paths[i]; + int matchlen = pathlens[i]; + + if (baselen >= matchlen) { + /* If it doesn't match, move along... */ + if (strncmp(base, match, matchlen)) + continue; + + /* The base is a subdirectory of a path which was specified. */ + return 1; + } + + /* Does the base match? */ + if (strncmp(base, match, baselen)) + continue; + + match += baselen; + matchlen -= baselen; + + if (pathlen > matchlen) + continue; + + if (matchlen > pathlen) { + if (match[pathlen] != '/') + continue; + if (!S_ISDIR(mode)) + continue; + } + + if (strncmp(path, match, pathlen)) + continue; + + return 1; + } + return 0; /* No matches */ +} + +/* A whole sub-tree went away or appeared */ +static void show_tree(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base) +{ + while (desc->size) { + if (interesting(desc, base)) + show_entry(opt, prefix, desc, base); + update_tree_entry(desc); + } +} + +/* A file entry went away or appeared */ +static int show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base) +{ + unsigned mode; + const char *path; + const unsigned char *sha1 = extract(desc, &path, &mode); + + if (opt->recursive && S_ISDIR(mode)) { + char type[20]; + char *newbase = malloc_base(base, path, strlen(path)); + struct tree_desc inner; + void *tree; + + tree = read_sha1_file(sha1, type, &inner.size); + if (!tree || strcmp(type, "tree")) + die("corrupt tree sha %s", sha1_to_hex(sha1)); + + inner.buf = tree; + show_tree(opt, prefix, &inner, newbase); + + free(tree); + free(newbase); + return 0; + } + + opt->add_remove(opt, prefix[0], mode, sha1, base, path); + return 0; +} + +int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt) +{ + while (t1->size | t2->size) { + if (nr_paths && t1->size && !interesting(t1, base)) { + update_tree_entry(t1); + continue; + } + if (nr_paths && t2->size && !interesting(t2, base)) { + update_tree_entry(t2); + continue; + } + if (!t1->size) { + show_entry(opt, "+", t2, base); + update_tree_entry(t2); + continue; + } + if (!t2->size) { + show_entry(opt, "-", t1, base); + update_tree_entry(t1); + continue; + } + switch (compare_tree_entry(t1, t2, base, opt)) { + case -1: + update_tree_entry(t1); + continue; + case 0: + update_tree_entry(t1); + /* Fallthrough */ + case 1: + update_tree_entry(t2); + continue; + } + die("git-diff-tree: internal error"); + } + return 0; +} + +int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const char *base, struct diff_options *opt) +{ + void *tree1, *tree2; + struct tree_desc t1, t2; + int retval; + + tree1 = read_object_with_reference(old, "tree", &t1.size, NULL); + if (!tree1) + die("unable to read source tree (%s)", sha1_to_hex(old)); + tree2 = read_object_with_reference(new, "tree", &t2.size, NULL); + if (!tree2) + die("unable to read destination tree (%s)", sha1_to_hex(new)); + t1.buf = tree1; + t2.buf = tree2; + retval = diff_tree(&t1, &t2, base, opt); + free(tree1); + free(tree2); + return retval; +} + +static int count_paths(const char **paths) +{ + int i = 0; + while (*paths++) + i++; + return i; +} + +void diff_tree_setup_paths(const char **p) +{ + if (p) { + int i; + + paths = p; + nr_paths = count_paths(paths); + pathlens = xmalloc(nr_paths * sizeof(int)); + for (i=0; i Date: Sun, 23 Oct 2005 18:15:34 +0200 Subject: Add git-mv It supersedes git-rename by adding functionality to move multiple files, directories or symlinks into another directory. It also provides according documentation. The implementation renames multiple files, using the arguments from the command line to produce an array of sources and destinations. In a first pass, all requested renames are checked for errors, and overwriting of existing files is only allowed with '-f'. The actual renaming is done in a second pass. This ensures that any error condition is checked before anything is changed. Signed-off-by: Josef Weidendorfer Signed-off-by: Junio C Hamano --- Documentation/git-mv.txt | 51 +++++++++++++ Makefile | 2 +- git-mv.perl | 185 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 237 insertions(+), 1 deletion(-) create mode 100644 Documentation/git-mv.txt create mode 100755 git-mv.perl (limited to 'Makefile') diff --git a/Documentation/git-mv.txt b/Documentation/git-mv.txt new file mode 100644 index 0000000000..f2d5882f48 --- /dev/null +++ b/Documentation/git-mv.txt @@ -0,0 +1,51 @@ +git-mv(1) +========= + +NAME +---- +git-mv - Script used to move or rename a file, directory or symlink. + + +SYNOPSIS +-------- +'git-mv' [-f] [-n] +'git-mv' [-f] [-k] [-n] ... + +DESCRIPTION +----------- +This script is used to move or rename a file, directory or symlink. +In the first form, it renames , which must exist and be either +a file, symlink or directory, to , which must not exist. +In the second form, the last argument has to be an existing +directory; the given sources will be moved into this directory. + +The index is updated after successful completion, but the change must still be +committed. + +OPTIONS +------- +-f:: + Force renaming or moving even targets exist +-k:: + Skip move or rename actions which would lead to an error + condition. An error happens when a source is neither existing nor + controlled by GIT, or when it would overwrite an existing + file unless '-f' is given. +-n:: + Do nothing; only show what would happen + + +Author +------ +Written by Linus Torvalds +Rewritten by Ryan Anderson +Move functionality added by Josef Weidendorfer + +Documentation +-------------- +Documentation by David Greaves, Junio C Hamano and the git-list . + +GIT +--- +Part of the gitlink:git[7] suite + diff --git a/Makefile b/Makefile index 7eacf61b3f..5bdf3cc8dd 100644 --- a/Makefile +++ b/Makefile @@ -94,7 +94,7 @@ 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-findtags.perl git-svnimport.perl + git-findtags.perl git-svnimport.perl git-mv.perl SCRIPT_PYTHON = \ git-merge-recursive.py diff --git a/git-mv.perl b/git-mv.perl new file mode 100755 index 0000000000..28bced9595 --- /dev/null +++ b/git-mv.perl @@ -0,0 +1,185 @@ +#!/usr/bin/perl +# +# Copyright 2005, Ryan Anderson +# Josef Weidendorfer +# +# This file is licensed under the GPL v2, or a later version +# at the discretion of Linus Torvalds. + + +use warnings; +use strict; +use Getopt::Std; + +sub usage() { + print < +$0 [-f] [-k] [-n] ... + +In the first form, source must exist and be either a file, +symlink or directory, dest must not exist. It renames source to dest. +In the second form, the last argument has to be an existing +directory; the given sources will be moved into this directory. + +Updates the git cache to reflect the change. +Use "git commit" to make the change permanently. + +Options: + -f Force renaming/moving, even if target exists + -k Continue on error by skipping + not-existing or not revision-controlled source + -n Do nothing; show what would happen +EOT + exit(1); +} + +# Sanity checks: +my $GIT_DIR = $ENV{'GIT_DIR'} || ".git"; + +unless ( -d $GIT_DIR && -d $GIT_DIR . "/objects" && + -d $GIT_DIR . "/objects/" && -d $GIT_DIR . "/refs") { + print "Git repository not found."; + usage(); +} + + +our ($opt_n, $opt_f, $opt_h, $opt_k, $opt_v); +getopts("hnfkv") || usage; +usage() if $opt_h; +@ARGV >= 1 or usage; + +my (@srcArgs, @dstArgs, @srcs, @dsts); +my ($src, $dst, $base, $dstDir); + +my $argCount = scalar @ARGV; +if (-d $ARGV[$argCount-1]) { + $dstDir = $ARGV[$argCount-1]; + @srcArgs = @ARGV[0..$argCount-2]; + + foreach $src (@srcArgs) { + $base = $src; + $base =~ s/^.*\///; + $dst = "$dstDir/". $base; + push @dstArgs, $dst; + } +} +else { + if ($argCount != 2) { + print "Error: moving to directory '" + . $ARGV[$argCount-1] + . "' not possible; not exisiting\n"; + usage; + } + @srcArgs = ($ARGV[0]); + @dstArgs = ($ARGV[1]); + $dstDir = ""; +} + +my (@allfiles,@srcfiles,@dstfiles); +my $safesrc; +my %overwritten; + +$/ = "\0"; +open(F,"-|","git-ls-files","-z") + or die "Failed to open pipe from git-ls-files: " . $!; + +@allfiles = map { chomp; $_; } ; +close(F); + + +my ($i, $bad); +while(scalar @srcArgs > 0) { + $src = shift @srcArgs; + $dst = shift @dstArgs; + $bad = ""; + + if ($opt_v) { + print "Checking rename of '$src' to '$dst'\n"; + } + + unless (-f $src || -l $src || -d $src) { + $bad = "bad source '$src'"; + } + + $overwritten{$dst} = 0; + if (($bad eq "") && -e $dst) { + $bad = "destination '$dst' already exists"; + if (-f $dst && $opt_f) { + print "Warning: $bad; will overwrite!\n"; + $bad = ""; + $overwritten{$dst} = 1; + } + } + + if (($bad eq "") && ($src eq $dstDir)) { + $bad = "can not move directory '$src' into itself"; + } + + if ($bad eq "") { + $safesrc = quotemeta($src); + @srcfiles = grep /^$safesrc(\/|$)/, @allfiles; + if (scalar @srcfiles == 0) { + $bad = "'$src' not under version control"; + } + } + + if ($bad ne "") { + if ($opt_k) { + print "Warning: $bad; skipping\n"; + next; + } + print "Error: $bad\n"; + usage(); + } + push @srcs, $src; + push @dsts, $dst; +} + +# Final pass: rename/move +my (@deletedfiles,@addedfiles,@changedfiles); +while(scalar @srcs > 0) { + $src = shift @srcs; + $dst = shift @dsts; + + if ($opt_n || $opt_v) { print "Renaming $src to $dst\n"; } + if (!$opt_n) { + rename($src,$dst) + or die "rename failed: $!"; + } + + $safesrc = quotemeta($src); + @srcfiles = grep /^$safesrc(\/|$)/, @allfiles; + @dstfiles = @srcfiles; + s/^$safesrc(\/|$)/$dst$1/ for @dstfiles; + + push @deletedfiles, @srcfiles; + if (scalar @srcfiles == 1) { + if ($overwritten{$dst} ==1) { + push @changedfiles, $dst; + } else { + push @addedfiles, $dst; + } + } + else { + push @addedfiles, @dstfiles; + } +} + +if ($opt_n) { + print "Changed : ". join(", ", @changedfiles) ."\n"; + print "Adding : ". join(", ", @addedfiles) ."\n"; + print "Deleting : ". join(", ", @deletedfiles) ."\n"; + exit(1); +} + +my $rc; +if (scalar @changedfiles >0) { + $rc = system("git-update-index","--",@changedfiles); + die "git-update-index failed to update changed files with code $?\n" if $rc; +} +if (scalar @addedfiles >0) { + $rc = system("git-update-index","--add","--",@addedfiles); + die "git-update-index failed to add new names with code $?\n" if $rc; +} +$rc = system("git-update-index","--remove","--",@deletedfiles); +die "git-update-index failed to remove old names with code $?\n" if $rc; -- cgit v1.3-5-g9baa From 35eb2d36418a25f9e956b116a622d8d99f4abad9 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 23 Oct 2005 14:30:45 -0700 Subject: Add git-shell. This adds a very git specific restricted shell, that can be added to /etc/shells and set to the pw_shell in the /etc/passwd file, to give users ability to push into repositories over ssh without giving them full interactive shell acount. [jc: I updated Linus' patch to match what the current sq_quote() does.] Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- Makefile | 2 +- quote.c | 41 ++++++++++++++++++++++++++++++++++++++++- quote.h | 6 ++++++ shell.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 shell.c (limited to 'Makefile') diff --git a/Makefile b/Makefile index 5bdf3cc8dd..5b0306d391 100644 --- a/Makefile +++ b/Makefile @@ -116,7 +116,7 @@ PROGRAMS = \ 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-send-pack$X git-show-branch$X git-shell$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 \ diff --git a/quote.c b/quote.c index 009e69494b..e662a7da71 100644 --- a/quote.c +++ b/quote.c @@ -15,6 +15,11 @@ #undef EMIT #define EMIT(x) ( (++len < n) && (*bp++ = (x)) ) +static inline int need_bs_quote(char c) +{ + return (c == '\'' || c == '!'); +} + size_t sq_quote_buf(char *dst, size_t n, const char *src) { char c; @@ -23,7 +28,7 @@ size_t sq_quote_buf(char *dst, size_t n, const char *src) EMIT('\''); while ((c = *src++)) { - if (c == '\'' || c == '!') { + if (need_bs_quote(c)) { EMIT('\''); EMIT('\\'); EMIT(c); @@ -52,6 +57,40 @@ char *sq_quote(const char *src) return buf; } +char *sq_dequote(char *arg) +{ + char *dst = arg; + char *src = arg; + char c; + + if (*src != '\'') + return NULL; + for (;;) { + c = *++src; + if (!c) + return NULL; + if (c != '\'') { + *dst++ = c; + continue; + } + /* We stepped out of sq */ + switch (*++src) { + case '\0': + *dst = 0; + return arg; + case '\\': + c = *++src; + if (need_bs_quote(c) && *++src == '\'') { + *dst++ = c; + continue; + } + /* Fallthrough */ + default: + return NULL; + } + } +} + /* * C-style name quoting. * diff --git a/quote.h b/quote.h index 2fdde3b66b..2486e6e68c 100644 --- a/quote.h +++ b/quote.h @@ -31,6 +31,12 @@ extern char *sq_quote(const char *src); extern size_t sq_quote_buf(char *dst, size_t n, const char *src); +/* This unwraps what sq_quote() produces in place, but returns + * NULL if the input does not look like what sq_quote would have + * produced. + */ +extern char *sq_dequote(char *); + extern int quote_c_style(const char *name, char *outbuf, FILE *outfp, int nodq); extern char *unquote_c_style(const char *quoted, const char **endp); diff --git a/shell.c b/shell.c new file mode 100644 index 0000000000..2c4789e944 --- /dev/null +++ b/shell.c @@ -0,0 +1,59 @@ +#include "cache.h" +#include "quote.h" + +static int do_generic_cmd(const char *me, char *arg) +{ + const char *my_argv[4]; + + arg = sq_dequote(arg); + if (!arg) + die("bad argument"); + + my_argv[0] = me; + my_argv[1] = arg; + my_argv[2] = NULL; + + return execvp(me, (char**) my_argv); +} + +static struct commands { + const char *name; + int (*exec)(const char *me, char *arg); +} cmd_list[] = { + { "git-receive-pack", do_generic_cmd }, + { "git-upload-pack", do_generic_cmd }, + { NULL }, +}; + +int main(int argc, char **argv) +{ + char *prog; + struct commands *cmd; + + /* We want to see "-c cmd args", and nothing else */ + if (argc != 3 || strcmp(argv[1], "-c")) + die("What do you think I am? A shell?"); + + prog = argv[2]; + argv += 2; + argc -= 2; + for (cmd = cmd_list ; cmd->name ; cmd++) { + int len = strlen(cmd->name); + char *arg; + if (strncmp(cmd->name, prog, len)) + continue; + arg = NULL; + switch (prog[len]) { + case '\0': + arg = NULL; + break; + case ' ': + arg = prog + len + 1; + break; + default: + continue; + } + exit(cmd->exec(cmd->name, arg)); + } + die("unrecognized command '%s'", prog); +} -- cgit v1.3-5-g9baa From f3123c4ab3d3698262e59561ac084de45b10365a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 22 Oct 2005 01:28:13 -0700 Subject: pack-objects: Allow use of pre-generated pack. git-pack-objects can reuse pack files stored in $GIT_DIR/pack-cache directory, when a necessary pack is found. This is hopefully useful when upload-pack (called from git-daemon) is expected to receive requests for the same set of objects many times (e.g full cloning request of any project, or updates from the set of heads previous day to the latest for a slow moving project). Currently git-pack-objects does *not* keep pack files it creates for reusing. It might be useful to add --update-cache option to it, which would allow it store pack files it created in the pack-cache directory, and prune rarely used ones from it. Signed-off-by: Junio C Hamano --- Makefile | 2 +- cache.h | 1 + copy.c | 37 ++++++++++++++++++++++++++ pack-objects.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 112 insertions(+), 12 deletions(-) create mode 100644 copy.c (limited to 'Makefile') diff --git a/Makefile b/Makefile index 5b0306d391..701067d435 100644 --- a/Makefile +++ b/Makefile @@ -159,7 +159,7 @@ LIB_OBJS = \ object.o pack-check.o patch-delta.o path.o pkt-line.o \ quote.o read-cache.o refs.o run-command.o \ server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \ - tag.o tree.o usage.o config.o environment.o ctype.o \ + tag.o tree.o usage.o config.o environment.o ctype.o copy.o \ $(DIFF_OBJS) LIBS = $(LIB_FILE) diff --git a/cache.h b/cache.h index d776016822..2e36cc5b8b 100644 --- a/cache.h +++ b/cache.h @@ -413,4 +413,5 @@ static inline int sane_case(int x, int high) return x; } +extern int copy_fd(int ifd, int ofd); #endif /* CACHE_H */ diff --git a/copy.c b/copy.c new file mode 100644 index 0000000000..20092757d3 --- /dev/null +++ b/copy.c @@ -0,0 +1,37 @@ +#include "cache.h" + +int copy_fd(int ifd, int ofd) +{ + while (1) { + int len; + char buffer[8192]; + char *buf = buffer; + len = read(ifd, buffer, sizeof(buffer)); + if (!len) + break; + if (len < 0) { + if (errno == EAGAIN) + continue; + return error("copy-fd: read returned %s", + strerror(errno)); + } + while (1) { + int written = write(ofd, buf, len); + if (written > 0) { + buf += written; + len -= written; + if (!len) + break; + } + if (!written) + return error("copy-fd: write returned 0"); + if (errno == EAGAIN || errno == EINTR) + continue; + return error("copy-fd: write returned %s", + strerror(errno)); + } + } + close(ifd); + return 0; +} + diff --git a/pack-objects.c b/pack-objects.c index b3e6152033..4e941e7392 100644 --- a/pack-objects.c +++ b/pack-objects.c @@ -400,6 +400,71 @@ static void find_deltas(struct object_entry **list, int window, int depth) free(array); } +static void prepare_pack(int window, int depth) +{ + get_object_details(); + + fprintf(stderr, "Packing %d objects\n", nr_objects); + + sorted_by_type = create_sorted_list(type_size_sort); + if (window && depth) + find_deltas(sorted_by_type, window+1, depth); + write_pack_file(); +} + +static int reuse_cached_pack(unsigned char *sha1, int pack_to_stdout) +{ + static const char cache[] = "pack-cache/pack-%s.%s"; + char *cached_pack, *cached_idx; + int ifd, ofd, ifd_ix = -1; + + cached_pack = git_path(cache, sha1_to_hex(sha1), "pack"); + ifd = open(cached_pack, O_RDONLY); + if (ifd < 0) + return 0; + + if (!pack_to_stdout) { + cached_idx = git_path(cache, sha1_to_hex(sha1), "idx"); + ifd_ix = open(cached_idx, O_RDONLY); + if (ifd_ix < 0) { + close(ifd); + return 0; + } + } + + fprintf(stderr, "Reusing %d objects pack %s\n", nr_objects, + sha1_to_hex(sha1)); + + if (pack_to_stdout) { + if (copy_fd(ifd, 1)) + exit(1); + close(ifd); + } + else { + char name[PATH_MAX]; + snprintf(name, sizeof(name), + "%s-%s.%s", base_name, sha1_to_hex(sha1), "pack"); + ofd = open(name, O_CREAT | O_EXCL | O_WRONLY, 0666); + if (ofd < 0) + die("unable to open %s (%s)", name, strerror(errno)); + if (copy_fd(ifd, ofd)) + exit(1); + close(ifd); + + snprintf(name, sizeof(name), + "%s-%s.%s", base_name, sha1_to_hex(sha1), "idx"); + ofd = open(name, O_CREAT | O_EXCL | O_WRONLY, 0666); + if (ofd < 0) + die("unable to open %s (%s)", name, strerror(errno)); + if (copy_fd(ifd_ix, ofd)) + exit(1); + close(ifd_ix); + puts(sha1_to_hex(sha1)); + } + + return 1; +} + int main(int argc, char **argv) { SHA_CTX ctx; @@ -472,9 +537,6 @@ int main(int argc, char **argv) } if (non_empty && !nr_objects) return 0; - get_object_details(); - - fprintf(stderr, "Packing %d objects\n", nr_objects); sorted_by_sha = create_sorted_list(sha1_sort); SHA1_Init(&ctx); @@ -485,14 +547,14 @@ int main(int argc, char **argv) } SHA1_Final(object_list_sha1, &ctx); - sorted_by_type = create_sorted_list(type_size_sort); - if (window && depth) - find_deltas(sorted_by_type, window+1, depth); - - write_pack_file(); - if (!pack_to_stdout) { - write_index_file(); - puts(sha1_to_hex(object_list_sha1)); + if (reuse_cached_pack(object_list_sha1, pack_to_stdout)) + ; + else { + prepare_pack(window, depth); + if (!pack_to_stdout) { + write_index_file(); + puts(sha1_to_hex(object_list_sha1)); + } } return 0; } -- cgit v1.3-5-g9baa From bd321bcc51e95f644ac5335abe673afcbcaade62 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 26 Oct 2005 15:10:20 +0200 Subject: Add git-name-rev git-name-rev tries to find nice symbolic names for commits. It does so by walking the commits from the refs. When the symbolic name is ambiguous, the following heuristic is applied: Try to avoid too many ~'s, and if two ambiguous names have the same count of ~'s, take the one whose last number is smaller. With "--tags", the names are derived only from tags. With "--stdin", the stdin is parsed, and after every sha1 for which a name could be found, the name is appended. (Try "git log | git name-rev --stdin".) Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Documentation/git-name-rev.txt | 66 +++++++++++ Makefile | 2 +- name-rev.c | 246 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 Documentation/git-name-rev.txt create mode 100644 name-rev.c (limited to 'Makefile') diff --git a/Documentation/git-name-rev.txt b/Documentation/git-name-rev.txt new file mode 100644 index 0000000000..e37b0b8f97 --- /dev/null +++ b/Documentation/git-name-rev.txt @@ -0,0 +1,66 @@ +git-name-rev(1) +=============== + +NAME +---- +git-name-rev - Find symbolic names for given revs. + + +SYNOPSIS +-------- +'git-name-rev' [--tags] ( --all | --stdin | ... ) + +DESCRIPTION +----------- +Finds symbolic names suitable for human digestion for revisions given in any +format parsable by git-rev-parse. + + +OPTIONS +------- + +--tags:: + Do not use branch names, but only tags to name the commits + +--all:: + List all commits reachable from all refs + +--stdin:: + Read from stdin, append "()" to all sha1's of name'able + commits, and pass to stdout + +EXAMPLE +------- + +Given a commit, find out where it is relative to the local refs. Say somebody +wrote you about that phantastic commit 33db5f4d9027a10e477ccf054b2c1ab94f74c85a. +Of course, you look into the commit, but that only tells you what happened, but +not the context. + +Enter git-name-rev: + +------------ +% git name-rev 33db5f4d9027a10e477ccf054b2c1ab94f74c85a +------------ + +Now you are wiser, because you know that it happened 940 revisions before v0.99. + +Another nice thing you can do is: + +------------ +% git log | git name-rev --stdin +------------ + + +Author +------ +Written by Johannes Schindelin + +Documentation +-------------- +Documentation by Johannes Schindelin. + +GIT +--- +Part of the gitlink:git[7] suite + diff --git a/Makefile b/Makefile index 701067d435..e76e6c4a3e 100644 --- a/Makefile +++ b/Makefile @@ -122,7 +122,7 @@ PROGRAMS = \ 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 git-symbolic-ref$X git-check-ref-format$X \ - $(SIMPLE_PROGRAMS) + git-name-rev$X $(SIMPLE_PROGRAMS) # Backward compatibility -- to be removed after 1.0 PROGRAMS += git-ssh-pull$X git-ssh-push$X diff --git a/name-rev.c b/name-rev.c new file mode 100644 index 0000000000..21fecdf542 --- /dev/null +++ b/name-rev.c @@ -0,0 +1,246 @@ +#include +#include "cache.h" +#include "commit.h" +#include "tag.h" +#include "refs.h" + +static const char name_rev_usage[] = + "git-name-rev [--tags] ( --all | --stdin | commitish [commitish...] )\n"; + +typedef struct rev_name { + const char *tip_name; + int merge_traversals; + int generation; +} rev_name; + +static long cutoff = LONG_MAX; + +static void name_rev(struct commit *commit, + const char *tip_name, int merge_traversals, int generation, + int deref) +{ + struct rev_name *name = (struct rev_name *)commit->object.util; + struct commit_list *parents; + int parent_number = 0; + + if (!commit->object.parsed) + parse_commit(commit); + + if (commit->date < cutoff) + return; + + if (deref) { + char *new_name = xmalloc(strlen(tip_name)+3); + strcpy(new_name, tip_name); + strcat(new_name, "^0"); + tip_name = new_name; + + if (generation) + die("generation: %d, but deref?", generation); + } + + if (name == NULL) { + name = xmalloc(sizeof(rev_name)); + commit->object.util = name; + goto copy_data; + } else if (name->merge_traversals > merge_traversals || + (name->merge_traversals == merge_traversals && + name->generation > generation)) { +copy_data: + name->tip_name = tip_name; + name->merge_traversals = merge_traversals; + name->generation = generation; + } else + return; + + for (parents = commit->parents; + parents; + parents = parents->next, parent_number++) { + if (parent_number > 0) { + char *new_name = xmalloc(strlen(tip_name)+8); + + if (generation > 0) + sprintf(new_name, "%s~%d^%d", tip_name, + generation, parent_number); + else + sprintf(new_name, "%s^%d", tip_name, parent_number); + + name_rev(parents->item, new_name, + merge_traversals + 1 , 0, 0); + } else { + name_rev(parents->item, tip_name, merge_traversals, + generation + 1, 0); + } + } +} + +static int tags_only = 0; + +static int name_ref(const char *path, const unsigned char *sha1) +{ + struct object *o = parse_object(sha1); + int deref = 0; + + if (tags_only && strncmp(path, "refs/tags/", 10)) + return 0; + + while (o && o->type == tag_type) { + struct tag *t = (struct tag *) o; + if (!t->tagged) + break; /* broken repository */ + o = parse_object(t->tagged->sha1); + deref = 1; + } + if (o && o->type == commit_type) { + struct commit *commit = (struct commit *)o; + const char *p; + + while ((p = strchr(path, '/'))) + path = p+1; + + name_rev(commit, strdup(path), 0, 0, deref); + } + return 0; +} + +/* returns a static buffer */ +static const char* get_rev_name(struct object *o) +{ + static char buffer[1024]; + struct rev_name *n = (struct rev_name *)o->util; + if (!n) + return "undefined"; + + if (!n->generation) + return n->tip_name; + + snprintf(buffer, sizeof(buffer), "%s~%d", n->tip_name, n->generation); + + return buffer; +} + +int main(int argc, char **argv) +{ + struct object_list *revs = NULL; + struct object_list **walker = &revs; + int as_is = 0, all = 0, transform_stdin = 0; + + setup_git_directory(); + + if (argc < 2) + usage(name_rev_usage); + + for (--argc, ++argv; argc; --argc, ++argv) { + unsigned char sha1[20]; + struct object *o; + struct commit *commit; + + if (!as_is && (*argv)[0] == '-') { + if (!strcmp(*argv, "--")) { + as_is = 1; + continue; + } else if (!strcmp(*argv, "--tags")) { + tags_only = 1; + continue; + } else if (!strcmp(*argv, "--all")) { + if (argc > 1) + die("Specify either a list, or --all, not both!"); + all = 1; + cutoff = 0; + continue; + } else if (!strcmp(*argv, "--stdin")) { + if (argc > 1) + die("Specify either a list, or --stdin, not both!"); + transform_stdin = 1; + cutoff = 0; + continue; + } + usage(name_rev_usage); + } + + if (get_sha1(*argv, sha1)) { + fprintf(stderr, "Could not get sha1 for %s. Skipping.\n", + *argv); + continue; + } + + o = deref_tag(parse_object(sha1)); + if (!o || o->type != commit_type) { + fprintf(stderr, "Could not get commit for %s. Skipping.\n", + *argv); + continue; + } + + commit = (struct commit *)o; + + if (cutoff > commit->date) + cutoff = commit->date; + + object_list_append((struct object *)commit, walker); + (*walker)->name = *argv; + walker = &((*walker)->next); + } + + for_each_ref(name_ref); + + if (transform_stdin) { + char buffer[2048]; + char *p, *p_start; + + while (!feof(stdin)) { + int forty = 0; + p = fgets(buffer, sizeof(buffer), stdin); + if (!p) + break; + + for (p_start = p; *p; p++) { +#define ishex(x) (isdigit((x)) || ((x) >= 'a' && (x) <= 'f')) + if (!ishex(*p)) + forty = 0; + else if (++forty == 40 && + !ishex(*(p+1))) { + unsigned char sha1[40]; + const char *name = "undefined"; + char c = *(p+1); + + forty = 0; + + *(p+1) = 0; + if (!get_sha1(p - 39, sha1)) { + struct object *o = + lookup_object(sha1); + if (o) + name = get_rev_name(o); + } + *(p+1) = c; + + if (!strcmp(name, "undefined")) + continue; + + fwrite(p_start, p - p_start, 1, stdout); + fputc('(', stdout); + fputs(name, stdout); + fputc(')', stdout); + p_start = p + 1; + } + } + + /* flush */ + if (p_start != p) + fwrite(p_start, p - p_start, 1, stdout); + } + } else if (all) { + extern struct object **objs; + extern int nr_objs; + int i; + + for (i = 0; i < nr_objs; i++) + printf("%s %s\n", sha1_to_hex(objs[i]->sha1), + get_rev_name(objs[i])); + } else + for ( ; revs; revs = revs->next) + printf("%s %s\n", revs->name, get_rev_name(revs->item)); + + return 0; +} + -- cgit v1.3-5-g9baa From 46774a81f9d6ca4d230d33757afe9dd07bfe398b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 29 Oct 2005 14:35:11 -0700 Subject: GIT 0.99.9 Done in 0.99.9 ============== Ports ~~~~~ * Cygwin port [HPA]. * OpenBSD build [Merlyn and others]. Fixes ~~~~~ * clone request over git native protocol from a repository with too many refs did not work; this has been fixed. * git-daemon got safer for kernel.org use [HPA]. * Extended SHA1 parser was not enforcing uniqueness for abbreviated SHA1; this has been fixed. * http transport does not barf on funny characters in URL. * The ref naming restrictions have been formalized and the coreish refuses to create funny refs; we still need to audit importers. See git-check-ref-format(1). New Features and Commands ~~~~~~~~~~~~~~~~~~~~~~~~~ * .git/config file as a per-repository configuration mechanism, and some commands understand it [Linus]. See git(7). * The core.filemode configuration item can be used to make us a bit more FAT friendly. See git(7). * The extended SHA1 notation acquired Peel-the-onion operator ^{type} and ^{}. See git-rev-parse(1). * SVN importer [Matthias]. See git-svnimport(1). * .git/objects/[0-9a-f]{2} directories are created on demand, and removed when becomes empty after prune-packed [Linus]. * Filenames output from various commands without -z option are quoted when they embed funny characters (TAB and LF) using C-style quoting within double-quotes, to match the proposed GNU diff/patch notation [me, but many people contributed in the discussion]. * git-mv is expected to be a better replacement for git-rename. While the latter has two parameter restriction, it acts more like the regular 'mv' that can move multiple things to one destinatino directory [Josef Weidendorfer]. * git-checkout can take filenames to revert the changes to them. See git-checkout(1) * The new program git-am is a replacement for git-applymbox that has saner command line options and a bit easier to use when a patch does not apply cleanly. * git-ls-remote can show unwrapped onions using ^{} notation, to help Cogito to track tags. * git-merge-recursive backend can merge unrelated projects. * git-clone over native transport leaves the result packed. * git-http-fetch issues multiple requests in parallel when underlying cURL library supports it [Nick and Daniel]. * git-fetch-pack and git-upload-pack try harder to figure out better common commits [Johannes]. * git-read-tree -u removes a directory when it makes it empty. * git-diff-* records abbreviated SHA1 names of original and resulting blob; this sometimes helps to apply otherwise an unapplicable patch by falling back to 3-way merge. * git-format-patch now takes series of from..to rev ranges and with '-m --stdout', writes them out to the standard output. This can be piped to 'git-am' to implement cheaper cherry-picking. * git-tag takes '-u' to specify the tag signer identity [Linus]. * git-rev-list can take optional pathspecs to skip commits that do not touch them (--dense) [Linus]. * Comes with new and improved gitk [Paulus and Linus]. Signed-off-by: Junio C Hamano --- Makefile | 2 +- debian/changelog | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index e76e6c4a3e..7bccc76f15 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,7 @@ # DEFINES += -DUSE_STDEV -GIT_VERSION = 0.99.8.GIT +GIT_VERSION = 0.99.9 CFLAGS = -g -O2 -Wall ALL_CFLAGS = $(CFLAGS) $(PLATFORM_DEFINES) $(DEFINES) diff --git a/debian/changelog b/debian/changelog index bebc1919ba..5fd31b7ef4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +git-core (0.99.9-0) unstable; urgency=low + + * GIT 0.99.9 + + -- Junio C Hamano Sat, 29 Oct 2005 14:34:30 -0700 + git-core (0.99.8-0) unstable; urgency=low * GIT 0.99.8 -- cgit v1.3-5-g9baa From c2d07d24e48fd7109ac4c717bcdc6b82609ece1a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 30 Oct 2005 17:27:38 -0800 Subject: GIT 0.99.9 master branch. Signed-off-by: Junio C Hamano --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 7bccc76f15..1163dda0f6 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,7 @@ # DEFINES += -DUSE_STDEV -GIT_VERSION = 0.99.9 +GIT_VERSION = 0.99.9.GIT CFLAGS = -g -O2 -Wall ALL_CFLAGS = $(CFLAGS) $(PLATFORM_DEFINES) $(DEFINES) -- cgit v1.3-5-g9baa