parent
							
								
									60d64db461
								
							
						
					
					
						commit
						27dedf0c3b
					
				|  | @ -81,7 +81,7 @@ The "diff" formatting options can be customized via the | |||
| environment variable 'GIT_DIFF_OPTS'.  For example, if you | ||||
| prefer context diff: | ||||
|  | ||||
|       GIT_DIFF_OPTS=-c git-diff-index -p $(cat .git/HEAD) | ||||
|       GIT_DIFF_OPTS=-c git-diff-index -p HEAD | ||||
|  | ||||
|  | ||||
| 2. When the environment variable 'GIT_EXTERNAL_DIFF' is set, the | ||||
|  |  | |||
|  | @ -13,6 +13,11 @@ | |||
| --name-status:: | ||||
| 	Show only names and status of changed files. | ||||
|  | ||||
| --full-index:: | ||||
| 	Instead of the first handful characters, show full | ||||
| 	object name of pre- and post-image blob on the "index" | ||||
| 	line when generating a patch format output.	 | ||||
|  | ||||
| -B:: | ||||
| 	Break complete rewrite changes into pairs of delete and create. | ||||
|  | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ git-apply - Apply patch on a git index file and a work tree | |||
|  | ||||
| SYNOPSIS | ||||
| -------- | ||||
| 'git-apply' [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [-z] [<patch>...] | ||||
| 'git-apply' [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] [<patch>...] | ||||
|  | ||||
| DESCRIPTION | ||||
| ----------- | ||||
|  | @ -79,6 +79,17 @@ OPTIONS | |||
| 	the result with this option, which would apply the | ||||
| 	deletion part but not addition part. | ||||
|  | ||||
| --allow-binary-replacement:: | ||||
| 	When applying a patch, which is a git-enhanced patch | ||||
| 	that was prepared to record the pre- and post-image object | ||||
| 	name in full, and the path being patched exactly matches | ||||
| 	the object the patch applies to (i.e. "index" line's | ||||
| 	pre-image object name is what is in the working tree), | ||||
| 	and the post-image object is available in the object | ||||
| 	database, use the post-image object as the patch | ||||
| 	result.  This allows binary files to be patched in a | ||||
| 	very limited way. | ||||
|  | ||||
| Author | ||||
| ------ | ||||
| Written by Linus Torvalds <torvalds@osdl.org> | ||||
|  |  | |||
|  | @ -26,8 +26,9 @@ to get there. | |||
|  | ||||
| Normally a commit would identify a new "HEAD" state, and while git | ||||
| doesn't care where you save the note about that state, in practice we | ||||
| tend to just write the result to the file `.git/HEAD`, so that we can | ||||
| always see what the last committed state was. | ||||
| tend to just write the result to the file that is pointed at by | ||||
| `.git/HEAD`, so that we can always see what the last committed | ||||
| state was. | ||||
|  | ||||
| OPTIONS | ||||
| ------- | ||||
|  |  | |||
|  | @ -35,7 +35,7 @@ OPTIONS | |||
| 	do not have the 'git-daemon-export-ok' file. | ||||
|  | ||||
| --inetd:: | ||||
| 	Have the server run as an inetd service. | ||||
| 	Have the server run as an inetd service. Implies --syslog. | ||||
|  | ||||
| --port:: | ||||
| 	Listen on an alternative port. | ||||
|  |  | |||
|  | @ -57,14 +57,14 @@ some files in the index and are ready to commit. You want to see eactly | |||
| *what* you are going to commit is without having to write a new tree | ||||
| object and compare it that way, and to do that, you just do | ||||
|  | ||||
| 	git-diff-index --cached $(cat .git/HEAD) | ||||
| 	git-diff-index --cached HEAD | ||||
|  | ||||
| Example: let's say I had renamed `commit.c` to `git-commit.c`, and I had | ||||
| done an "git-update-index" to make that effective in the index file. | ||||
| "git-diff-files" wouldn't show anything at all, since the index file | ||||
| matches my working directory. But doing a "git-diff-index" does: | ||||
|  | ||||
|   torvalds@ppc970:~/git> git-diff-index --cached $(cat .git/HEAD) | ||||
|   torvalds@ppc970:~/git> git-diff-index --cached HEAD | ||||
|   -100644 blob    4161aecc6700a2eb579e842af0b7f22b98443f74        commit.c | ||||
|   +100644 blob    4161aecc6700a2eb579e842af0b7f22b98443f74        git-commit.c | ||||
|  | ||||
|  | @ -98,7 +98,7 @@ show that. So let's say that you have edited `kernel/sched.c`, but | |||
| have not actually done a "git-update-index" on it yet - there is no | ||||
| "object" associated with the new state, and you get: | ||||
|  | ||||
|   torvalds@ppc970:~/v2.6/linux> git-diff-index $(cat .git/HEAD ) | ||||
|   torvalds@ppc970:~/v2.6/linux> git-diff-index HEAD | ||||
|   *100644->100664 blob    7476bb......->000000......      kernel/sched.c | ||||
|  | ||||
| ie it shows that the tree has changed, and that `kernel/sched.c` has is | ||||
|  |  | |||
|  | @ -68,7 +68,7 @@ that aren't readable from any of the specified head nodes. | |||
|  | ||||
| So for example | ||||
|  | ||||
| 	git-fsck-objects --unreachable $(cat .git/HEAD .git/refs/heads/*) | ||||
| 	git-fsck-objects --unreachable HEAD $(cat .git/refs/heads/*) | ||||
|  | ||||
| will do quite a _lot_ of verification on the tree. There are a few | ||||
| extra validity tests to be added (make sure that tree objects are | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ This manual page describes only the most frequently used options. | |||
|  | ||||
| OPTIONS | ||||
| ------- | ||||
| --pretty=<format>: | ||||
| --pretty=<format>:: | ||||
| 	Controls the way the commit log is formatted. | ||||
|  | ||||
| --max-count=<n>:: | ||||
|  |  | |||
|  | @ -237,7 +237,7 @@ This is done to prevent you from losing your work-in-progress | |||
| changes.  To illustrate, suppose you start from what has been | ||||
| commited last to your repository: | ||||
|  | ||||
|     $ JC=`cat .git/HEAD` | ||||
|     $ JC=`git-rev-parse --verify "HEAD^0"` | ||||
|     $ git-checkout-index -f -u -a $JC | ||||
|  | ||||
| You do random edits, without running git-update-index.  And then | ||||
|  |  | |||
|  | @ -24,8 +24,8 @@ Traditionally, `.git/HEAD` is a symlink pointing at | |||
| we did `ln -sf refs/heads/newbranch .git/HEAD`, and when we want | ||||
| to find out which branch we are on, we did `readlink .git/HEAD`. | ||||
| This was fine, and internally that is what still happens by | ||||
| default, but on platforms that does not have working symlinks, | ||||
| or that does not have the `readlink(1)` command, this was a bit | ||||
| default, but on platforms that do not have working symlinks, | ||||
| or that do not have the `readlink(1)` command, this was a bit | ||||
| cumbersome.  On some platforms, `ln -sf` does not even work as | ||||
| advertised (horrors). | ||||
|  | ||||
|  |  | |||
|  | @ -8,13 +8,33 @@ git - the stupid content tracker | |||
|  | ||||
| SYNOPSIS | ||||
| -------- | ||||
| 'git-<command>' <args> | ||||
| 'git' [--version] [--exec-path[=GIT_EXEC_PATH]] [--help] COMMAND [ARGS] | ||||
|  | ||||
| DESCRIPTION | ||||
| ----------- | ||||
| 'git' is both a program and a directory content tracker system. | ||||
| The program 'git' is just a wrapper to reach the core git programs | ||||
| (or a potty if you like, as it's not exactly porcelain but still | ||||
| brings your stuff to the plumbing). | ||||
|  | ||||
| This is reference information for the core git commands. | ||||
| OPTIONS | ||||
| ------- | ||||
| --version:: | ||||
| 	prints the git suite version that the 'git' program came from. | ||||
|  | ||||
| --help:: | ||||
| 	prints the synopsis and a list of available commands. | ||||
| 	If a git command is named this option will bring up the | ||||
| 	man-page for that command. | ||||
|  | ||||
| --exec-path:: | ||||
| 	path to wherever your core git programs are installed. | ||||
| 	This can also be controlled by setting the GIT_EXEC_PATH | ||||
| 	environment variable. If no path is given 'git' will print | ||||
| 	the current setting and then exit. | ||||
|  | ||||
| CORE GIT COMMANDS | ||||
| ----------------- | ||||
| Before reading this cover to cover, you may want to take a look | ||||
| at the link:tutorial.html[tutorial] document. | ||||
|  | ||||
|  | @ -67,7 +87,7 @@ gitlink:git-commit-tree[1]:: | |||
| gitlink:git-hash-object[1]:: | ||||
| 	Computes the object ID from a file. | ||||
|  | ||||
| gitlink:git-index-pack.html[1]:: | ||||
| gitlink:git-index-pack[1]:: | ||||
| 	Build pack index file for an existing packed archive. | ||||
|  | ||||
| gitlink:git-init-db[1]:: | ||||
|  | @ -533,9 +553,12 @@ Discussion[[Discussion]] | |||
| ------------------------ | ||||
| include::../README[] | ||||
|  | ||||
| Author | ||||
| ------ | ||||
| Written by Linus Torvalds <torvalds@osdl.org> and the git-list <git@vger.kernel.org>. | ||||
| Authors | ||||
| ------- | ||||
| 	git's founding father is Linus Torvalds <torvalds@osdl.org>. | ||||
| 	The current git nurse is Junio C. Hamano <junkio@cox.net>. | ||||
| 	The git potty was written by Andres Ericsson <ae@op5.se>. | ||||
| 	General upbringing is handled by the git-list <git@vger.kernel.org>. | ||||
|  | ||||
| Documentation | ||||
| -------------- | ||||
|  |  | |||
							
								
								
									
										40
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										40
									
								
								Makefile
								
								
								
								
							|  | @ -50,7 +50,7 @@ | |||
| # Define USE_STDEV below if you want git to care about the underlying device | ||||
| # change being considered an inode change from the update-cache perspective. | ||||
|  | ||||
| GIT_VERSION = 0.99.9i | ||||
| GIT_VERSION = 0.99.9j | ||||
|  | ||||
| # CFLAGS and LDFLAGS are for the users to override from the command line. | ||||
|  | ||||
|  | @ -88,7 +88,7 @@ SCRIPT_SH = \ | |||
| 	git-prune.sh git-pull.sh git-push.sh git-rebase.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-tag.sh git-verify-tag.sh git-whatchanged.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-merge-ours.sh git-grep.sh \ | ||||
|  | @ -105,7 +105,7 @@ 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-stripspace$X git-daemon$X | ||||
|  | ||||
| # ... and all the rest | ||||
| PROGRAMS = \ | ||||
|  | @ -125,7 +125,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 \ | ||||
| 	git-name-rev$X git-pack-redundant$X $(SIMPLE_PROGRAMS) | ||||
| 	git-name-rev$X git-pack-redundant$X git-var$X $(SIMPLE_PROGRAMS) | ||||
|  | ||||
| # Backward compatibility -- to be removed after 1.0 | ||||
| PROGRAMS += git-ssh-pull$X git-ssh-push$X | ||||
|  | @ -334,19 +334,15 @@ SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ | |||
| export prefix TAR INSTALL DESTDIR SHELL_PATH template_dir | ||||
| ### Build rules | ||||
|  | ||||
| all: $(PROGRAMS) $(SCRIPTS) | ||||
| all: $(PROGRAMS) $(SCRIPTS) git | ||||
|  | ||||
| all: | ||||
| 	$(MAKE) -C templates | ||||
|  | ||||
| git: git.sh Makefile | ||||
| 	rm -f $@+ $@ | ||||
| 	sed -e '1s|#!.*/sh|#!$(call shq,$(SHELL_PATH))|' \ | ||||
| 	    -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ | ||||
| 	    -e 's/@@X@@/$(X)/g' \ | ||||
| 	    $(GIT_LIST_TWEAK) <$@.sh >$@+ | ||||
| 	chmod +x $@+ | ||||
| 	mv $@+ $@ | ||||
| # Only use $(CFLAGS). We don't need anything else. | ||||
| git: git.c Makefile | ||||
| 	$(CC) -DGIT_EXEC_PATH='"$(bindir)"' -DGIT_VERSION='"$(GIT_VERSION)"' \ | ||||
| 		$(CFLAGS) $@.c -o $@ | ||||
|  | ||||
| $(filter-out git,$(patsubst %.sh,%,$(SCRIPT_SH))) : % : %.sh | ||||
| 	rm -f $@ | ||||
|  | @ -431,9 +427,9 @@ check: | |||
|  | ||||
| ### Installation rules | ||||
|  | ||||
| install: $(PROGRAMS) $(SCRIPTS) | ||||
| install: $(PROGRAMS) $(SCRIPTS) git | ||||
| 	$(INSTALL) -d -m755 $(call shellquote,$(DESTDIR)$(bindir)) | ||||
| 	$(INSTALL) $(PROGRAMS) $(SCRIPTS) $(call shellquote,$(DESTDIR)$(bindir)) | ||||
| 	$(INSTALL) git $(PROGRAMS) $(SCRIPTS) $(call shellquote,$(DESTDIR)$(bindir)) | ||||
| 	$(MAKE) -C templates install | ||||
| 	$(INSTALL) -d -m755 $(call shellquote,$(DESTDIR)$(GIT_PYTHON_DIR)) | ||||
| 	$(INSTALL) $(PYMODULES) $(call shellquote,$(DESTDIR)$(GIT_PYTHON_DIR)) | ||||
|  | @ -446,20 +442,20 @@ install-doc: | |||
|  | ||||
| ### Maintainer's dist rules | ||||
|  | ||||
| git-core.spec: git-core.spec.in Makefile | ||||
| git.spec: git.spec.in Makefile | ||||
| 	sed -e 's/@@VERSION@@/$(GIT_VERSION)/g' < $< > $@ | ||||
|  | ||||
| GIT_TARNAME=git-core-$(GIT_VERSION) | ||||
| dist: git-core.spec git-tar-tree | ||||
| GIT_TARNAME=git-$(GIT_VERSION) | ||||
| dist: git.spec git-tar-tree | ||||
| 	./git-tar-tree HEAD $(GIT_TARNAME) > $(GIT_TARNAME).tar | ||||
| 	@mkdir -p $(GIT_TARNAME) | ||||
| 	@cp git-core.spec $(GIT_TARNAME) | ||||
| 	$(TAR) rf $(GIT_TARNAME).tar $(GIT_TARNAME)/git-core.spec | ||||
| 	@cp git.spec $(GIT_TARNAME) | ||||
| 	$(TAR) rf $(GIT_TARNAME).tar $(GIT_TARNAME)/git.spec | ||||
| 	@rm -rf $(GIT_TARNAME) | ||||
| 	gzip -f -9 $(GIT_TARNAME).tar | ||||
|  | ||||
| rpm: dist | ||||
| 	$(RPMBUILD) -ta git-core-$(GIT_VERSION).tar.gz | ||||
| 	$(RPMBUILD) -ta $(GIT_TARNAME).tar.gz | ||||
|  | ||||
| deb: dist | ||||
| 	rm -rf $(GIT_TARNAME) | ||||
|  | @ -472,7 +468,7 @@ deb: dist | |||
| clean: | ||||
| 	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 -f *.spec *.pyc *.pyo | ||||
| 	rm -rf $(GIT_TARNAME) | ||||
| 	rm -f $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz | ||||
| 	rm -f git-core_$(GIT_VERSION)-*.dsc | ||||
|  |  | |||
							
								
								
									
										6
									
								
								README
								
								
								
								
							
							
						
						
									
										6
									
								
								README
								
								
								
								
							|  | @ -396,8 +396,8 @@ git-commit-tree will return the name of the object that represents | |||
| that commit, and you should save it away for later use. Normally, | ||||
| you'd commit a new `HEAD` state, and while git doesn't care where you | ||||
| save the note about that state, in practice we tend to just write the | ||||
| result to the file `.git/HEAD`, so that we can always see what the | ||||
| last committed state was. | ||||
| result to the file pointed at by `.git/HEAD`, so that we can always see | ||||
| what the last committed state was. | ||||
|  | ||||
| Here is an ASCII art by Jon Loeliger that illustrates how | ||||
| various pieces fit together. | ||||
|  | @ -464,7 +464,7 @@ tend to be small and fairly self-explanatory. In particular, if you | |||
| follow the convention of having the top commit name in `.git/HEAD`, | ||||
| you can do | ||||
|  | ||||
| 		git-cat-file commit $(cat .git/HEAD) | ||||
| 		git-cat-file commit HEAD | ||||
|  | ||||
| to see what the top commit was. | ||||
|  | ||||
|  |  | |||
							
								
								
									
										92
									
								
								apply.c
								
								
								
								
							
							
						
						
									
										92
									
								
								apply.c
								
								
								
								
							|  | @ -16,6 +16,7 @@ | |||
| //  --numstat does numeric diffstat, and doesn't actually apply | ||||
| //  --index-info shows the old and new index info for paths if available. | ||||
| // | ||||
| static int allow_binary_replacement = 0; | ||||
| static int check_index = 0; | ||||
| static int write_index = 0; | ||||
| static int diffstat = 0; | ||||
|  | @ -27,7 +28,7 @@ static int no_add = 0; | |||
| static int show_index_info = 0; | ||||
| static int line_termination = '\n'; | ||||
| static const char apply_usage[] = | ||||
| "git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [-z] <patch>..."; | ||||
| "git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [-z] <patch>..."; | ||||
|  | ||||
| /* | ||||
|  * For "diff-stat" like behaviour, we keep track of the biggest change | ||||
|  | @ -891,7 +892,7 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch) | |||
|  | ||||
| 	patchsize = parse_single_patch(buffer + offset + hdrsize, size - offset - hdrsize, patch); | ||||
|  | ||||
| 	if (!patchsize && !metadata_changes(patch)) { | ||||
| 	if (!patchsize) { | ||||
| 		static const char binhdr[] = "Binary files "; | ||||
|  | ||||
| 		if (sizeof(binhdr) - 1 < size - offset - hdrsize && | ||||
|  | @ -899,9 +900,14 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch) | |||
| 			    sizeof(binhdr)-1)) | ||||
| 			patch->is_binary = 1; | ||||
|  | ||||
| 		if (patch->is_binary && !apply && !check) | ||||
| 			; | ||||
| 		else | ||||
| 		/* Empty patch cannot be applied if: | ||||
| 		 * - it is a binary patch and we do not do binary_replace, or | ||||
| 		 * - text patch without metadata change | ||||
| 		 */ | ||||
| 		if ((apply || check) && | ||||
| 		    (patch->is_binary | ||||
| 		     ? !allow_binary_replacement | ||||
| 		     : !metadata_changes(patch))) | ||||
| 			die("patch with only garbage at line %d", linenr); | ||||
| 	} | ||||
|  | ||||
|  | @ -1155,10 +1161,77 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag) | |||
| static int apply_fragments(struct buffer_desc *desc, struct patch *patch) | ||||
| { | ||||
| 	struct fragment *frag = patch->fragments; | ||||
| 	const char *name = patch->old_name ? patch->old_name : patch->new_name; | ||||
|  | ||||
| 	if (patch->is_binary) { | ||||
| 		unsigned char sha1[20]; | ||||
|  | ||||
| 		if (!allow_binary_replacement) | ||||
| 			return error("cannot apply binary patch to '%s' " | ||||
| 				     "without --allow-binary-replacement", | ||||
| 				     name); | ||||
|  | ||||
| 		/* For safety, we require patch index line to contain | ||||
| 		 * full 40-byte textual SHA1 for old and new, at least for now. | ||||
| 		 */ | ||||
| 		if (strlen(patch->old_sha1_prefix) != 40 || | ||||
| 		    strlen(patch->new_sha1_prefix) != 40 || | ||||
| 		    get_sha1_hex(patch->old_sha1_prefix, sha1) || | ||||
| 		    get_sha1_hex(patch->new_sha1_prefix, sha1)) | ||||
| 			return error("cannot apply binary patch to '%s' " | ||||
| 				     "without full index line", name); | ||||
|  | ||||
| 		if (patch->old_name) { | ||||
| 			unsigned char hdr[50]; | ||||
| 			int hdrlen; | ||||
|  | ||||
| 			/* See if the old one matches what the patch | ||||
| 			 * applies to. | ||||
| 			 */ | ||||
| 			write_sha1_file_prepare(desc->buffer, desc->size, | ||||
| 						"blob", sha1, hdr, &hdrlen); | ||||
| 			if (strcmp(sha1_to_hex(sha1), patch->old_sha1_prefix)) | ||||
| 				return error("the patch applies to '%s' (%s), " | ||||
| 					     "which does not match the " | ||||
| 					     "current contents.", | ||||
| 					     name, sha1_to_hex(sha1)); | ||||
| 		} | ||||
| 		else { | ||||
| 			/* Otherwise, the old one must be empty. */ | ||||
| 			if (desc->size) | ||||
| 				return error("the patch applies to an empty " | ||||
| 					     "'%s' but it is not empty", name); | ||||
| 		} | ||||
|  | ||||
| 		/* For now, we do not record post-image data in the patch, | ||||
| 		 * and require the object already present in the recipient's | ||||
| 		 * object database. | ||||
| 		 */ | ||||
| 		if (desc->buffer) { | ||||
| 			free(desc->buffer); | ||||
| 			desc->alloc = desc->size = 0; | ||||
| 		} | ||||
| 		get_sha1_hex(patch->new_sha1_prefix, sha1); | ||||
|  | ||||
| 		if (memcmp(sha1, null_sha1, 20)) { | ||||
| 			char type[10]; | ||||
| 			unsigned long size; | ||||
|  | ||||
| 			desc->buffer = read_sha1_file(sha1, type, &size); | ||||
| 			if (!desc->buffer) | ||||
| 				return error("the necessary postimage %s for " | ||||
| 					     "'%s' does not exist", | ||||
| 					     patch->new_sha1_prefix, name); | ||||
| 			desc->alloc = desc->size = size; | ||||
| 		} | ||||
|  | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	while (frag) { | ||||
| 		if (apply_one_fragment(desc, frag) < 0) | ||||
| 			return error("patch failed: %s:%ld", patch->old_name, frag->oldpos); | ||||
| 			return error("patch failed: %s:%ld", | ||||
| 				     name, frag->oldpos); | ||||
| 		frag = frag->next; | ||||
| 	} | ||||
| 	return 0; | ||||
|  | @ -1200,6 +1273,7 @@ static int check_patch(struct patch *patch) | |||
| 	struct stat st; | ||||
| 	const char *old_name = patch->old_name; | ||||
| 	const char *new_name = patch->new_name; | ||||
| 	const char *name = old_name ? old_name : new_name; | ||||
|  | ||||
| 	if (old_name) { | ||||
| 		int changed; | ||||
|  | @ -1274,7 +1348,7 @@ static int check_patch(struct patch *patch) | |||
| 	}	 | ||||
|  | ||||
| 	if (apply_data(patch, &st) < 0) | ||||
| 		return error("%s: patch does not apply", old_name); | ||||
| 		return error("%s: patch does not apply", name); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | @ -1723,6 +1797,10 @@ int main(int argc, char **argv) | |||
| 			diffstat = 1; | ||||
| 			continue; | ||||
| 		} | ||||
| 		if (!strcmp(arg, "--allow-binary-replacement")) { | ||||
| 			allow_binary_replacement = 1; | ||||
| 			continue; | ||||
| 		} | ||||
| 		if (!strcmp(arg, "--numstat")) { | ||||
| 			apply = 0; | ||||
| 			numstat = 1; | ||||
|  |  | |||
							
								
								
									
										2
									
								
								cache.h
								
								
								
								
							
							
						
						
									
										2
									
								
								cache.h
								
								
								
								
							|  | @ -179,6 +179,8 @@ extern int commit_index_file(struct cache_file *); | |||
| extern void rollback_index_file(struct cache_file *); | ||||
|  | ||||
| extern int trust_executable_bit; | ||||
| extern int only_use_symrefs; | ||||
| extern int diff_rename_limit_default; | ||||
|  | ||||
| #define MTIME_CHANGED	0x0001 | ||||
| #define CTIME_CHANGED	0x0002 | ||||
|  |  | |||
							
								
								
									
										19
									
								
								commit.c
								
								
								
								
							
							
						
						
									
										19
									
								
								commit.c
								
								
								
								
							|  | @ -204,6 +204,7 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size) | |||
| 	unsigned char parent[20]; | ||||
| 	struct commit_list **pptr; | ||||
| 	struct commit_graft *graft; | ||||
| 	unsigned n_refs = 0; | ||||
|  | ||||
| 	if (item->object.parsed) | ||||
| 		return 0; | ||||
|  | @ -214,7 +215,7 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size) | |||
| 		return error("bad tree pointer in commit %s\n", sha1_to_hex(item->object.sha1)); | ||||
| 	item->tree = lookup_tree(parent); | ||||
| 	if (item->tree) | ||||
| 		add_ref(&item->object, &item->tree->object); | ||||
| 		n_refs++; | ||||
| 	bufptr += 46; /* "tree " + "hex sha1" + "\n" */ | ||||
| 	pptr = &item->parents; | ||||
|  | ||||
|  | @ -230,7 +231,7 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size) | |||
| 		new_parent = lookup_commit(parent); | ||||
| 		if (new_parent) { | ||||
| 			pptr = &commit_list_insert(new_parent, pptr)->next; | ||||
| 			add_ref(&item->object, &new_parent->object); | ||||
| 			n_refs++; | ||||
| 		} | ||||
| 	} | ||||
| 	if (graft) { | ||||
|  | @ -241,10 +242,22 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size) | |||
| 			if (!new_parent) | ||||
| 				continue; | ||||
| 			pptr = &commit_list_insert(new_parent, pptr)->next; | ||||
| 			add_ref(&item->object, &new_parent->object); | ||||
| 			n_refs++; | ||||
| 		} | ||||
| 	} | ||||
| 	item->date = parse_commit_date(bufptr); | ||||
|  | ||||
| 	if (track_object_refs) { | ||||
| 		unsigned i = 0; | ||||
| 		struct commit_list *p; | ||||
| 		struct object_refs *refs = alloc_object_refs(n_refs); | ||||
| 		if (item->tree) | ||||
| 			refs->ref[i++] = &item->tree->object; | ||||
| 		for (p = item->parents; p; p = p->next) | ||||
| 			refs->ref[i++] = &p->item->object; | ||||
| 		set_object_refs(&item->object, refs); | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  |  | |||
							
								
								
									
										10
									
								
								config.c
								
								
								
								
							
							
						
						
									
										10
									
								
								config.c
								
								
								
								
							|  | @ -214,6 +214,11 @@ int git_default_config(const char *var, const char *value) | |||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	if (!strcmp(var, "core.symrefsonly")) { | ||||
| 		only_use_symrefs = git_config_bool(var, value); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	if (!strcmp(var, "user.name")) { | ||||
| 		strncpy(git_default_name, value, sizeof(git_default_name)); | ||||
| 		return 0; | ||||
|  | @ -224,6 +229,11 @@ int git_default_config(const char *var, const char *value) | |||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	if (!strcmp(var, "diff.renamelimit")) { | ||||
| 		diff_rename_limit_default = git_config_int(var, value); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* Add other config variables here.. */ | ||||
| 	return 0; | ||||
| } | ||||
|  |  | |||
							
								
								
									
										11
									
								
								daemon.c
								
								
								
								
							
							
						
						
									
										11
									
								
								daemon.c
								
								
								
								
							|  | @ -594,6 +594,7 @@ int main(int argc, char **argv) | |||
| 		} | ||||
| 		if (!strcmp(arg, "--inetd")) { | ||||
| 			inetd_mode = 1; | ||||
| 			log_syslog = 1; | ||||
| 			continue; | ||||
| 		} | ||||
| 		if (!strcmp(arg, "--verbose")) { | ||||
|  | @ -602,7 +603,6 @@ int main(int argc, char **argv) | |||
| 		} | ||||
| 		if (!strcmp(arg, "--syslog")) { | ||||
| 			log_syslog = 1; | ||||
| 			openlog("git-daemon", 0, LOG_DAEMON); | ||||
| 			continue; | ||||
| 		} | ||||
| 		if (!strcmp(arg, "--export-all")) { | ||||
|  | @ -611,9 +611,11 @@ int main(int argc, char **argv) | |||
| 		} | ||||
| 		if (!strncmp(arg, "--timeout=", 10)) { | ||||
| 			timeout = atoi(arg+10); | ||||
| 			continue; | ||||
| 		} | ||||
| 		if (!strncmp(arg, "--init-timeout=", 15)) { | ||||
| 			init_timeout = atoi(arg+15); | ||||
| 			continue; | ||||
| 		} | ||||
| 		if (!strcmp(arg, "--")) { | ||||
| 			ok_paths = &argv[i+1]; | ||||
|  | @ -626,10 +628,13 @@ int main(int argc, char **argv) | |||
| 		usage(daemon_usage); | ||||
| 	} | ||||
|  | ||||
| 	if (log_syslog) | ||||
| 		openlog("git-daemon", 0, LOG_DAEMON); | ||||
|  | ||||
| 	if (inetd_mode) { | ||||
| 		fclose(stderr); //FIXME: workaround | ||||
| 		return execute(); | ||||
| 	} else { | ||||
| 		return serve(port); | ||||
| 	} | ||||
|  | ||||
| 	return serve(port); | ||||
| } | ||||
|  |  | |||
|  | @ -1,3 +1,9 @@ | |||
| git-core (0.99.9j-0) unstable; urgency=low | ||||
|  | ||||
|   * GIT 0.99.9j aka 1.0rc3 | ||||
|  | ||||
|  -- Junio C Hamano <junkio@cox.net>  Wed, 16 Nov 2005 20:39:55 -0800 | ||||
|  | ||||
| git-core (0.99.9i-0) unstable; urgency=low | ||||
|  | ||||
|   * GIT 0.99.9i aka 1.0rc2 | ||||
|  |  | |||
							
								
								
									
										23
									
								
								diff.c
								
								
								
								
							
							
						
						
									
										23
									
								
								diff.c
								
								
								
								
							|  | @ -13,6 +13,8 @@ static const char *diff_opts = "-pu"; | |||
|  | ||||
| static int use_size_cache; | ||||
|  | ||||
| int diff_rename_limit_default = -1; | ||||
|  | ||||
| static char *quote_one(const char *str) | ||||
| { | ||||
| 	int needlen; | ||||
|  | @ -648,7 +650,7 @@ static void diff_fill_sha1_info(struct diff_filespec *one) | |||
| 		memset(one->sha1, 0, 20); | ||||
| } | ||||
|  | ||||
| static void run_diff(struct diff_filepair *p) | ||||
| static void run_diff(struct diff_filepair *p, struct diff_options *o) | ||||
| { | ||||
| 	const char *pgm = external_diff(); | ||||
| 	char msg[PATH_MAX*2+300], *xfrm_msg; | ||||
|  | @ -711,11 +713,11 @@ static void run_diff(struct diff_filepair *p) | |||
|  | ||||
| 	if (memcmp(one->sha1, two->sha1, 20)) { | ||||
| 		char one_sha1[41]; | ||||
| 		const char *index_fmt = o->full_index ? "index %s..%s" : "index %.7s..%.7s"; | ||||
| 		memcpy(one_sha1, sha1_to_hex(one->sha1), 41); | ||||
|  | ||||
| 		len += snprintf(msg + len, sizeof(msg) - len, | ||||
| 				"index %.7s..%.7s", one_sha1, | ||||
| 				sha1_to_hex(two->sha1)); | ||||
| 				index_fmt, one_sha1, sha1_to_hex(two->sha1)); | ||||
| 		if (one->mode == two->mode) | ||||
| 			len += snprintf(msg + len, sizeof(msg) - len, | ||||
| 					" %06o", one->mode); | ||||
|  | @ -761,9 +763,12 @@ void diff_setup(struct diff_options *options) | |||
|  | ||||
| int diff_setup_done(struct diff_options *options) | ||||
| { | ||||
| 	if ((options->find_copies_harder || 0 <= options->rename_limit) && | ||||
| 	    options->detect_rename != DIFF_DETECT_COPY) | ||||
| 	if ((options->find_copies_harder && | ||||
| 	     options->detect_rename != DIFF_DETECT_COPY) || | ||||
| 	    (0 <= options->rename_limit && !options->detect_rename)) | ||||
| 		return -1; | ||||
| 	if (options->detect_rename && options->rename_limit < 0) | ||||
| 		options->rename_limit = diff_rename_limit_default; | ||||
| 	if (options->setup & DIFF_SETUP_USE_CACHE) { | ||||
| 		if (!active_cache) | ||||
| 			/* read-cache does not die even when it fails | ||||
|  | @ -789,6 +794,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) | |||
| 		options->line_termination = 0; | ||||
| 	else if (!strncmp(arg, "-l", 2)) | ||||
| 		options->rename_limit = strtoul(arg+2, NULL, 10); | ||||
| 	else if (!strcmp(arg, "--full-index")) | ||||
| 		options->full_index = 1; | ||||
| 	else if (!strcmp(arg, "--name-only")) | ||||
| 		options->output_format = DIFF_FORMAT_NAME; | ||||
| 	else if (!strcmp(arg, "--name-status")) | ||||
|  | @ -1017,7 +1024,7 @@ int diff_unmodified_pair(struct diff_filepair *p) | |||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void diff_flush_patch(struct diff_filepair *p) | ||||
| static void diff_flush_patch(struct diff_filepair *p, struct diff_options *o) | ||||
| { | ||||
| 	if (diff_unmodified_pair(p)) | ||||
| 		return; | ||||
|  | @ -1026,7 +1033,7 @@ static void diff_flush_patch(struct diff_filepair *p) | |||
| 	    (DIFF_FILE_VALID(p->two) && S_ISDIR(p->two->mode))) | ||||
| 		return; /* no tree diffs in patch format */  | ||||
|  | ||||
| 	run_diff(p); | ||||
| 	run_diff(p, o); | ||||
| } | ||||
|  | ||||
| int diff_queue_is_empty(void) | ||||
|  | @ -1158,7 +1165,7 @@ void diff_flush(struct diff_options *options) | |||
| 			die("internal error in diff-resolve-rename-copy"); | ||||
| 		switch (diff_output_format) { | ||||
| 		case DIFF_FORMAT_PATCH: | ||||
| 			diff_flush_patch(p); | ||||
| 			diff_flush_patch(p, options); | ||||
| 			break; | ||||
| 		case DIFF_FORMAT_RAW: | ||||
| 		case DIFF_FORMAT_NAME_STATUS: | ||||
|  |  | |||
							
								
								
									
										4
									
								
								diff.h
								
								
								
								
							
							
						
						
									
										4
									
								
								diff.h
								
								
								
								
							|  | @ -32,7 +32,8 @@ struct diff_options { | |||
| 	const char *orderfile; | ||||
| 	const char *pickaxe; | ||||
| 	unsigned recursive:1, | ||||
| 		 tree_in_recursive:1; | ||||
| 		 tree_in_recursive:1, | ||||
| 		 full_index:1; | ||||
| 	int break_opt; | ||||
| 	int detect_rename; | ||||
| 	int find_copies_harder; | ||||
|  | @ -96,6 +97,7 @@ extern void diffcore_std_no_resolve(struct diff_options *); | |||
| "  -u            synonym for -p.\n" \ | ||||
| "  --name-only   show only names of changed files.\n" \ | ||||
| "  --name-status show names and status of changed files.\n" \ | ||||
| "  --full-index  show full object name on index ines.\n" \ | ||||
| "  -R            swap input file pairs.\n" \ | ||||
| "  -B            detect complete rewrites.\n" \ | ||||
| "  -M            detect renames.\n" \ | ||||
|  |  | |||
|  | @ -283,7 +283,7 @@ void diffcore_rename(struct diff_options *options) | |||
| 			register_rename_src(p->one, 1); | ||||
| 	} | ||||
| 	if (rename_dst_nr == 0 || | ||||
| 	    (0 <= rename_limit && rename_limit < rename_dst_nr)) | ||||
| 	    (0 < rename_limit && rename_limit < rename_dst_nr)) | ||||
| 		goto cleanup; /* nothing to do */ | ||||
|  | ||||
| 	/* We really want to cull the candidates list early | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ | |||
| char git_default_email[MAX_GITNAME]; | ||||
| char git_default_name[MAX_GITNAME]; | ||||
| int trust_executable_bit = 1; | ||||
| int only_use_symrefs = 0; | ||||
|  | ||||
| static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir, | ||||
| 	*git_graft_file; | ||||
|  |  | |||
|  | @ -56,7 +56,6 @@ static void check_connectivity(void) | |||
| 	/* Look up all the requirements, warn about missing objects.. */ | ||||
| 	for (i = 0; i < nr_objs; i++) { | ||||
| 		struct object *obj = objs[i]; | ||||
| 		struct object_list *refs; | ||||
|  | ||||
| 		if (!obj->parsed) { | ||||
| 			if (!standalone && has_sha1_file(obj->sha1)) | ||||
|  | @ -67,14 +66,19 @@ static void check_connectivity(void) | |||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		for (refs = obj->refs; refs; refs = refs->next) { | ||||
| 			if (refs->item->parsed || | ||||
| 			    (!standalone && has_sha1_file(refs->item->sha1))) | ||||
| 				continue; | ||||
| 			printf("broken link from %7s %s\n", | ||||
| 			       obj->type, sha1_to_hex(obj->sha1)); | ||||
| 			printf("              to %7s %s\n", | ||||
| 			       refs->item->type, sha1_to_hex(refs->item->sha1)); | ||||
| 		if (obj->refs) { | ||||
| 			const struct object_refs *refs = obj->refs; | ||||
| 			unsigned j; | ||||
| 			for (j = 0; j < refs->count; j++) { | ||||
| 				struct object *ref = refs->ref[j]; | ||||
| 				if (ref->parsed || | ||||
| 				    (!standalone && has_sha1_file(ref->sha1))) | ||||
| 					continue; | ||||
| 				printf("broken link from %7s %s\n", | ||||
| 				       obj->type, sha1_to_hex(obj->sha1)); | ||||
| 				printf("              to %7s %s\n", | ||||
| 				       ref->type, sha1_to_hex(ref->sha1)); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (show_unreachable && !(obj->flags & REACHABLE)) { | ||||
|  | @ -184,10 +188,17 @@ static int fsck_tree(struct tree *item) | |||
| 			default: | ||||
| 				break; | ||||
| 			} | ||||
| 			free(last->name); | ||||
| 			free(last); | ||||
| 		} | ||||
|  | ||||
| 		last = entry; | ||||
| 	} | ||||
| 	if (last) { | ||||
| 		free(last->name); | ||||
| 		free(last); | ||||
| 	} | ||||
| 	item->entries = NULL; | ||||
|  | ||||
| 	retval = 0; | ||||
| 	if (has_full_path) { | ||||
|  |  | |||
							
								
								
									
										65
									
								
								git-am.sh
								
								
								
								
							
							
						
						
									
										65
									
								
								git-am.sh
								
								
								
								
							|  | @ -3,16 +3,10 @@ | |||
| # | ||||
| . 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=<dir>] [--utf8] [--3way] <mbox>" | ||||
|     echo >&2 "	or, when resuming" | ||||
|     echo >&2 "	$0 [--skip]" | ||||
|     echo >&2 "	$0 [--skip | --resolved]" | ||||
|     exit 1; | ||||
| } | ||||
|  | ||||
|  | @ -104,7 +98,7 @@ fall_back_3way () { | |||
| } | ||||
|  | ||||
| prec=4 | ||||
| dotest=.dotest sign= utf8= keep= skip= interactive= | ||||
| dotest=.dotest sign= utf8= keep= skip= interactive= resolved= | ||||
|  | ||||
| while case "$#" in 0) break;; esac | ||||
| do | ||||
|  | @ -128,6 +122,9 @@ do | |||
| 	-k|--k|--ke|--kee|--keep) | ||||
| 	keep=t; shift ;; | ||||
|  | ||||
| 	-r|--r|--re|--res|--reso|--resol|--resolv|--resolve|--resolved) | ||||
| 	resolved=t; shift ;; | ||||
|  | ||||
| 	--sk|--ski|--skip) | ||||
| 	skip=t; shift ;; | ||||
|  | ||||
|  | @ -140,6 +137,8 @@ do | |||
| 	esac | ||||
| done | ||||
|  | ||||
| # If the dotest directory exists, but we have finished applying all the | ||||
| # patches in them, clear it out. | ||||
| if test -d "$dotest" && | ||||
|    last=$(cat "$dotest/last") && | ||||
|    next=$(cat "$dotest/next") && | ||||
|  | @ -155,9 +154,9 @@ then | |||
| 	die "previous dotest directory $dotest still exists but mbox given." | ||||
| 	resume=yes | ||||
| else | ||||
| 	# Make sure we are not given --skip | ||||
| 	test ",$skip," = ,, || | ||||
| 	die "we are not resuming." | ||||
| 	# Make sure we are not given --skip nor --resolved | ||||
| 	test ",$skip,$resolved," = ,,, || | ||||
| 		die "we are not resuming." | ||||
|  | ||||
| 	# Start afresh. | ||||
| 	mkdir -p "$dotest" || exit | ||||
|  | @ -170,12 +169,24 @@ else | |||
| 		exit 1 | ||||
| 	} | ||||
|  | ||||
| 	# -s, -u and -k flags are kept for the resuming session after | ||||
| 	# a patch failure. | ||||
| 	# -3 and -i can and must be given when resuming. | ||||
| 	echo "$sign" >"$dotest/sign" | ||||
| 	echo "$utf8" >"$dotest/utf8" | ||||
| 	echo "$keep" >"$dotest/keep" | ||||
| 	echo 1 >"$dotest/next" | ||||
| fi | ||||
|  | ||||
| case "$resolved" in | ||||
| '') | ||||
| 	files=$(git-diff-index --cached --name-only HEAD) || exit | ||||
| 	if [ "$files" ]; then | ||||
| 	   echo "Dirty index: cannot apply patches (dirty: $files)" >&2 | ||||
| 	   exit 1 | ||||
| 	fi | ||||
| esac | ||||
|  | ||||
| if test "$(cat "$dotest/utf8")" = t | ||||
| then | ||||
| 	utf8=-u | ||||
|  | @ -216,6 +227,15 @@ do | |||
| 		go_next | ||||
| 		continue | ||||
| 	} | ||||
|  | ||||
| 	# If we are not resuming, parse and extract the patch information | ||||
| 	# into separate files: | ||||
| 	#  - info records the authorship and title | ||||
| 	#  - msg is the rest of commit log message | ||||
| 	#  - patch is the patch body. | ||||
| 	# | ||||
| 	# When we are resuming, these files are either already prepared | ||||
| 	# by the user, or the user can tell us to do so by --resolved flag. | ||||
| 	case "$resume" in | ||||
| 	'') | ||||
| 		git-mailinfo $keep $utf8 "$dotest/msg" "$dotest/patch" \ | ||||
|  | @ -263,6 +283,13 @@ do | |||
| 		fi | ||||
| 	    } >"$dotest/final-commit" | ||||
| 	    ;; | ||||
| 	*) | ||||
| 		case "$resolved,$interactive" in | ||||
| 		tt) | ||||
| 			# This is used only for interactive view option. | ||||
| 			git-diff-index -p --cached HEAD >"$dotest/patch" | ||||
| 			;; | ||||
| 		esac | ||||
| 	esac | ||||
|  | ||||
| 	resume= | ||||
|  | @ -310,7 +337,21 @@ do | |||
| 	echo "Applying '$SUBJECT'" | ||||
| 	echo | ||||
|  | ||||
| 	git-apply --index "$dotest/patch"; apply_status=$? | ||||
| 	case "$resolved" in | ||||
| 	'') | ||||
| 		git-apply --index "$dotest/patch" | ||||
| 		apply_status=$? | ||||
| 		;; | ||||
| 	t) | ||||
| 		# Resolved means the user did all the hard work, and | ||||
| 		# we do not have to do any patch application.  Just | ||||
| 		# trust what the user has in the index file and the | ||||
| 		# working tree. | ||||
| 		resolved= | ||||
| 		apply_status=0 | ||||
| 		;; | ||||
| 	esac | ||||
|  | ||||
| 	if test $apply_status = 1 && test "$threeway" = t | ||||
| 	then | ||||
| 		if (fall_back_3way) | ||||
|  |  | |||
|  | @ -410,8 +410,7 @@ foreach my $ps (@psets) { | |||
|     open  HEAD, ">$git_dir/refs/heads/$ps->{branch}"; | ||||
|     print HEAD $commitid; | ||||
|     close HEAD; | ||||
|     unlink ("$git_dir/HEAD"); | ||||
|     symlink("refs/heads/$ps->{branch}","$git_dir/HEAD"); | ||||
|     system('git-update-ref', 'HEAD', "$ps->{branch}"); | ||||
|  | ||||
|     # tag accordingly | ||||
|     ptag($ps->{id}, $commitid); # private tag | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ use strict; | |||
| use Getopt::Std; | ||||
| use File::Temp qw(tempdir); | ||||
| use Data::Dumper; | ||||
| use File::Basename qw(basename); | ||||
|  | ||||
| unless ($ENV{GIT_DIR} && -r $ENV{GIT_DIR}){ | ||||
|     die "GIT_DIR is not defined or is unreadable"; | ||||
|  | @ -11,7 +12,7 @@ unless ($ENV{GIT_DIR} && -r $ENV{GIT_DIR}){ | |||
|  | ||||
| our ($opt_h, $opt_p, $opt_v, $opt_c ); | ||||
|  | ||||
| getopt('hpvc'); | ||||
| getopts('hpvc'); | ||||
|  | ||||
| $opt_h && usage(); | ||||
|  | ||||
|  | @ -77,7 +78,7 @@ $opt_v && print "Applying to CVS commit $commit from parent $parent\n"; | |||
|  | ||||
| # grab the commit message | ||||
| `git-cat-file commit $commit | sed -e '1,/^\$/d' > .msg`; | ||||
| $? && die "Error extraction the commit message"; | ||||
| $? && die "Error extracting the commit message"; | ||||
|  | ||||
| my (@afiles, @dfiles, @mfiles); | ||||
| my @files = `git-diff-tree -r $parent $commit`; | ||||
|  | @ -187,9 +188,9 @@ my $cmd = "cvs commit -F .msg $commitfiles"; | |||
|  | ||||
| if ($dirtypatch) { | ||||
|     print "NOTE: One or more hunks failed to apply cleanly.\n"; | ||||
|     print "Resolve the conflicts and then commit using:n"; | ||||
|     print "Resolve the conflicts and then commit using:\n"; | ||||
|     print "\n    $cmd\n\n"; | ||||
|     exit; | ||||
|     exit(1); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | @ -206,8 +207,7 @@ if ($opt_c) { | |||
| } | ||||
| sub usage { | ||||
| 	print STDERR <<END; | ||||
| Usage: GIT_DIR=/path/to/.gi ${\basename $0}      # fetch/update GIT from CVS | ||||
|        [-h] [-p] [ parent ] commit | ||||
| Usage: GIT_DIR=/path/to/.git ${\basename $0} [-h] [-p] [-v] [-c] [ parent ] commit | ||||
| END | ||||
| 	exit(1); | ||||
| } | ||||
|  |  | |||
|  | @ -437,7 +437,11 @@ unless(-d $git_dir) { | |||
| 		       "Either use the correct '-o branch' option,\n". | ||||
| 		       "or import to a new repository.\n"; | ||||
|  | ||||
| 	$last_branch = basename(readlink("$git_dir/HEAD")); | ||||
| 	open(F, "git-symbolic-ref HEAD |") or | ||||
| 		die "Cannot run git-symbolic-ref: $!\n"; | ||||
| 	chomp ($last_branch = <F>); | ||||
| 	$last_branch = basename($last_branch); | ||||
| 	close(F); | ||||
| 	unless($last_branch) { | ||||
| 		warn "Cannot read the last branch name: $! -- assuming 'master'\n"; | ||||
| 		$last_branch = "master"; | ||||
|  | @ -829,8 +833,7 @@ if($orig_branch) { | |||
| 	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"); | ||||
| 	system('git-update-ref', 'HEAD', "$orig_branch"); | ||||
| 	unless ($opt_i) { | ||||
| 		system('git checkout'); | ||||
| 		die "checkout failed: $?\n" if $?; | ||||
|  |  | |||
|  | @ -39,5 +39,9 @@ while : ; do | |||
| 	esac | ||||
| 	shift | ||||
| done | ||||
| [ "$pattern" ] || { | ||||
| 	echo >&2 "usage: 'git grep <pattern> [pathspec*]'" | ||||
| 	exit 1 | ||||
| } | ||||
| git-ls-files -z "${git_flags[@]}" "$@" | | ||||
| 	xargs -0 grep "${flags[@]}" -e "$pattern" | ||||
|  |  | |||
|  | @ -3,11 +3,13 @@ | |||
| # Copyright (C) 2005 Fredrik Kuivinen | ||||
| # | ||||
|  | ||||
| import sys, math, random, os, re, signal, tempfile, stat, errno, traceback | ||||
| import sys | ||||
| sys.path.append('''@@GIT_PYTHON_PATH@@''') | ||||
|  | ||||
| import math, random, os, re, signal, tempfile, stat, errno, traceback | ||||
| from heapq import heappush, heappop | ||||
| from sets import Set | ||||
|  | ||||
| sys.path.append('''@@GIT_PYTHON_PATH@@''') | ||||
| from gitMergeCommon import * | ||||
|  | ||||
| outputIndent = 0 | ||||
|  |  | |||
|  | @ -216,7 +216,11 @@ unless(-d $git_dir) { | |||
| 	-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")); | ||||
| 	open(F, "git-symbolic-ref HEAD |") or | ||||
| 		die "Cannot run git-symbolic-ref: $!\n"; | ||||
| 	chomp ($last_branch = <F>); | ||||
| 	$last_branch = basename($last_branch); | ||||
| 	close(F); | ||||
| 	unless($last_branch) { | ||||
| 		warn "Cannot read the last branch name: $! -- assuming 'master'\n"; | ||||
| 		$last_branch = "master"; | ||||
|  | @ -766,8 +770,7 @@ if($orig_branch) { | |||
| 	print "DONE; creating $orig_branch branch\n" if $opt_v and (not defined $opt_l or $opt_l > 0); | ||||
| 	system("cp","$git_dir/refs/heads/$opt_o","$git_dir/refs/heads/master") | ||||
| 		unless -f "$git_dir/refs/heads/master"; | ||||
| 	unlink("$git_dir/HEAD"); | ||||
| 	symlink("refs/heads/$orig_branch","$git_dir/HEAD"); | ||||
| 	system('git-update-ref', 'HEAD', "$orig_branch"); | ||||
| 	unless ($opt_i) { | ||||
| 		system('git checkout'); | ||||
| 		die "checkout failed: $?\n" if $?; | ||||
|  |  | |||
|  | @ -0,0 +1,295 @@ | |||
| #include <stdio.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
| #include <dirent.h> | ||||
| #include <unistd.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <errno.h> | ||||
| #include <limits.h> | ||||
| #include <stdarg.h> | ||||
|  | ||||
| #ifndef PATH_MAX | ||||
| # define PATH_MAX 4096 | ||||
| #endif | ||||
|  | ||||
| static const char git_usage[] = | ||||
| 	"Usage: git [--version] [--exec-path[=GIT_EXEC_PATH]] [--help] COMMAND [ ARGS ]"; | ||||
|  | ||||
| /* most gui terms set COLUMNS (although some don't export it) */ | ||||
| static int term_columns(void) | ||||
| { | ||||
| 	char *col_string = getenv("COLUMNS"); | ||||
| 	int n_cols = 0; | ||||
|  | ||||
| 	if (col_string && (n_cols = atoi(col_string)) > 0) | ||||
| 		return n_cols; | ||||
|  | ||||
| 	return 80; | ||||
| } | ||||
|  | ||||
| static void oom(void) | ||||
| { | ||||
| 	fprintf(stderr, "git: out of memory\n"); | ||||
| 	exit(1); | ||||
| } | ||||
|  | ||||
| static inline void mput_char(char c, unsigned int num) | ||||
| { | ||||
| 	while(num--) | ||||
| 		putchar(c); | ||||
| } | ||||
|  | ||||
| static struct cmdname { | ||||
| 	size_t len; | ||||
| 	char name[1]; | ||||
| } **cmdname; | ||||
| static int cmdname_alloc, cmdname_cnt; | ||||
|  | ||||
| static void add_cmdname(const char *name, int len) | ||||
| { | ||||
| 	struct cmdname *ent; | ||||
| 	if (cmdname_alloc <= cmdname_cnt) { | ||||
| 		cmdname_alloc = cmdname_alloc + 200; | ||||
| 		cmdname = realloc(cmdname, cmdname_alloc * sizeof(*cmdname)); | ||||
| 		if (!cmdname) | ||||
| 			oom(); | ||||
| 	} | ||||
| 	ent = malloc(sizeof(*ent) + len); | ||||
| 	if (!ent) | ||||
| 		oom(); | ||||
| 	ent->len = len; | ||||
| 	memcpy(ent->name, name, len+1); | ||||
| 	cmdname[cmdname_cnt++] = ent; | ||||
| } | ||||
|  | ||||
| static int cmdname_compare(const void *a_, const void *b_) | ||||
| { | ||||
| 	struct cmdname *a = *(struct cmdname **)a_; | ||||
| 	struct cmdname *b = *(struct cmdname **)b_; | ||||
| 	return strcmp(a->name, b->name); | ||||
| } | ||||
|  | ||||
| static void pretty_print_string_list(struct cmdname **cmdname, int longest) | ||||
| { | ||||
| 	int cols = 1; | ||||
| 	int space = longest + 1; /* min 1 SP between words */ | ||||
| 	int max_cols = term_columns() - 1; /* don't print *on* the edge */ | ||||
| 	int i; | ||||
|  | ||||
| 	if (space < max_cols) | ||||
| 		cols = max_cols / space; | ||||
|  | ||||
| 	qsort(cmdname, cmdname_cnt, sizeof(*cmdname), cmdname_compare); | ||||
|  | ||||
| 	for (i = 0; i < cmdname_cnt; ) { | ||||
| 		int c; | ||||
| 		printf("  "); | ||||
|  | ||||
| 		for (c = cols; c && i < cmdname_cnt; i++) { | ||||
| 			printf("%s", cmdname[i]->name); | ||||
|  | ||||
| 			if (--c) | ||||
| 				mput_char(' ', space - cmdname[i]->len); | ||||
| 		} | ||||
| 		putchar('\n'); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void list_commands(const char *exec_path, const char *pattern) | ||||
| { | ||||
| 	unsigned int longest = 0; | ||||
| 	char path[PATH_MAX]; | ||||
| 	int dirlen; | ||||
| 	DIR *dir = opendir(exec_path); | ||||
| 	struct dirent *de; | ||||
|  | ||||
| 	if (!dir) { | ||||
| 		fprintf(stderr, "git: '%s': %s\n", exec_path, strerror(errno)); | ||||
| 		exit(1); | ||||
| 	} | ||||
|  | ||||
| 	dirlen = strlen(exec_path); | ||||
| 	if (PATH_MAX - 20 < dirlen) { | ||||
| 		fprintf(stderr, "git: insanely long exec-path '%s'\n", | ||||
| 			exec_path); | ||||
| 		exit(1); | ||||
| 	} | ||||
|  | ||||
| 	memcpy(path, exec_path, dirlen); | ||||
| 	path[dirlen++] = '/'; | ||||
|  | ||||
| 	while ((de = readdir(dir)) != NULL) { | ||||
| 		struct stat st; | ||||
| 		int entlen; | ||||
|  | ||||
| 		if (strncmp(de->d_name, "git-", 4)) | ||||
| 			continue; | ||||
| 		strcpy(path+dirlen, de->d_name); | ||||
| 		if (stat(path, &st) || /* stat, not lstat */ | ||||
| 		    !S_ISREG(st.st_mode) || | ||||
| 		    !(st.st_mode & S_IXUSR)) | ||||
| 			continue; | ||||
|  | ||||
| 		entlen = strlen(de->d_name); | ||||
|  | ||||
| 		if (longest < entlen) | ||||
| 			longest = entlen; | ||||
|  | ||||
| 		add_cmdname(de->d_name + 4, entlen-4); | ||||
| 	} | ||||
| 	closedir(dir); | ||||
|  | ||||
| 	printf("git commands available in '%s'\n", exec_path); | ||||
| 	printf("----------------------------"); | ||||
| 	mput_char('-', strlen(exec_path)); | ||||
| 	putchar('\n'); | ||||
| 	pretty_print_string_list(cmdname, longest - 4); | ||||
| 	putchar('\n'); | ||||
| } | ||||
|  | ||||
| #ifdef __GNUC__ | ||||
| static void usage(const char *exec_path, const char *fmt, ...) | ||||
| 	__attribute__((__format__(__printf__, 2, 3), __noreturn__)); | ||||
| #endif | ||||
| static void usage(const char *exec_path, const char *fmt, ...) | ||||
| { | ||||
| 	if (fmt) { | ||||
| 		va_list ap; | ||||
|  | ||||
| 		va_start(ap, fmt); | ||||
| 		printf("git: "); | ||||
| 		vprintf(fmt, ap); | ||||
| 		va_end(ap); | ||||
| 		putchar('\n'); | ||||
| 	} | ||||
| 	else | ||||
| 		puts(git_usage); | ||||
|  | ||||
| 	putchar('\n'); | ||||
|  | ||||
| 	if(exec_path) | ||||
| 		list_commands(exec_path, "git-*"); | ||||
|  | ||||
| 	exit(1); | ||||
| } | ||||
|  | ||||
| static void prepend_to_path(const char *dir, int len) | ||||
| { | ||||
| 	char *path, *old_path = getenv("PATH"); | ||||
| 	int path_len = len; | ||||
|  | ||||
| 	if (!old_path) | ||||
| 		old_path = "/usr/local/bin:/usr/bin:/bin"; | ||||
|  | ||||
| 	path_len = len + strlen(old_path) + 1; | ||||
|  | ||||
| 	path = malloc(path_len + 1); | ||||
| 	path[path_len + 1] = '\0'; | ||||
|  | ||||
| 	memcpy(path, dir, len); | ||||
| 	path[len] = ':'; | ||||
| 	memcpy(path + len + 1, old_path, path_len - len); | ||||
|  | ||||
| 	setenv("PATH", path, 1); | ||||
| } | ||||
|  | ||||
| static void show_man_page(char *git_cmd) | ||||
| { | ||||
| 	char *page; | ||||
|  | ||||
| 	if (!strncmp(git_cmd, "git", 3)) | ||||
| 		page = git_cmd; | ||||
| 	else { | ||||
| 		int page_len = strlen(git_cmd) + 4; | ||||
|  | ||||
| 		page = malloc(page_len + 1); | ||||
| 		strcpy(page, "git-"); | ||||
| 		strcpy(page + 4, git_cmd); | ||||
| 		page[page_len] = 0; | ||||
| 	} | ||||
|  | ||||
| 	execlp("man", "man", page, NULL); | ||||
| } | ||||
|  | ||||
| int main(int argc, char **argv, char **envp) | ||||
| { | ||||
| 	char git_command[PATH_MAX + 1]; | ||||
| 	char wd[PATH_MAX + 1]; | ||||
| 	int i, len, show_help = 0; | ||||
| 	char *exec_path = getenv("GIT_EXEC_PATH"); | ||||
|  | ||||
| 	getcwd(wd, PATH_MAX); | ||||
|  | ||||
| 	if (!exec_path) | ||||
| 		exec_path = GIT_EXEC_PATH; | ||||
|  | ||||
| 	for (i = 1; i < argc; i++) { | ||||
| 		char *arg = argv[i]; | ||||
|  | ||||
| 		if (strncmp(arg, "--", 2)) | ||||
| 			break; | ||||
|  | ||||
| 		arg += 2; | ||||
|  | ||||
| 		if (!strncmp(arg, "exec-path", 9)) { | ||||
| 			arg += 9; | ||||
| 			if (*arg == '=') | ||||
| 				exec_path = arg + 1; | ||||
| 			else { | ||||
| 				puts(exec_path); | ||||
| 				exit(0); | ||||
| 			} | ||||
| 		} | ||||
| 		else if (!strcmp(arg, "version")) { | ||||
| 			printf("git version %s\n", GIT_VERSION); | ||||
| 			exit(0); | ||||
| 		} | ||||
| 		else if (!strcmp(arg, "help")) | ||||
| 			show_help = 1; | ||||
| 		else if (!show_help) | ||||
| 			usage(NULL, NULL); | ||||
| 	} | ||||
|  | ||||
| 	if (i >= argc || show_help) { | ||||
| 		if (i >= argc) | ||||
| 			usage(exec_path, NULL); | ||||
|  | ||||
| 		show_man_page(argv[i]); | ||||
| 	} | ||||
|  | ||||
| 	if (*exec_path != '/') { | ||||
| 		if (!getcwd(git_command, sizeof(git_command))) { | ||||
| 			fprintf(stderr, | ||||
| 				"git: cannot determine current directory"); | ||||
| 			exit(1); | ||||
| 		} | ||||
| 		len = strlen(git_command); | ||||
|  | ||||
| 		/* Trivial cleanup */ | ||||
| 		while (!strncmp(exec_path, "./", 2)) { | ||||
| 			exec_path += 2; | ||||
| 			while (*exec_path == '/') | ||||
| 				*exec_path++; | ||||
| 		} | ||||
| 		snprintf(git_command + len, sizeof(git_command) - len, | ||||
| 			 "/%s", exec_path); | ||||
| 	} | ||||
| 	else | ||||
| 		strcpy(git_command, exec_path); | ||||
| 	len = strlen(git_command); | ||||
| 	prepend_to_path(git_command, len); | ||||
|  | ||||
| 	strncat(&git_command[len], "/git-", sizeof(git_command) - len); | ||||
| 	len += 5; | ||||
| 	strncat(&git_command[len], argv[i], sizeof(git_command) - len); | ||||
|  | ||||
| 	if (access(git_command, X_OK)) | ||||
| 		usage(exec_path, "'%s' is not a git-command", argv[i]); | ||||
|  | ||||
| 	/* execve() can only ever return if it fails */ | ||||
| 	execve(git_command, &argv[i], envp); | ||||
| 	printf("Failed to run command '%s': %s\n", git_command, strerror(errno)); | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
							
								
								
									
										76
									
								
								git.sh
								
								
								
								
							
							
						
						
									
										76
									
								
								git.sh
								
								
								
								
							|  | @ -1,76 +0,0 @@ | |||
| #!/bin/sh | ||||
|  | ||||
| cmd= | ||||
| path=$(dirname "$0") | ||||
| case "$#" in | ||||
| 0)	;; | ||||
| *)	cmd="$1" | ||||
| 	shift | ||||
| 	case "$cmd" in | ||||
| 	-v|--v|--ve|--ver|--vers|--versi|--versio|--version) | ||||
| 		echo "git version @@GIT_VERSION@@" | ||||
| 		exit 0 ;; | ||||
| 	esac | ||||
| 	 | ||||
| 	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]" | ||||
| if [ -n "$cmd" ]; then | ||||
|     echo "git command '$cmd' not found." | ||||
| fi | ||||
| echo "git commands are:" | ||||
|  | ||||
| fmt <<\EOF | sed -e 's/^/    /' | ||||
| add | ||||
| apply | ||||
| archimport | ||||
| bisect | ||||
| branch | ||||
| checkout | ||||
| cherry | ||||
| clone | ||||
| commit | ||||
| count-objects | ||||
| cvsimport | ||||
| diff | ||||
| fetch | ||||
| format-patch | ||||
| fsck-objects | ||||
| get-tar-commit-id | ||||
| init-db | ||||
| log | ||||
| ls-remote | ||||
| octopus | ||||
| pack-objects | ||||
| parse-remote | ||||
| patch-id | ||||
| prune | ||||
| pull | ||||
| push | ||||
| rebase | ||||
| relink | ||||
| rename | ||||
| repack | ||||
| request-pull | ||||
| reset | ||||
| resolve | ||||
| revert | ||||
| send-email | ||||
| shortlog | ||||
| show-branch | ||||
| status | ||||
| tag | ||||
| verify-tag | ||||
| whatchanged | ||||
| EOF | ||||
|  | @ -1,5 +1,5 @@ | |||
| # Pass --without docs to rpmbuild if you don't want the documentation | ||||
| Name: 		git-core | ||||
| Name: 		git | ||||
| Version: 	@@VERSION@@ | ||||
| Release: 	1%{?dist} | ||||
| Summary:  	Git core and tools | ||||
|  | @ -9,7 +9,7 @@ URL: 		http://kernel.org/pub/software/scm/git/ | |||
| Source: 	http://kernel.org/pub/software/scm/git/%{name}-%{version}.tar.gz | ||||
| BuildRequires:	zlib-devel >= 1.2, openssl-devel, curl-devel, expat-devel  %{!?_without_docs:, xmlto, asciidoc > 6.0.3} | ||||
| BuildRoot:	%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) | ||||
| Requires:	zlib >= 1.2, rsync, rcs, curl, less, openssh-clients, python >= 2.3, expat | ||||
| Requires:	git-core, git-svn, git-cvs, git-arch, git-email, gitk | ||||
|  | ||||
| %description | ||||
| This is a stupid (but extremely fast) directory content manager.  It | ||||
|  | @ -19,6 +19,22 @@ distributed source code management system. This package includes | |||
| rudimentary tools that can be used as a SCM, but you should look | ||||
| elsewhere for tools for ordinary humans layered on top of this. | ||||
|  | ||||
| This is a dummy package which brings in all subpackages. | ||||
|  | ||||
| %package core | ||||
| Summary:	Core git tools | ||||
| Group:		Development/Tools | ||||
| Requires:	zlib >= 1.2, rsync, rcs, curl, less, openssh-clients, python >= 2.3, expat | ||||
| %description core | ||||
| This is a stupid (but extremely fast) directory content manager.  It | ||||
| doesn't do a whole lot, but what it _does_ do is track directory | ||||
| contents efficiently. It is intended to be the base of an efficient, | ||||
| distributed source code management system. This package includes | ||||
| rudimentary tools that can be used as a SCM, but you should look | ||||
| elsewhere for tools for ordinary humans layered on top of this. | ||||
|  | ||||
| These are the core tools with minimal dependencies. | ||||
|  | ||||
| %package svn | ||||
| Summary:        Git tools for importing Subversion repositories | ||||
| Group:          Development/Tools | ||||
|  | @ -47,11 +63,11 @@ Requires:	git-core = %{version}-%{release} | |||
| %description email | ||||
| Git tools for sending email. | ||||
|  | ||||
| %package tk | ||||
| %package -n gitk | ||||
| Summary:        Git revision tree visualiser ('gitk') | ||||
| Group:          Development/Tools | ||||
| Requires:       git-core = %{version}-%{release}, tk >= 8.4 | ||||
| %description tk | ||||
| %description -n gitk | ||||
| Git revision tree visualiser ('gitk') | ||||
|  | ||||
| %prep | ||||
|  | @ -75,6 +91,9 @@ make %{_smp_mflags} DESTDIR=$RPM_BUILD_ROOT WITH_OWN_SUBPROCESS_PY=YesPlease WIT | |||
| %clean | ||||
| rm -rf $RPM_BUILD_ROOT | ||||
|  | ||||
| %files | ||||
| # These are no files in the root package | ||||
|  | ||||
| %files svn | ||||
| %defattr(-,root,root) | ||||
| %{_bindir}/*svn* | ||||
|  | @ -103,20 +122,25 @@ rm -rf $RPM_BUILD_ROOT | |||
| %{!?_without_docs: %{_mandir}/man1/*email*.1*} | ||||
| %{!?_without_docs: %doc Documentation/*email*.html } | ||||
|  | ||||
| %files tk | ||||
| %files -n gitk | ||||
| %defattr(-,root,root) | ||||
| %doc Documentation/*gitk*.txt | ||||
| %{_bindir}/*gitk* | ||||
| %{!?_without_docs: %{_mandir}/man1/*gitk*.1*} | ||||
| %{!?_without_docs: %doc Documentation/*gitk*.html } | ||||
|  | ||||
| %files -f bin-man-doc-files | ||||
| %files core -f bin-man-doc-files | ||||
| %defattr(-,root,root) | ||||
| %{_datadir}/git-core/ | ||||
| %doc README COPYING Documentation/*.txt | ||||
| %{!?_without_docs: %doc Documentation/*.html } | ||||
|  | ||||
| %changelog | ||||
| * Mon Nov 14 2005 H. Peter Anvin <hpa@zytor.com> 0.99.9j-1 | ||||
| - Change subpackage names to git-<name> instead of git-core-<name> | ||||
| - Create empty root package which brings in all subpackages | ||||
| - Rename git-tk -> gitk | ||||
|  | ||||
| * Thu Nov 10 2005 Chris Wright <chrisw@osdl.org> 0.99.9g-1 | ||||
| - zlib dependency fix | ||||
| - Minor cleanups from split | ||||
							
								
								
									
										16
									
								
								http-fetch.c
								
								
								
								
							
							
						
						
									
										16
									
								
								http-fetch.c
								
								
								
								
							|  | @ -425,6 +425,8 @@ static void start_request(struct transfer_request *request) | |||
| 	rename(request->tmpfile, prevfile); | ||||
| 	unlink(request->tmpfile); | ||||
|  | ||||
| 	if (request->local != -1) | ||||
| 		error("fd leakage in start: %d", request->local); | ||||
| 	request->local = open(request->tmpfile, | ||||
| 			      O_WRONLY | O_CREAT | O_EXCL, 0666); | ||||
| 	/* This could have failed due to the "lazy directory creation"; | ||||
|  | @ -523,7 +525,7 @@ static void start_request(struct transfer_request *request) | |||
| 	/* Try to get the request started, abort the request on error */ | ||||
| 	if (!start_active_slot(slot)) { | ||||
| 		request->state = ABORTED; | ||||
| 		close(request->local); | ||||
| 		close(request->local); request->local = -1; | ||||
| 		free(request->url); | ||||
| 		return; | ||||
| 	} | ||||
|  | @ -537,7 +539,7 @@ static void finish_request(struct transfer_request *request) | |||
| 	struct stat st; | ||||
|  | ||||
| 	fchmod(request->local, 0444); | ||||
| 	close(request->local); | ||||
| 	close(request->local); request->local = -1; | ||||
|  | ||||
| 	if (request->http_code == 416) { | ||||
| 		fprintf(stderr, "Warning: requested range invalid; we may already have all the data.\n"); | ||||
|  | @ -569,6 +571,8 @@ static void release_request(struct transfer_request *request) | |||
| { | ||||
| 	struct transfer_request *entry = request_queue_head; | ||||
|  | ||||
| 	if (request->local != -1) | ||||
| 		error("fd leakage in release: %d", request->local); | ||||
| 	if (request == request_queue_head) { | ||||
| 		request_queue_head = request->next; | ||||
| 	} else { | ||||
|  | @ -631,6 +635,8 @@ static void process_curl_messages(void) | |||
| 					if (request->repo->next != NULL) { | ||||
| 						request->repo = | ||||
| 							request->repo->next; | ||||
| 						close(request->local); | ||||
| 							request->local = -1; | ||||
| 						start_request(request); | ||||
| 					} else { | ||||
| 						finish_request(request); | ||||
|  | @ -763,6 +769,7 @@ static int fetch_index(struct alt_base *repo, unsigned char *sha1) | |||
| 				     curl_errorstr); | ||||
| 		} | ||||
| 	} else { | ||||
| 		fclose(indexfile); | ||||
| 		return error("Unable to start request"); | ||||
| 	} | ||||
|  | ||||
|  | @ -1083,6 +1090,7 @@ static int fetch_pack(struct alt_base *repo, unsigned char *sha1) | |||
| 				     curl_errorstr); | ||||
| 		} | ||||
| 	} else { | ||||
| 		fclose(packfile); | ||||
| 		return error("Unable to start request"); | ||||
| 	} | ||||
|  | ||||
|  | @ -1145,6 +1153,7 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1) | |||
| 			fetch_alternates(alt->base); | ||||
| 			if (request->repo->next != NULL) { | ||||
| 				request->repo = request->repo->next; | ||||
| 				close(request->local); request->local = -1; | ||||
| 				start_request(request); | ||||
| 			} | ||||
| 		} else { | ||||
|  | @ -1153,6 +1162,9 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1) | |||
| 		} | ||||
| #endif | ||||
| 	} | ||||
| 	if (request->local != -1) { | ||||
| 		close(request->local); request->local = -1; | ||||
| 	} | ||||
|  | ||||
| 	if (request->state == ABORTED) { | ||||
| 		release_request(request); | ||||
|  |  | |||
							
								
								
									
										64
									
								
								object.c
								
								
								
								
							
							
						
						
									
										64
									
								
								object.c
								
								
								
								
							|  | @ -67,40 +67,66 @@ void created_object(const unsigned char *sha1, struct object *obj) | |||
| 	nr_objs++; | ||||
| } | ||||
|  | ||||
| void add_ref(struct object *refer, struct object *target) | ||||
| struct object_refs *alloc_object_refs(unsigned count) | ||||
| { | ||||
| 	struct object_list **pp, *p; | ||||
| 	struct object_refs *refs; | ||||
| 	size_t size = sizeof(*refs) + count*sizeof(struct object *); | ||||
|  | ||||
| 	if (!track_object_refs) | ||||
| 	refs = xmalloc(size); | ||||
| 	memset(refs, 0, size); | ||||
| 	refs->count = count; | ||||
| 	return refs; | ||||
| } | ||||
|  | ||||
| static int compare_object_pointers(const void *a, const void *b) | ||||
| { | ||||
| 	const struct object * const *pa = a; | ||||
| 	const struct object * const *pb = b; | ||||
| 	return *pa - *pb; | ||||
| } | ||||
|  | ||||
| void set_object_refs(struct object *obj, struct object_refs *refs) | ||||
| { | ||||
| 	unsigned int i, j; | ||||
|  | ||||
| 	/* Do not install empty list of references */ | ||||
| 	if (refs->count < 1) { | ||||
| 		free(refs); | ||||
| 		return; | ||||
|  | ||||
| 	pp = &refer->refs; | ||||
| 	while ((p = *pp) != NULL) { | ||||
| 		if (p->item == target) | ||||
| 			return; | ||||
| 		pp = &p->next; | ||||
| 	} | ||||
|  | ||||
| 	target->used = 1; | ||||
| 	p = xmalloc(sizeof(*p)); | ||||
| 	p->item = target; | ||||
| 	p->next = NULL; | ||||
| 	*pp = p; | ||||
| 	/* Sort the list and filter out duplicates */ | ||||
| 	qsort(refs->ref, refs->count, sizeof(refs->ref[0]), | ||||
| 	      compare_object_pointers); | ||||
| 	for (i = j = 1; i < refs->count; i++) { | ||||
| 		if (refs->ref[i] != refs->ref[i - 1]) | ||||
| 			refs->ref[j++] = refs->ref[i]; | ||||
| 	} | ||||
| 	if (j < refs->count) { | ||||
| 		/* Duplicates were found - reallocate list */ | ||||
| 		size_t size = sizeof(*refs) + j*sizeof(struct object *); | ||||
| 		refs->count = j; | ||||
| 		refs = xrealloc(refs, size); | ||||
| 	} | ||||
|  | ||||
| 	for (i = 0; i < refs->count; i++) | ||||
| 		refs->ref[i]->used = 1; | ||||
| 	obj->refs = refs; | ||||
| } | ||||
|  | ||||
| void mark_reachable(struct object *obj, unsigned int mask) | ||||
| { | ||||
| 	struct object_list *p = obj->refs; | ||||
|  | ||||
| 	if (!track_object_refs) | ||||
| 		die("cannot do reachability with object refs turned off"); | ||||
| 	/* If we've been here already, don't bother */ | ||||
| 	if (obj->flags & mask) | ||||
| 		return; | ||||
| 	obj->flags |= mask; | ||||
| 	while (p) { | ||||
| 		mark_reachable(p->item, mask); | ||||
| 		p = p->next; | ||||
| 	if (obj->refs) { | ||||
| 		const struct object_refs *refs = obj->refs; | ||||
| 		unsigned i; | ||||
| 		for (i = 0; i < refs->count; i++) | ||||
| 			mark_reachable(refs->ref[i], mask); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  |  | |||
							
								
								
									
										10
									
								
								object.h
								
								
								
								
							
							
						
						
									
										10
									
								
								object.h
								
								
								
								
							|  | @ -7,13 +7,18 @@ struct object_list { | |||
| 	const char *name; | ||||
| }; | ||||
|  | ||||
| struct object_refs { | ||||
| 	unsigned count; | ||||
| 	struct object *ref[0]; | ||||
| }; | ||||
|  | ||||
| struct object { | ||||
| 	unsigned parsed : 1; | ||||
| 	unsigned used : 1; | ||||
| 	unsigned int flags; | ||||
| 	unsigned char sha1[20]; | ||||
| 	const char *type; | ||||
| 	struct object_list *refs; | ||||
| 	struct object_refs *refs; | ||||
| 	void *util; | ||||
| }; | ||||
|  | ||||
|  | @ -35,7 +40,8 @@ struct object *parse_object(const unsigned char *sha1); | |||
| /** Returns the object, with potentially excess memory allocated. **/ | ||||
| struct object *lookup_unknown_object(const unsigned  char *sha1); | ||||
|  | ||||
| void add_ref(struct object *refer, struct object *target); | ||||
| struct object_refs *alloc_object_refs(unsigned count); | ||||
| void set_object_refs(struct object *obj, struct object_refs *refs); | ||||
|  | ||||
| void mark_reachable(struct object *obj, unsigned int mask); | ||||
|  | ||||
|  |  | |||
|  | @ -127,38 +127,6 @@ inline struct llist_item * llist_insert_sorted_unique(struct llist *list, | |||
| 	return llist_insert_back(list, sha1); | ||||
| } | ||||
|  | ||||
| /* computes A\B */ | ||||
| void llist_sorted_difference_inplace(struct llist *A, | ||||
| 				     struct llist *B) | ||||
| { | ||||
| 	struct llist_item *prev, *a, *b, *x; | ||||
|  | ||||
| 	prev = a = A->front; | ||||
| 	b = B->front; | ||||
|  | ||||
| 	while (a != NULL && b != NULL) { | ||||
| 		int cmp = memcmp(a->sha1, b->sha1, 20); | ||||
| 		if (!cmp) { | ||||
| 			x = a; | ||||
| 			if (a == A->front) | ||||
| 				A->front = a->next; | ||||
| 			a = prev->next = a->next; | ||||
|  | ||||
| 			if (a == NULL) /* end of list */ | ||||
| 				A->back = prev; | ||||
| 			A->size--; | ||||
| 			free(x); | ||||
| 			b = b->next; | ||||
| 		} else | ||||
| 			if (cmp > 0) | ||||
| 				b = b->next; | ||||
| 			else { | ||||
| 				prev = a; | ||||
| 				a = a->next; | ||||
| 			} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* returns a pointer to an item in front of sha1 */ | ||||
| inline struct llist_item * llist_sorted_remove(struct llist *list, char *sha1, | ||||
| 					       struct llist_item *hint) | ||||
|  | @ -194,6 +162,21 @@ redo_from_start: | |||
| 	return prev; | ||||
| } | ||||
|  | ||||
| /* computes A\B */ | ||||
| void llist_sorted_difference_inplace(struct llist *A, | ||||
| 				     struct llist *B) | ||||
| { | ||||
| 	struct llist_item *hint, *b; | ||||
|  | ||||
| 	hint = NULL; | ||||
| 	b = B->front; | ||||
|  | ||||
| 	while (b) { | ||||
| 		hint = llist_sorted_remove(A, b->sha1, hint); | ||||
| 		b = b->next; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| inline struct pack_list * pack_list_insert(struct pack_list **pl, | ||||
| 					   struct pack_list *entry) | ||||
| { | ||||
|  |  | |||
							
								
								
									
										10
									
								
								refs.c
								
								
								
								
							
							
						
						
									
										10
									
								
								refs.c
								
								
								
								
							|  | @ -121,10 +121,12 @@ int create_symref(const char *git_HEAD, const char *refs_heads_master) | |||
| 	int fd, len, written; | ||||
|  | ||||
| #if USE_SYMLINK_HEAD | ||||
| 	unlink(git_HEAD); | ||||
| 	if (!symlink(refs_heads_master, git_HEAD)) | ||||
| 		return 0; | ||||
| 	fprintf(stderr, "no symlink - falling back to symbolic ref\n"); | ||||
| 	if (!only_use_symrefs) { | ||||
| 		unlink(git_HEAD); | ||||
| 		if (!symlink(refs_heads_master, git_HEAD)) | ||||
| 			return 0; | ||||
| 		fprintf(stderr, "no symlink - falling back to symbolic ref\n"); | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	len = snprintf(ref, sizeof(ref), "ref: %s\n", refs_heads_master); | ||||
|  |  | |||
|  | @ -424,7 +424,6 @@ static void find_pack_info_one(int pack_ix) | |||
| { | ||||
| 	unsigned char sha1[20]; | ||||
| 	struct object *o; | ||||
| 	struct object_list *ref; | ||||
| 	int i; | ||||
| 	struct packed_git *p = info[pack_ix]->p; | ||||
| 	int num = num_packed_objects(p); | ||||
|  | @ -437,8 +436,12 @@ static void find_pack_info_one(int pack_ix) | |||
| 			die("corrupt pack file %s?", p->pack_name); | ||||
| 		if ((o = lookup_object(sha1)) == NULL) | ||||
| 			die("cannot parse %s", sha1_to_hex(sha1)); | ||||
| 		for (ref = o->refs; ref; ref = ref->next) | ||||
| 			ref->item->flags = 0; | ||||
| 		if (o->refs) { | ||||
| 			struct object_refs *refs = o->refs; | ||||
| 			int j; | ||||
| 			for (j = 0; j < refs->count; j++) | ||||
| 				refs->ref[j]->flags = 0; | ||||
| 		} | ||||
| 		o->flags = 0; | ||||
| 	} | ||||
|  | ||||
|  | @ -448,8 +451,12 @@ static void find_pack_info_one(int pack_ix) | |||
| 			die("corrupt pack file %s?", p->pack_name); | ||||
| 		if ((o = lookup_object(sha1)) == NULL) | ||||
| 			die("cannot find %s", sha1_to_hex(sha1)); | ||||
| 		for (ref = o->refs; ref; ref = ref->next) | ||||
| 			ref->item->flags |= REFERENCED; | ||||
| 		if (o->refs) { | ||||
| 			struct object_refs *refs = o->refs; | ||||
| 			int j; | ||||
| 			for (j = 0; j < refs->count; j++) | ||||
| 				refs->ref[j]->flags |= REFERENCED; | ||||
| 		} | ||||
| 		o->flags |= INTERNAL; | ||||
| 	} | ||||
|  | ||||
|  | @ -460,8 +467,12 @@ static void find_pack_info_one(int pack_ix) | |||
| 			die("cannot find %s", sha1_to_hex(sha1)); | ||||
|  | ||||
| 		show(o, pack_ix); | ||||
| 		for (ref = o->refs; ref; ref = ref->next) | ||||
| 			show(ref->item, pack_ix); | ||||
| 		if (o->refs) { | ||||
| 			struct object_refs *refs = o->refs; | ||||
| 			int j; | ||||
| 			for (j = 0; j < refs->count; j++) | ||||
| 				show(refs->ref[j], pack_ix); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  |  | |||
|  | @ -424,7 +424,7 @@ struct packed_git *add_packed_git(char *path, int path_len, int local) | |||
| 	struct packed_git *p; | ||||
| 	unsigned long idx_size; | ||||
| 	void *idx_map; | ||||
| 	char sha1[20]; | ||||
| 	unsigned char sha1[20]; | ||||
|  | ||||
| 	if (check_packed_git_idx(path, &idx_size, &idx_map)) | ||||
| 		return NULL; | ||||
|  |  | |||
|  | @ -20,6 +20,7 @@ static void check_symref(const char *HEAD) | |||
| int main(int argc, const char **argv) | ||||
| { | ||||
| 	setup_git_directory(); | ||||
| 	git_config(git_default_config); | ||||
| 	switch (argc) { | ||||
| 	case 2: | ||||
| 		check_symref(argv[1]); | ||||
|  |  | |||
|  | @ -0,0 +1,115 @@ | |||
| #!/bin/sh | ||||
| # | ||||
| # Copyright (c) 2005 Junio C Hamano | ||||
| # | ||||
|  | ||||
| test_description='git-apply handling binary patches | ||||
|  | ||||
| ' | ||||
| . ./test-lib.sh | ||||
|  | ||||
| # setup | ||||
|  | ||||
| cat >file1 <<EOF | ||||
| A quick brown fox jumps over the lazy dog. | ||||
| A tiny little penguin runs around in circles. | ||||
| There is a flag with Linux written on it. | ||||
| A slow black-and-white panda just sits there, | ||||
| munching on his bamboo. | ||||
| EOF | ||||
| cat file1 >file2 | ||||
| cat file1 >file4 | ||||
|  | ||||
| git-update-index --add --remove file1 file2 file4 | ||||
| git-commit -m 'Initial Version' 2>/dev/null | ||||
|  | ||||
| git-checkout -b binary | ||||
| tr 'x' '\0' <file1 >file3 | ||||
| cat file3 >file4 | ||||
| git-add file2 | ||||
| tr '\0' 'v' <file3 >file1 | ||||
| rm -f file2 | ||||
| git-update-index --add --remove file1 file2 file3 file4 | ||||
| git-commit -m 'Second Version' | ||||
|  | ||||
| git-diff-tree -p master binary >B.diff | ||||
| git-diff-tree -p -C master binary >C.diff | ||||
|  | ||||
| git-diff-tree -p --full-index master binary >BF.diff | ||||
| git-diff-tree -p --full-index -C master binary >CF.diff | ||||
|  | ||||
| test_expect_success 'stat binary diff -- should not fail.' \ | ||||
| 	'git-checkout master | ||||
| 	 git-apply --stat --summary B.diff' | ||||
|  | ||||
| test_expect_success 'stat binary diff (copy) -- should not fail.' \ | ||||
| 	'git-checkout master | ||||
| 	 git-apply --stat --summary C.diff' | ||||
|  | ||||
| test_expect_failure 'check binary diff -- should fail.' \ | ||||
| 	'git-checkout master | ||||
| 	 git-apply --check B.diff' | ||||
|  | ||||
| test_expect_failure 'check binary diff (copy) -- should fail.' \ | ||||
| 	'git-checkout master | ||||
| 	 git-apply --check C.diff' | ||||
|  | ||||
| test_expect_failure 'check incomplete binary diff with replacement -- should fail.' \ | ||||
| 	'git-checkout master | ||||
| 	 git-apply --check --allow-binary-replacement B.diff' | ||||
|  | ||||
| test_expect_failure 'check incomplete binary diff with replacement (copy) -- should fail.' \ | ||||
| 	'git-checkout master | ||||
| 	 git-apply --check --allow-binary-replacement C.diff' | ||||
|  | ||||
| test_expect_success 'check binary diff with replacement.' \ | ||||
| 	'git-checkout master | ||||
| 	 git-apply --check --allow-binary-replacement BF.diff' | ||||
|  | ||||
| test_expect_success 'check binary diff with replacement (copy).' \ | ||||
| 	'git-checkout master | ||||
| 	 git-apply --check --allow-binary-replacement CF.diff' | ||||
|  | ||||
| # Now we start applying them. | ||||
|  | ||||
| do_reset () { | ||||
| 	rm -f file? | ||||
| 	git-reset --hard | ||||
| 	git-checkout -f master | ||||
| } | ||||
|  | ||||
| test_expect_failure 'apply binary diff -- should fail.' \ | ||||
| 	'do_reset | ||||
| 	 git-apply B.diff' | ||||
|  | ||||
| test_expect_failure 'apply binary diff -- should fail.' \ | ||||
| 	'do_reset | ||||
| 	 git-apply --index B.diff' | ||||
|  | ||||
| test_expect_failure 'apply binary diff (copy) -- should fail.' \ | ||||
| 	'do_reset | ||||
| 	 git-apply C.diff' | ||||
|  | ||||
| test_expect_failure 'apply binary diff (copy) -- should fail.' \ | ||||
| 	'do_reset | ||||
| 	 git-apply --index C.diff' | ||||
|  | ||||
| test_expect_failure 'apply binary diff without replacement -- should fail.' \ | ||||
| 	'do_reset | ||||
| 	 git-apply BF.diff' | ||||
|  | ||||
| test_expect_failure 'apply binary diff without replacement (copy) -- should fail.' \ | ||||
| 	'do_reset | ||||
| 	 git-apply CF.diff' | ||||
|  | ||||
| test_expect_success 'apply binary diff.' \ | ||||
| 	'do_reset | ||||
| 	 git-apply --allow-binary-replacement --index BF.diff && | ||||
| 	 test -z "$(git-diff --name-status binary)"' | ||||
|  | ||||
| test_expect_success 'apply binary diff (copy).' \ | ||||
| 	'do_reset | ||||
| 	 git-apply --allow-binary-replacement --index CF.diff && | ||||
| 	 test -z "$(git-diff --name-status binary)"' | ||||
|  | ||||
| test_done | ||||
|  | @ -158,6 +158,8 @@ test_done () { | |||
| # Test the binaries we have just built.  The tests are kept in | ||||
| # t/ subdirectory and are run in trash subdirectory. | ||||
| PATH=$(pwd)/..:$PATH | ||||
| GIT_EXEC_PATH=$(pwd)/.. | ||||
| export GIT_EXEC_PATH | ||||
|  | ||||
| # Test repository | ||||
| test=trash | ||||
|  |  | |||
							
								
								
									
										7
									
								
								tag.c
								
								
								
								
							
							
						
						
									
										7
									
								
								tag.c
								
								
								
								
							|  | @ -75,8 +75,11 @@ int parse_tag_buffer(struct tag *item, void *data, unsigned long size) | |||
| 	item->tag[taglen] = '\0'; | ||||
|  | ||||
| 	item->tagged = lookup_object_type(object, type); | ||||
| 	if (item->tagged) | ||||
| 		add_ref(&item->object, item->tagged); | ||||
| 	if (item->tagged && track_object_refs) { | ||||
| 		struct object_refs *refs = alloc_object_refs(1); | ||||
| 		refs->ref[0] = item->tagged; | ||||
| 		set_object_refs(&item->object, refs); | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  |  | |||
							
								
								
									
										13
									
								
								tree.c
								
								
								
								
							
							
						
						
									
										13
									
								
								tree.c
								
								
								
								
							|  | @ -148,6 +148,7 @@ int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size) | |||
| { | ||||
| 	void *bufptr = buffer; | ||||
| 	struct tree_entry_list **list_p; | ||||
| 	int n_refs = 0; | ||||
|  | ||||
| 	if (item->object.parsed) | ||||
| 		return 0; | ||||
|  | @ -184,11 +185,21 @@ int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size) | |||
| 			obj = &entry->item.blob->object; | ||||
| 		} | ||||
| 		if (obj) | ||||
| 			add_ref(&item->object, obj); | ||||
| 			n_refs++; | ||||
| 		entry->parent = NULL; /* needs to be filled by the user */ | ||||
| 		*list_p = entry; | ||||
| 		list_p = &entry->next; | ||||
| 	} | ||||
|  | ||||
| 	if (track_object_refs) { | ||||
| 		struct tree_entry_list *entry; | ||||
| 		unsigned i = 0; | ||||
| 		struct object_refs *refs = alloc_object_refs(n_refs); | ||||
| 		for (entry = item->entries; entry; entry = entry->next) | ||||
| 			refs->ref[i++] = entry->item.any; | ||||
| 		set_object_refs(&item->object, refs); | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Junio C Hamano
						Junio C Hamano