Git development
 help / color / mirror / Atom feed
* [PATCH 3/3] git --help COMMAND brings up the git-COMMAND man-page., take two
From: Andreas Ericsson @ 2005-11-16  0:23 UTC (permalink / raw)
  To: git


It's by design a bit stupid (matching ^git rather than ^git-), so as
to work with 'gitk' and 'git' as well.

Signed-off-by: Andreas Ericsson <ae@op5.se>

---

 Documentation/git.txt |    2 ++
 git.c                 |   26 ++++++++++++++++++++++++--
 2 files changed, 26 insertions(+), 2 deletions(-)

applies-to: 8a47ae8a825ab0e68ac46392bccd1ec16df39456
53e2024f89514d31a45936e3596e3d285dfd1bfe
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 91e9f9f..7cbfaf8 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -24,6 +24,8 @@ OPTIONS
 
 --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.
diff --git a/git.c b/git.c
index d189801..4b7cbf6 100644
--- a/git.c
+++ b/git.c
@@ -160,6 +160,24 @@ static void prepend_to_path(const char *
 	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];
@@ -199,8 +217,12 @@ int main(int argc, char **argv, char **e
 			usage(NULL, NULL);
 	}
 
-	if (i >= argc || show_help)
-		usage(exec_path, NULL);
+	if (i >= argc || show_help) {
+		if (i >= argc)
+			usage(exec_path, NULL);
+
+		show_man_page(argv[i]);
+	}
 
 	/* allow relative paths, but run with exact */
 	if (chdir(exec_path)) {
---
0.99.9.GIT

^ permalink raw reply related

* Re: [PATCH 1/3] C implementation of the 'git' program, take two.
From: Linus Torvalds @ 2005-11-16  0:18 UTC (permalink / raw)
  To: Andreas Ericsson; +Cc: git
In-Reply-To: <20051115233125.3153B5BF76@nox.op5.se>



On Wed, 16 Nov 2005, Andreas Ericsson wrote:
> +
> +	/* allow relative paths, but run with exact */
> +	if (chdir(exec_path)) {
> +		printf("git: '%s': %s\n", exec_path, strerror(errno));
> +		exit (1);
> +	}
> +
> +	getcwd(git_command, sizeof(git_command));
> +	chdir(wd);

Argh. This is pretty horrible way to turn a path into an absolute one. 
Especially since you didn't even test whether the original "wd" was 
successful.

Why don't you just do

	if (exec_path[0] != '/') {
		.. prepend "cwd/" to exec_path ..

since as far as I can tell you don't actually care whether it's a 
simplified path or not (you can remove "./" at the beginning just to make 
it cleaner, if you wish. In fact, you can remove "../" at the beginning 
too (but only the beginning) since getcwd() shouldn't have any symlink 
components).

The reason to avoid "chdir(relative) + chdir(back)" is that it totally 
unnecessarily breaks under some extreme cases. For example, if the 
exec_path is already absolute, and we just happen to be in a really deep 
subdirectory, then the getcwd() could have failed due to the PATH_MAX 
limitations.

Also, depending on getcwd() will not work if any parent directory is 
unreadable or non-executable (well, under Linux it will, as long as it's 
executable, since getcwd() is actually a system call. Not in UNIX in 
general, though). Again, that means that unless you _have_ to know what 
the cwd is, you should try to avoid relying on it.

Now, there are Linux-specific tricks that can avoid some of the problems 
if you want to, but they are very much hacks:

	if (filename[0] != '/') {
		fd = open(filename, O_DIRECTORY);
		if (fd >= 0) {
			snprintf(link_name, sizeof(link_name), "/proc/self/fd/%d", fd);
			if (!readlink(link_name ...)) {
				.. there it is ..
			}
			close(fd);
		}
	..

and the nicer thign to do is to just not try to be clever.

		Linus

^ permalink raw reply

* Re: [PATCH 1/3] C implementation of the 'git' program, take two.
From: Junio C Hamano @ 2005-11-16  0:17 UTC (permalink / raw)
  To: Andreas Ericsson; +Cc: git
In-Reply-To: <437A78FC.10608@op5.se>

Andreas Ericsson <ae@op5.se> writes:

> Dunno, really. I suppose it does as it bypasses the shell with the 
> execve() call, unless windows or the cygwin stuff does some trickery to 
> find an .exe regardless.
>
> Is it ok if I send a separate patch for it, or would you rather have me 
> redo this one?

I'll take this as is and have Cygwin folks holler if it breaks
things for them ;-).  Thanks.

^ permalink raw reply

* Re: [PATCH 1/3] C implementation of the 'git' program, take two.
From: Andreas Ericsson @ 2005-11-16  0:10 UTC (permalink / raw)
  To: git
In-Reply-To: <7vwtj9eaqm.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano wrote:
> exon@op5.se (Andreas Ericsson) writes:
> 
> 
>>This patch provides a C implementation of the 'git' program and
>>introduces support for putting the git-* commands in a directory
>>of their own.
> 
> 
> Very nice, thanks.  Two questions and a half.
> 
> 
>>+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 = "/bin:/usr/bin:.";
> 
> 
> This is to cover strange case and probably would not matter in
> practice, but perhaps without current directory?
> 

I have no preference really and since it already covers a strange case 
it probably shouldn't matter either way.

> 
>>+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);
>>+...
>>+	/* allow relative paths, but run with exact */
>>+	if (chdir(exec_path)) {
>>+		printf("git: '%s': %s\n", exec_path, strerror(errno));
>>+		exit (1);
>>+	}
>>+
>>+	getcwd(git_command, sizeof(git_command));
>>+	chdir(wd);
> 
> 
> Can we always come back from where we started?
> 

Not sure what you mean. Perhaps "Come back *to* where we started"?

If getcwd(wd, sizeof(wd)) fails then chdir(wd) will also fail (or do 
something strange, at least). wd is otherwise absolute.

> 
>>+
>>+	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);
> 
> 
> Shell version for Cygwin seems to do ".exe" at the end --- does
> it matter?
> 

Dunno, really. I suppose it does as it bypasses the shell with the 
execve() call, unless windows or the cygwin stuff does some trickery to 
find an .exe regardless.

Is it ok if I send a separate patch for it, or would you rather have me 
redo this one?

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

^ permalink raw reply

* Re: fix git-pack-redundant crashing sometimes
From: Linus Torvalds @ 2005-11-15 23:58 UTC (permalink / raw)
  To: Alex Riesen; +Cc: Lukas Sandström, git, junkio
In-Reply-To: <20051115223340.GA3951@steel.home>



On Tue, 15 Nov 2005, Alex Riesen wrote:
> 
> Sorry, it doesn't. The code loops here:
> 
> 401             /* find the permutations which contain all missing objects */
> 402             perm_all = perm = get_all_permutations(non_unique);

Looks like the whole thing is exponential.

A good way to do sane pack handling is to keep a _sorted_ list of all 
objects each pack has. At that point it becomes much easier to see which 
objects only exist in one particular pack.

The sorting itself is O(nlogn), and the "does this pack have any unique 
objects" (or "is this pack a superset of all other packs") question should 
then be O(n).

This is how the packs are generated in the first place - by sorting the 
objects and limiting the diff generation to the "neighbors" of the 
objects, you can generate pack-files in O(n logn) rather than O(n**2). 
Which is pretty important when there are currently 140,000+ objects in the 
kernel tree.

		Linus

^ permalink raw reply

* Re: [ANNOUNCE] GIT 0.99.9i aka 1.0rc2
From: walt @ 2005-11-15 23:48 UTC (permalink / raw)
  To: git; +Cc: linux-kernel
In-Reply-To: <Pine.LNX.4.64.0511150715390.17817@x2.ybpnyarg>

On Tue, 15 Nov 2005, walt wrote:

> On Mon, 14 Nov 2005, Junio C Hamano wrote:
>
> > I think the source-tree-wise almost everything is done except:
> >  - http-fetch file descriptor leak fix...

> So, you're saying that you have *not* fixed it?...

I just confirmed the good news on NetBSD.  Out of curiosity I did
this test:  I cg-updated and reinstalled cogito, which did *not*
fix the too-many-open-files error.  Then I cg-updated and rebuilt
git which *did* fix the error.  Clearly, something you committed
in the last two days has fixed this problem.  Dunno what you did,
but thanks :o)

^ permalink raw reply

* Re: [PATCH 3/3] git --help COMMAND brings up the git-COMMAND man-page.
From: Junio C Hamano @ 2005-11-15 23:49 UTC (permalink / raw)
  To: Andreas Ericsson; +Cc: git
In-Reply-To: <20051115233125.2C0355BF73@nox.op5.se>

exon@op5.se (Andreas Ericsson) writes:

> It's by design a bit stupid (matching ^git rather than ^git-), so as
> to work with 'gitk' and 'git' as well.
>
> Signed-off-by: Andreas Ericsson <ae@op5.se>

Thanks, stupid is fine.

> +/* has anyone seen 'man' installed anywhere else than in /usr/bin? */
> +#define PATH_TO_MAN "/usr/bin/man"
> +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(PATH_TO_MAN, "man", page, NULL);
> +}

If you do PATH_TO_MAN absolute, execl would suffice, but just
saying "man" and have execlp look for it would be easier to
manage.

^ permalink raw reply

* Re: [PATCH 1/3] C implementation of the 'git' program, take two.
From: Junio C Hamano @ 2005-11-15 23:45 UTC (permalink / raw)
  To: Andreas Ericsson; +Cc: git
In-Reply-To: <20051115233125.3153B5BF76@nox.op5.se>

exon@op5.se (Andreas Ericsson) writes:

> This patch provides a C implementation of the 'git' program and
> introduces support for putting the git-* commands in a directory
> of their own.

Very nice, thanks.  Two questions and a half.

> +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 = "/bin:/usr/bin:.";

This is to cover strange case and probably would not matter in
practice, but perhaps without current directory?

> +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);
> +...
> +	/* allow relative paths, but run with exact */
> +	if (chdir(exec_path)) {
> +		printf("git: '%s': %s\n", exec_path, strerror(errno));
> +		exit (1);
> +	}
> +
> +	getcwd(git_command, sizeof(git_command));
> +	chdir(wd);

Can we always come back from where we started?

> +
> +	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);

Shell version for Cygwin seems to do ".exe" at the end --- does
it matter?

^ permalink raw reply

* [PATCH 0/3] C implementation of git, take two.
From: Andreas Ericsson @ 2005-11-15 23:40 UTC (permalink / raw)
  To: Git Mailing List

The commit-messages says it all really, but in case anyone doesn't want 
to read near-identical code to find out what's different between take 
two and take one, I'll just list it briefly here.

* Renamed "git --lib" and $GIT_LIB to "git --exec-path" and 
$GIT_EXEC_PATH, respectively, as per Junio's decision.

* Implemented Linus' idea of prepending exec-path to $PATH.

* "git --help diff-index" brings up the git-diff-index(1) man-page 
(patch 3/3), as does "git --help git-diff-index".

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

^ permalink raw reply

* [PATCH 4/4] rebase: make it usable for binary files as well.
From: Junio C Hamano @ 2005-11-15 23:34 UTC (permalink / raw)
  To: git
In-Reply-To: <7voe4lfpxm.fsf@assigned-by-dhcp.cox.net>

Use git-format-patch --full-index to generate a patch, and feed
that to git-am that uses git-apply --allow-binary-replacement.
This way, rebase can be used to move development that contains
binary files as long as there is no need for file-level merges.

Signed-off-by: Junio C Hamano <junkio@cox.net>

---

 git-am.sh     |    7 ++++---
 git-rebase.sh |    2 +-
 2 files changed, 5 insertions(+), 4 deletions(-)

applies-to: 349326f3647597dabf38d82e1c2806cef45060f7
7f5bff7c3e5b1245e479fc13665641424dee9a41
diff --git a/git-am.sh b/git-am.sh
index 38841d9..8307d77 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -46,7 +46,7 @@ fall_back_3way () {
 	    cd "$dotest/patch-merge-tmp-dir" &&
 	    GIT_INDEX_FILE="../patch-merge-tmp-index" \
 	    GIT_OBJECT_DIRECTORY="$O_OBJECT" \
-	    git-apply --index <../patch
+	    git-apply --allow-binary-replacement --index <../patch
         )
     then
 	echo Using index info to reconstruct a base tree...
@@ -77,7 +77,7 @@ fall_back_3way () {
 		GIT_OBJECT_DIRECTORY="$O_OBJECT" &&
 		export GIT_INDEX_FILE GIT_OBJECT_DIRECTORY &&
 		git-read-tree "$base" &&
-		git-apply --index &&
+		git-apply --index --allow-binary-replacement &&
 		mv ../patch-merge-tmp-index ../patch-merge-index &&
 		echo "$base" >../patch-merge-base
 	    ) <"$dotest/patch"  2>/dev/null && break
@@ -310,7 +310,8 @@ do
 	echo "Applying '$SUBJECT'"
 	echo
 
-	git-apply --index "$dotest/patch"; apply_status=$?
+	git-apply --allow-binary-replacement --index "$dotest/patch"
+	apply_status=$?
 	if test $apply_status = 1 && test "$threeway" = t
 	then
 		if (fall_back_3way)
diff --git a/git-rebase.sh b/git-rebase.sh
index 56196e7..b8abf33 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -25,4 +25,4 @@ esac
 
 # Rewind the head to "$other"
 git-reset --hard "$other"
-git-format-patch -k --stdout "$other" ORIG_HEAD | git am -3 -k
+git-format-patch -k --stdout --full-index "$other" ORIG_HEAD | git am -3 -k
---
0.99.9.GIT

^ permalink raw reply related

* [PATCH 3/4] diff: --full-index
From: Junio C Hamano @ 2005-11-15 23:34 UTC (permalink / raw)
  To: git
In-Reply-To: <7voe4lfpxm.fsf@assigned-by-dhcp.cox.net>

A new option, --full-index, is introduced to diff family.  This
causes the full object name of pre- and post-images to appear on
the index line of patch formatted output, to be used in
conjunction with --allow-binary-replacement option of git-apply.

Signed-off-by: Junio C Hamano <junkio@cox.net>

---

 Documentation/diff-options.txt |    5 +++++
 diff.c                         |   14 ++++++++------
 diff.h                         |    4 +++-
 3 files changed, 16 insertions(+), 7 deletions(-)

applies-to: 87c089ccd1a4e2ea6284c1ac5e944efd5299f60e
3c38f257b87e61f02e8bf49195eb5084652ff0f9
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index 8eef86e..6b496ed 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -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.
 
diff --git a/diff.c b/diff.c
index ec94a96..8b7bb67 100644
--- a/diff.c
+++ b/diff.c
@@ -648,7 +648,7 @@ static void diff_fill_sha1_info(struct d
 		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 +711,11 @@ static void run_diff(struct diff_filepai
 
 	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);
@@ -789,6 +789,8 @@ int diff_opt_parse(struct diff_options *
 		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 +1019,7 @@ int diff_unmodified_pair(struct diff_fil
 	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 +1028,7 @@ static void diff_flush_patch(struct diff
 	    (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 +1160,7 @@ void diff_flush(struct diff_options *opt
 			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:
diff --git a/diff.h b/diff.h
index 1259079..9b2e1e6 100644
--- a/diff.h
+++ b/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(stru
 "  -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" \
---
0.99.9.GIT

^ permalink raw reply related

* [PATCH 2/4] apply: allow-binary-replacement.
From: Junio C Hamano @ 2005-11-15 23:33 UTC (permalink / raw)
  To: git
In-Reply-To: <7voe4lfpxm.fsf@assigned-by-dhcp.cox.net>

A new option, --allow-binary-replacement, is introduced.

When you feed a diff that records full SHA1 name of pre- and
post-image blob on its index line to git-apply with this option,
the post-image blob replaces the path if what you have in the
working tree matches the pre-image _and_ post-image blob is
already available in the object directory.

Later we _might_ want to enhance the diff output to also include
the full binary data of the post-image, to make this more
useful, but this is good enough for local rebasing application.

Signed-off-by: Junio C Hamano <junkio@cox.net>

---

 Documentation/git-apply.txt |   13 +++++++-
 apply.c                     |   72 +++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 81 insertions(+), 4 deletions(-)

applies-to: 4567363448244862ec2c6c8bd74fc09cd322f153
0d534967c6850288e1a36eae364da700348a77fe
diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt
index 6702a18..626e281 100644
--- a/Documentation/git-apply.txt
+++ b/Documentation/git-apply.txt
@@ -8,7 +8,7 @@ git-apply - Apply patch on a git index f
 
 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>
diff --git a/apply.c b/apply.c
index 590adc6..cb9a6c0 100644
--- a/apply.c
+++ b/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
@@ -899,8 +900,12 @@ static int parse_chunk(char *buffer, uns
 			    sizeof(binhdr)-1))
 			patch->is_binary = 1;
 
-		if (patch->is_binary && !apply && !check)
-			;
+		if (patch->is_binary) {
+			if ((!apply && !check) || allow_binary_replacement)
+				;
+			else
+				die("binary patch at line %d; you might want to try --allow-binary-replacement?", linenr);
+		}
 		else
 			die("patch with only garbage at line %d", linenr);
 	}
@@ -1156,6 +1161,63 @@ static int apply_fragments(struct buffer
 {
 	struct fragment *frag = patch->fragments;
 
+	if (patch->is_binary) {
+		unsigned char sha1[20];
+		const char *name = patch->old_name ? patch->old_name : patch->new_name;
+
+		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);
@@ -1723,6 +1785,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;
---
0.99.9.GIT

^ permalink raw reply related

* [PATCH 1/4] Rewrite rebase to use git-format-patch piped to git-am.
From: Junio C Hamano @ 2005-11-15 23:33 UTC (permalink / raw)
  To: git
In-Reply-To: <7voe4lfpxm.fsf@assigned-by-dhcp.cox.net>

This does not handle binary files yet, but a patch or two to
git-apply should solve that problem.

Signed-off-by: Junio C Hamano <junkio@cox.net>

---

 git-rebase.sh |   71 ++++++++++++---------------------------------------------
 1 files changed, 15 insertions(+), 56 deletions(-)

applies-to: efad0bc70473bdc02b8ac6a5e5f001519f1d5dfa
d64a7b926edfcebf9f5b116fedebd365e5c206f1
diff --git a/git-rebase.sh b/git-rebase.sh
index fa95009..56196e7 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -5,65 +5,24 @@
 
 . git-sh-setup || die "Not a git archive."
 
-usage="usage: $0 "'<upstream> [<head>]
-
-Uses output from git-cherry to rebase local commits to the new head of
-upstream tree.'
-
-case "$#,$1" in
-1,*..*)
-    upstream=$(expr "$1" : '\(.*\)\.\.') ours=$(expr "$1" : '.*\.\.\(.*\)$')
-    set x "$upstream" "$ours"
-    shift ;;
-esac
+# The other head is given
+other=$(git-rev-parse --verify "$1^0") || exit
 
+# The tree must be really really clean.
 git-update-index --refresh || exit
+diff=$(git-diff-index --cached --name-status -r HEAD)
+case "$different" in
+?*)	echo "$diff"
+	exit 1
+	;;
+esac
 
+# If the branch to rebase is given, first switch to it.
 case "$#" in
-1) ours_symbolic=HEAD ;;
-2) ours_symbolic="$2" ;;
-*) die "$usage" ;;
+2)
+	git-checkout "$2" || exit
 esac
 
-upstream=`git-rev-parse --verify "$1"` &&
-ours=`git-rev-parse --verify "$ours_symbolic"` || exit
-different1=$(git-diff-index --name-only --cached "$ours") &&
-different2=$(git-diff-index --name-only "$ours") &&
-test "$different1$different2" = "" ||
-die "Your working tree does not match $ours_symbolic."
-
-git-read-tree -m -u $ours $upstream &&
-new_head=$(git-rev-parse --verify "$upstream^0") &&
-git-update-ref HEAD "$new_head" || exit
-
-tmp=.rebase-tmp$$
-fail=$tmp-fail
-trap "rm -rf $tmp-*" 1 2 3 15
-
->$fail
-
-git-cherry -v $upstream $ours |
-while read sign commit msg
-do
-	case "$sign" in
-	-)
-		echo >&2 "* Already applied: $msg"
-		continue ;;
-	esac
-	echo >&2 "* Applying: $msg"
-	S=$(git-rev-parse --verify HEAD) &&
-	git-cherry-pick --replay $commit || {
-		echo >&2 "* Not applying the patch and continuing."
-		echo $commit >>$fail
-		git-reset --hard $S
-	}
-done
-if test -s $fail
-then
-	echo >&2 Some commits could not be rebased, check by hand:
-	cat >&2 $fail
-	echo >&2 "(the same list of commits are found in $tmp)"
-	exit 1
-else
-	rm -f $fail
-fi
+# Rewind the head to "$other"
+git-reset --hard "$other"
+git-format-patch -k --stdout "$other" ORIG_HEAD | git am -3 -k
---
0.99.9.GIT

^ permalink raw reply related

* [PATCH 0/4] reworking git-rebase
From: Junio C Hamano @ 2005-11-15 23:32 UTC (permalink / raw)
  To: git

The current rebase implementation finds commits in our tree but
not in the upstream tree using git-cherry, and tries to apply
them using git-cherry-pick (i.e. always use 3-way) one by one.

Which is fine, but when some of the changes do not apply
cleanly, it punts, and punts badly.

Suppose you have commits A-B-C-D-E since you forked from the
upstream and submitted the changes for inclusion.  You fetch
from upstream head U and find that B has been picked up.  You
run git-rebase to update your branch, which tries to apply
changes contained in A-C-D-E, in this order, but replaying of C
fails, because the upstream got changes that touch the same area
from elsewhere.

Now what?

It notes that fact, and goes ahead to apply D and E, and at the
very end tells you to deal with C by hand.  Even if you somehow
managed to replay C on top of the result, you would now end up
with ...-B-...-U-A-D-E-C.

Breaking the order between B and others was the conscious
decision made by the upstream, so we would not worry about it,
and even if it were worrisome, it is too late for us to fix now.
What D and E do may well depend on having C applied before them,
which is a problem for us.

Here is a series requesting comments and testing.  I think this
change makes rebase easier to use when some of the changes do
not replay cleanly.  What it does is:

 - Instead of calling git-cherry-pick, it runs git-format-patch
   on the unmerged commits git-cherry found, and feeds the
   result to "git-am --3way".

 - To keep rebase working on a repository that manages binary
   files, it adds a very limited support to handle "binary
   diffs".

In the "unapplicable patch in the middle" case, this "rebase"
works like this:

 - A series of patches in e-mail form is created that records
   what A-C-D-E do, and is fed to git-am.  This is stored in
   .dotest/ directory, just like the case you tried to apply
   them from your mailbox.  Your branch is rewound to the tip of
   upstream U, and the original head is kept in .git/ORIG_HEAD,
   so you could "git reset --hard ORIG_HEAD" in case the end
   result is really messy.

 - Patch A applies cleanly.  This could either be a clean patch
   application on top of rewound head (i.e. same as upstream
   head), or git-am might have internally fell back on 3-way
   (i.e.  it would have done the same thing as git-cherry-pick).
   In either case, a rebased commit A is made on top of U.

 - Patch C does not apply.  git-am stops here, with conflicts to
   be resolved in the working tree.  Yet-to-be-applied D and E
   are still kept in .dotest/ directory at this point.  What the
   user does is exactly the same as fixing up unapplicable patch
   when running git-am:

   - Resolve conflict just like any merge conflicts. 

   - "git diff -p --full-index HEAD >.dotest/patch" to pretend
     as if you received a perfect, applicable patch.

   - "git reset --hard", to pretend you have not tried to apply
     that patch yet.

   [Side note] I think the latter two steps can and should be
   made into a short-hand to tell "git-am" that the conflicting
   patch is resolved.  "git-am --resolved", perhaps?

 - Continue with "git am --3way".  This applies the fixed-up
   patch so by definition it had better apply.  "git am" knows
   the patch after the fixed-up one is D and then E; it applies
   them, and you will get the changes from A-C-D-E commits on
   top of U, in this order.

I've been using this without noticing any problem, and as people
may know I do a lot of rebases.

^ permalink raw reply

* [PATCH 1/3] C implementation of the 'git' program, take two.
From: Andreas Ericsson @ 2005-11-15 23:31 UTC (permalink / raw)
  To: git


This patch provides a C implementation of the 'git' program and
introduces support for putting the git-* commands in a directory
of their own. It also saves some time on executing those commands
in a tight loop and it prints the currently available git commands
in a nicely formatted list.

The location of the GIT_EXEC_PATH (name discussion's closed, thank gods)
can be obtained by running

	git --exec-path

which will hopefully give porcelainistas ample time to adapt their
heavy-duty loops to call the core programs directly and thus save
the extra fork() / execve() overhead, although that's not really
necessary any more.

The --exec-path value is prepended to $PATH, so the git-* programs
should Just Work without ever requiring any changes to how they call
other programs in the suite.

Some timing values for 10000 invocations of git-var >&/dev/null:
	git.sh: 24.194s
	git.c:   9.044s
	git-var: 7.377s

The git-<tab><tab> behaviour can, along with the someday-to-be-deprecated
git-<command> form of invocation, be indefinitely retained by adding
the following line to one's .bash_profile or equivalent:

	PATH=$PATH:$(git --exec-path)

Experimental libraries can be used by either setting the environment variable
GIT_EXEC_PATH, or by using

	git --exec-path=/some/experimental/exec-path

Relative paths are properly grok'ed as exec-path values.

Signed-off-by: Andreas Ericsson <ae@op5.se>

---

 Makefile |   20 ++---
 git.c    |  229 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 git.sh   |   76 ---------------------
 3 files changed, 237 insertions(+), 88 deletions(-)
 create mode 100644 git.c
 delete mode 100755 git.sh

applies-to: 4b6dbe856a3e63699b299c76f4f1fc5cb34cbe26
d9a0c94f64a140b5e32d8541875e77ee96ed5ff8
diff --git a/Makefile b/Makefile
index 63cb998..0515968 100644
--- a/Makefile
+++ b/Makefile
@@ -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 \
@@ -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))
diff --git a/git.c b/git.c
new file mode 100644
index 0000000..d189801
--- /dev/null
+++ b/git.c
@@ -0,0 +1,229 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <glob.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 ]";
+
+struct string_list {
+	size_t len;
+	char *str;
+	struct string_list *next;
+};
+
+/* 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 inline void mput_char(char c, unsigned int num)
+{
+	while(num--)
+		putchar(c);
+}
+
+static void pretty_print_string_list(struct string_list *list, 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 */
+
+	if (space < max_cols)
+		cols = max_cols / space;
+
+	while (list) {
+		int c;
+		printf("  ");
+
+		for (c = cols; c && list; list = list->next) {
+			printf("%s", list->str);
+
+			if (--c)
+				mput_char(' ', space - list->len);
+		}
+		putchar('\n');
+	}
+}
+
+static void list_commands(const char *exec_path, const char *pattern)
+{
+	struct string_list *list = NULL, *tail = NULL;
+	unsigned int longest = 0, i;
+	glob_t gl;
+
+	if (chdir(exec_path) < 0) {
+		printf("git: '%s': %s\n", exec_path, strerror(errno));
+		exit(1);
+	}
+
+	i = glob(pattern, 0, NULL, &gl);
+	switch(i) {
+	case GLOB_NOSPACE:
+		puts("Out of memory when running glob()");
+		exit(2);
+	case GLOB_ABORTED:
+		printf("'%s': Read error: %s\n", exec_path, strerror(errno));
+		exit(2);
+	case GLOB_NOMATCH:
+		printf("No git commands available in '%s'.\n", exec_path);
+		printf("Do you need to specify --exec-path or set GIT_EXEC_PATH?\n");
+		exit(1);
+	}
+
+	for (i = 0; i < gl.gl_pathc; i++) {
+		int len = strlen(gl.gl_pathv[i] + 4);
+
+		if (access(gl.gl_pathv[i], X_OK))
+			continue;
+
+		if (longest < len)
+			longest = len;
+
+		if (!tail)
+			tail = list = malloc(sizeof(struct string_list));
+		else {
+			tail->next = malloc(sizeof(struct string_list));
+			tail = tail->next;
+		}
+		tail->len = len;
+		tail->str = gl.gl_pathv[i] + 4;
+		tail->next = NULL;
+	}
+
+	printf("git commands available in '%s'\n", exec_path);
+	printf("----------------------------");
+	mput_char('-', strlen(exec_path));
+	putchar('\n');
+	pretty_print_string_list(list, longest);
+	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 = "/bin:/usr/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);
+}
+
+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)
+		usage(exec_path, NULL);
+
+	/* allow relative paths, but run with exact */
+	if (chdir(exec_path)) {
+		printf("git: '%s': %s\n", exec_path, strerror(errno));
+		exit (1);
+	}
+
+	getcwd(git_command, sizeof(git_command));
+	chdir(wd);
+
+	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;
+}
diff --git a/git.sh b/git.sh
deleted file mode 100755
index 94940ae..0000000
--- a/git.sh
+++ /dev/null
@@ -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
---
0.99.9.GIT

^ permalink raw reply related

* [PATCH 2/3] Update git(7) man-page for the C wrapper.
From: Andreas Ericsson @ 2005-11-15 23:31 UTC (permalink / raw)
  To: git


The program 'git' now has --exec-path which needs explaining.

Renamed old "DESCRIPTION" to "CORE GIT COMMANDS" to make room for
"OPTIONS" while following follow some sort of convention.

Also updated AUTHORS section to pat my own back a bit.

Signed-off-by: Andreas Ericsson <ae@op5.se>

---

 Documentation/git.txt |   33 +++++++++++++++++++++++++++------
 1 files changed, 27 insertions(+), 6 deletions(-)

applies-to: 5b537267ba1593d4eb92f9bc09d32c14fb7e2faf
e743bc1a48f15533ae9cd2f450106be96516d037
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 7045f3f..91e9f9f 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -8,13 +8,31 @@ 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).
+
+OPTIONS
+-------
+--version::
+	prints the git suite version that the 'git' program came from.
+
+--help::
+	prints the synopsis and a list of available commands.
+
+--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.
 
-This is reference information for the core git commands.
-
+CORE GIT COMMANDS
+-----------------
 Before reading this cover to cover, you may want to take a look
 at the link:tutorial.html[tutorial] document.
 
@@ -533,9 +551,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
 --------------
---
0.99.9.GIT

^ permalink raw reply related

* [PATCH 3/3] git --help COMMAND brings up the git-COMMAND man-page.
From: Andreas Ericsson @ 2005-11-15 23:31 UTC (permalink / raw)
  To: git


It's by design a bit stupid (matching ^git rather than ^git-), so as
to work with 'gitk' and 'git' as well.

Signed-off-by: Andreas Ericsson <ae@op5.se>

---

 Documentation/git.txt |    2 ++
 git.c                 |   28 ++++++++++++++++++++++++++--
 2 files changed, 28 insertions(+), 2 deletions(-)

applies-to: 8a47ae8a825ab0e68ac46392bccd1ec16df39456
3b7d6e6722b0d27ef5f9ae99a76d3ff909d3e98a
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 91e9f9f..7cbfaf8 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -24,6 +24,8 @@ OPTIONS
 
 --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.
diff --git a/git.c b/git.c
index d189801..583923d 100644
--- a/git.c
+++ b/git.c
@@ -160,6 +160,26 @@ static void prepend_to_path(const char *
 	setenv("PATH", path, 1);
 }
 
+/* has anyone seen 'man' installed anywhere else than in /usr/bin? */
+#define PATH_TO_MAN "/usr/bin/man"
+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(PATH_TO_MAN, "man", page, NULL);
+}
+
 int main(int argc, char **argv, char **envp)
 {
 	char git_command[PATH_MAX + 1];
@@ -199,8 +219,12 @@ int main(int argc, char **argv, char **e
 			usage(NULL, NULL);
 	}
 
-	if (i >= argc || show_help)
-		usage(exec_path, NULL);
+	if (i >= argc || show_help) {
+		if (i >= argc)
+			usage(exec_path, NULL);
+
+		show_man_page(argv[i]);
+	}
 
 	/* allow relative paths, but run with exact */
 	if (chdir(exec_path)) {
---
0.99.9.GIT

^ permalink raw reply related

* Re: fix git-pack-redundant crashing sometimes
From: Lukas Sandström @ 2005-11-15 23:13 UTC (permalink / raw)
  To: git; +Cc: Alex Riesen, junkio
In-Reply-To: <20051115223340.GA3951@steel.home>

Alex Riesen wrote:
> Lukas Sandström, Tue, Nov 15, 2005 22:41:34 +0100:
> 
>>>>llist_sorted_difference_inplace didn't handle the match in the first
>>>>sha1 correctly and the lists went wild everywhere.
>>>
>>>This wasn't enough. It never (>5 min on 2.4GHz PIV) finishes on
>>>my local mirror of git, which has 22 packs by now.
>>
>>If the patch I just sent out doesn't fix the problem, and you don't
> 
> 
> Sorry, it doesn't. The code loops here:
> 
> 401             /* find the permutations which contain all missing objects */
> 402             perm_all = perm = get_all_permutations(non_unique);
> 403             while (perm) {
> 404                     if (is_superset(perm->pl, missing)) {
> 405                             new_perm = xmalloc(sizeof(struct pll));
> 406                             new_perm->pl = perm->pl;
> 407                             new_perm->next = perm_ok;
> 408                             perm_ok = new_perm;
> (gdb) 
> 409                     }
> 410                     perm = perm->next;
> 411             }
> 412
> 413             if (perm_ok == NULL)
> 
> 
> 
>>want to debug it yourself, could you please publish the .idx files
>>so I could have a look at them?
> 
> 
> Of course: http://home.arcor.de/fork0/download/idx.tar.gz
> 

After giving it a quick look, I don't think it locks up. It is just horribly
slow. get_all_permutations returns (nice ASCII-art follows)

    ___n___
    \
     \ ____1____
n! * /  k!(n-k)!
    /______
      k=1

permutations, which for your case (22 packs) adds up to 4194303.

I'll look into an optimization so we won't have to call is_superset
for every one of them.

OTOH, I might be wrong and it could very well be an infinite loop.
Mind running it over the night? I won't look further into this in
20 hours or so anyway.

^ permalink raw reply

* Re: [PATCH 0/3] Support setting SymrefsOnly=true from scripts
From: Junio C Hamano @ 2005-11-15 23:07 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0511152233430.2152@wbgn013.biozentrum.uni-wuerzburg.de>

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> 	- set SymrefsOnly=true right from the start with
> 		git-init-db --dont-use-symrefs

I am almost tempted to say that we should be doing --template=
option to git-init-db for something like this, and make the
template instantiation first thing before even reading the
config file.

The rest might be useful to better support end-users, but I am
not sure.  Is it that much hassle to them to edit an .ini file?

^ permalink raw reply

* [PATCH] Re: Make "gitk" work better with dense revlists
From: Yann Dirson @ 2005-11-15 22:57 UTC (permalink / raw)
  To: git

Linus wrote:
>To generate the diff for a commit, gitk used to do
>
>	git-diff-tree -p -C $p $id

Although the "$p" reference is harmful to --dense mode, and redundant
when we just want to look at a single commit, removing it breaks the
"Diff this -> selected" and "Diff selected -> this" features.

A minimal fix would be at least make your change dependant on being in
dense mode, and disable those extra features then (better than keeping
them broken) if noone takes the lead to fix it.

Signed-off-by: Yann Dirson <ydirson@altern.org>

diff --git a/gitk b/gitk
index a9d37d9..f73ab41 100755
--- a/gitk
+++ b/gitk
@@ -2801,12 +2801,17 @@ proc addtocflist {ids} {
 }
 
 proc gettreediffs {ids} {
-    global treediff parents treepending
+    global treediff parents treepending isdense
     set treepending $ids
     set treediff {}
     set id [lindex $ids 0]
     set p [lindex $ids 1]
-    if [catch {set gdtf [open "|git-diff-tree -r $id" r]}] return
+    if {$isdense == 1} {
+       set range "$id"
+    } else {
+       set range "$p $id"
+    }
+    if [catch {set gdtf [open "|git-diff-tree -r $range" r]}] return
     fconfigure $gdtf -blocking 0
     fileevent $gdtf readable [list gettreediffline $gdtf $ids]
 }
@@ -2837,12 +2842,16 @@ proc gettreediffline {gdtf ids} {
 
 proc getblobdiffs {ids} {
     global diffopts blobdifffd diffids env curdifftag curtagstart
-    global difffilestart nextupdate diffinhdr treediffs
+    global difffilestart nextupdate diffinhdr treediffs isdense
 
     set id [lindex $ids 0]
     set p [lindex $ids 1]
     set env(GIT_DIFF_OPTS) $diffopts
-    set cmd [list | git-diff-tree -r -p -C $id]
+    if {$isdense == 1} {
+       set cmd [list | git-diff-tree -r -p -C $id]
+    } else {
+       set cmd [list | git-diff-tree -r -p -C $p $id]
+    }
     if {[catch {set bdf [open $cmd r]} err]} {
        puts "error getting diffs: $err"
        return
@@ -3299,16 +3308,21 @@ proc mstime {} {
 }
 
 proc rowmenu {x y id} {
-    global rowctxmenu idline selectedline rowmenuid
+    global rowctxmenu idline selectedline rowmenuid isdense
 
     if {![info exists selectedline] || $idline($id) eq $selectedline} {
-       set state disabled
+       set patchstate disabled
     } else {
-       set state normal
+       set patchstate normal
+    }
+    if {$isdense || $patchstate eq "disabled"} {
+       set diffstate disabled
+    } else {
+       set diffstate normal
     }
-    $rowctxmenu entryconfigure 0 -state $state
-    $rowctxmenu entryconfigure 1 -state $state
-    $rowctxmenu entryconfigure 2 -state $state
+    $rowctxmenu entryconfigure 0 -state $diffstate
+    $rowctxmenu entryconfigure 1 -state $diffstate
+    $rowctxmenu entryconfigure 2 -state $patchstate
     set rowmenuid $id
     tk_popup $rowctxmenu $x $y
 }
@@ -3653,6 +3667,7 @@ proc doquit {} {
 # defaults...
 set datemode 0
 set boldnames 0
+set isdense 0
 set diffopts "-U 5 -p"
 set wrcomcmd "git-diff-tree --stdin -p --pretty"
 
@@ -3678,6 +3693,10 @@ foreach arg $argv {
        "^$" { }
        "^-b" { set boldnames 1 }
        "^-d" { set datemode 1 }
+       "^--dense$" {
+           set isdense 1
+           lappend revtreeargs $arg
+       }
        default {
            lappend revtreeargs $arg
        }

-- 
Yann Dirson    <ydirson@altern.org> |
Debian-related: <dirson@debian.org> |   Support Debian GNU/Linux:
                                    |  Freedom, Power, Stability, Gratis
     http://ydirson.free.fr/        | Check <http://www.debian.org/>

^ permalink raw reply related

* [PATCH 1/2] Cleanup: remove unused variable
From: Chuck Lever @ 2005-11-15 22:52 UTC (permalink / raw)
  To: catalin.marinas; +Cc: git
In-Reply-To: <20051115225136.16350.96122.stgit@dexter.citi.umich.edu>

Get rid of git.py:head_link , as it is no longer used by any part of
StGIT.

Signed-off-by: Chuck Lever <cel@netapp.com>
---

 stgit/git.py |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/stgit/git.py b/stgit/git.py
index 9a07fa5..066a8f0 100644
--- a/stgit/git.py
+++ b/stgit/git.py
@@ -33,7 +33,6 @@ if 'GIT_DIR' in os.environ:
 else:
     base_dir = '.git'
 
-head_link = os.path.join(base_dir, 'HEAD')
 
 #
 # Classes

^ permalink raw reply related

* [PATCH 2/2] Clean up StGIT's "branch --delete" command
From: Chuck Lever @ 2005-11-15 22:52 UTC (permalink / raw)
  To: catalin.marinas; +Cc: git
In-Reply-To: <20051115225136.16350.96122.stgit@dexter.citi.umich.edu>

os.path.isfile is not the same as os.path.exists.

Signed-off-by: Chuck Lever <cel@netapp.com>
---

 stgit/stack.py |   21 +++++++++++----------
 1 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/stgit/stack.py b/stgit/stack.py
index 0907b37..7bf7e7c 100644
--- a/stgit/stack.py
+++ b/stgit/stack.py
@@ -404,16 +404,17 @@ class Series:
         """Renames a series
         """
         to_stack = Series(to_name)
-        if os.path.isdir(to_stack.__patch_dir):
-            raise StackException, '"%s" already exists' % to_stack.__patch_dir
-        if os.path.isfile(to_stack.__base_file):
-            raise StackException, '"%s" already exists' % to_stack.__base_file
+
+        if to_stack.is_initialised:
+            raise StackException, '"%s" already exists' % to_stack.get_branch()
+        if os.path.exists(to_stack.__base_file):
+            os.remove(to_stack.__base_file)
 
         git.rename_branch(self.__name, to_name)
 
         if os.path.isdir(self.__patch_dir):
             os.rename(self.__patch_dir, to_stack.__patch_dir)
-        if os.path.isfile(self.__base_file):
+        if os.path.exists(self.__base_file):
             os.rename(self.__base_file, to_stack.__base_file)
 
         self.__init__(to_name)
@@ -430,20 +431,20 @@ class Series:
             for p in patches:
                 self.delete_patch(p)
 
-            if os.path.isfile(self.__applied_file):
+            if os.path.exists(self.__applied_file):
                 os.remove(self.__applied_file)
-            if os.path.isfile(self.__unapplied_file):
+            if os.path.exists(self.__unapplied_file):
                 os.remove(self.__unapplied_file)
-            if os.path.isfile(self.__current_file):
+            if os.path.exists(self.__current_file):
                 os.remove(self.__current_file)
-            if os.path.isfile(self.__descr_file):
+            if os.path.exists(self.__descr_file):
                 os.remove(self.__descr_file)
             if not os.listdir(self.__patch_dir):
                 os.rmdir(self.__patch_dir)
             else:
                 print 'Series directory %s is not empty.' % self.__name
 
-        if os.path.isfile(self.__base_file):
+        if os.path.exists(self.__base_file):
             os.remove(self.__base_file)
 
     def refresh_patch(self, message = None, edit = False, show_patch = False,

^ permalink raw reply related

* [PATCH 0/2] Two more small clean-ups
From: Chuck Lever @ 2005-11-15 22:51 UTC (permalink / raw)
  To: catalin.marinas; +Cc: git

        -- Chuck Lever
--
corporate:    <cel at netapp dot com>
personal:     <chucklever at bigfoot dot com>

^ permalink raw reply

* Re: fix git-pack-redundant crashing sometimes
From: Alex Riesen @ 2005-11-15 22:33 UTC (permalink / raw)
  To: Lukas Sandström; +Cc: git, junkio
In-Reply-To: <437A560E.8020500@etek.chalmers.se>

Lukas Sandström, Tue, Nov 15, 2005 22:41:34 +0100:
> >>llist_sorted_difference_inplace didn't handle the match in the first
> >>sha1 correctly and the lists went wild everywhere.
> > 
> > This wasn't enough. It never (>5 min on 2.4GHz PIV) finishes on
> > my local mirror of git, which has 22 packs by now.
> 
> If the patch I just sent out doesn't fix the problem, and you don't

Sorry, it doesn't. The code loops here:

401             /* find the permutations which contain all missing objects */
402             perm_all = perm = get_all_permutations(non_unique);
403             while (perm) {
404                     if (is_superset(perm->pl, missing)) {
405                             new_perm = xmalloc(sizeof(struct pll));
406                             new_perm->pl = perm->pl;
407                             new_perm->next = perm_ok;
408                             perm_ok = new_perm;
(gdb) 
409                     }
410                     perm = perm->next;
411             }
412
413             if (perm_ok == NULL)


> want to debug it yourself, could you please publish the .idx files
> so I could have a look at them?

Of course: http://home.arcor.de/fork0/download/idx.tar.gz

^ permalink raw reply

* Re: [PATCH] Small script to patch .spec for Suse
From: H. Peter Anvin @ 2005-11-15 22:22 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Junio C Hamano, Josef Weidendorfer, git
In-Reply-To: <20051115215943.GW30496@pasky.or.cz>

Petr Baudis wrote:
> 
> Actually, can you have some kind of %if in specfiles? Then you could
> keep everything in the specfile and just pass it whatever system you
> want to build for.
> 

Sure.  It's called %if.  There is also %ifdef and %define.

	-hpa

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox