Git development
 help / color / mirror / Atom feed
* Re: [PATCH] rebase --preserve-merges keeps empty merge commits
From: Junio C Hamano @ 2013-01-14 17:15 UTC (permalink / raw)
  To: Matthieu Moy
  Cc: Phil Hord, git, phil.hord, Neil Horman, Martin von Zweigbergk
In-Reply-To: <vpqpq17zwdl.fsf@grenoble-inp.fr>

Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:

> Phil Hord <hordp@cisco.com> writes:
>
>> Subject: [PATCH] rebase --preserve-merges keeps empty merge commits
>
> I would rephrase it as
>
>   rebase --preserve-merges: keep empty merge commits
>
> we usually give orders in commit messages, not state facts (it's not
> clear from the existing subject line whether keeping merge commit is the
> new behavior or a bug that the commit tries to fix).

Thanks for giving a concise rationale on our use of imperative mood.

Phil, I think you meant to and forgot to sign-off; here is what I'll
queue.

Thanks.

-- >8 --
From: Phil Hord <hordp@cisco.com>
Date: Sat, 12 Jan 2013 15:46:01 -0500
Subject: [PATCH] rebase --preserve-merges: keep all merge commits including empty ones

Since 90e1818f9a  (git-rebase: add keep_empty flag, 2012-04-20)
'git rebase --preserve-merges' fails to preserve empty merge commits
unless --keep-empty is also specified.  Merge commits should be
preserved in order to preserve the structure of the rebased graph,
even if the merge commit does not introduce changes to the parent.

Teach rebase not to drop merge commits only because they are empty.

A special case which is not handled by this change is for a merge commit
whose parents are now the same commit because all the previous different
parents have been dropped as a result of this rebase or some previous
operation.

Signed-off-by: Phil Hord <hordp@cisco.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 git-rebase--interactive.sh | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 0c19b7c..2fed92f 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -175,6 +175,11 @@ is_empty_commit() {
 	test "$tree" = "$ptree"
 }
 
+is_merge_commit()
+{
+	git rev-parse --verify --quiet "$1"^2 >/dev/null 2>&1
+}
+
 # Run command with GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and
 # GIT_AUTHOR_DATE exported from the current environment.
 do_with_author () {
@@ -796,7 +801,7 @@ git rev-list $merges_option --pretty=oneline --abbrev-commit \
 while read -r shortsha1 rest
 do
 
-	if test -z "$keep_empty" && is_empty_commit $shortsha1
+	if test -z "$keep_empty" && is_empty_commit $shortsha1 && ! is_merge_commit $shortsha1
 	then
 		comment_out="# "
 	else
-- 
1.8.1.1.338.g126d652

^ permalink raw reply related

* Re: git list files
From: Стойчо Слепцов @ 2013-01-14 17:20 UTC (permalink / raw)
  To: Jeff King; +Cc: Jonathan Nieder, git
In-Reply-To: <20130114152836.GA18370@sigill.intra.peff.net>

I went through your initial thread about blame-tree,
and it is really very very (+very) close to answer my question.

Thanks for writing it,
if it comes one day to git, I will use it.

As for:
'I guess people's eyes and brains are trained by the old school "file
boundaries matter" way of thinking'
-- Junio C Hamano
at http://thread.gmane.org/gmane.comp.version-control.git/168323;
http://article.gmane.org/gmane.comp.version-control.git/168333

I think it's not the case, Mr. Hamano.

>From my point of view, it is just to have a quick picture of "what
came from where in this current directory",
which is a normal reaction of human beings, I think.

Speaking of which I can't help thinking that this feature could be
provided by $git rev-list (HEAD) --no-walk -- <paths>, just don't stop
at first commit,
but at first commit for each of the paths.

Or maybe diff could have an option to not compare against a specific point,
but actually do his job and go downstears and find where the
_diff_erence for _each_ path happened finally.

(... applicable for $git status -l (--list) --porcelain ... but thats
a whim, sorry.)

Anyway,
thank you all for your time, it was a real pleasure for me,
Blind.

2013/1/14 Jeff King <peff@peff.net>:
> On Sun, Jan 13, 2013 at 11:08:32PM -0800, Jonathan Nieder wrote:
>
>> Jeff King wrote:
>>
>> > As far as I recall, that script works. However, I have a pure-C
>> > blame-tree implementation that is much faster, which may also be of
>> > interest. I need to clean up and put a few finishing touches on it to
>> > send it to the list, but it has been in production at GitHub for a few
>> > months. You can find it here:
>> >
>> >   git://github.com/peff/git jk/blame-tree
>>
>> Oh, neat.  Would that make sense as an item in
>> <https://git.wiki.kernel.org/index.php/Interfaces,_frontends,_and_tools>?
>
> I'd rather finish cleaning it up and actually get it merged. It's on my
> todo list.
>
> -Peff

^ permalink raw reply

* Re: [PATCH v2 2/3] push: Add support for pre-push hooks
From: Junio C Hamano @ 2013-01-14 17:39 UTC (permalink / raw)
  To: Aaron Schrab; +Cc: git
In-Reply-To: <1358054224-7710-3-git-send-email-aaron@schrab.com>

Aaron Schrab <aaron@schrab.com> writes:

> Add support for a pre-push hook which can be used to determine if the
> set of refs to be pushed is suitable for the target repository.  The
> hook is run with two arguments specifying the name and location of the
> destination repository.
>
> Information about what is to be pushed is provided by sending lines of
> the following form to the hook's standard input:
>
>   <local ref> SP <local sha1> SP <remote ref> SP <remote sha1> LF
>
> If the hook exits with a non-zero status, the push will be aborted.
>
> This will allow the script to determine if the push is acceptable based
> on the target repository and branch(es), the commits which are to be
> pushed, and even the source branches in some cases.
>
> Signed-off-by: Aaron Schrab <aaron@schrab.com>
> ---
>  Documentation/githooks.txt |  29 ++++++++++
>  builtin/push.c             |   1 +
>  t/t5571-pre-push-hook.sh   | 129 +++++++++++++++++++++++++++++++++++++++++++++
>  transport.c                |  60 +++++++++++++++++++++
>  transport.h                |   1 +
>  5 files changed, 220 insertions(+)
>  create mode 100755 t/t5571-pre-push-hook.sh
>
> diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
> index b9003fe..d839233 100644
> --- a/Documentation/githooks.txt
> +++ b/Documentation/githooks.txt
> @@ -176,6 +176,35 @@ save and restore any form of metadata associated with the working tree
>  (eg: permissions/ownership, ACLS, etc).  See contrib/hooks/setgitperms.perl
>  for an example of how to do this.
>  
> +pre-push
> +~~~~~~~~
> +
> +This hook is called by 'git push' and can be used to prevent a push from taking
> +place.  The hook is called with two parameters which provide the name and
> +location of the destination remote, if a named remote is not being used both
> +values will be the same.
> +
> +Information about what is to be pushed is provided on the hook's standard
> +input with lines of the form:
> +
> +  <local ref> SP <local sha1> SP <remote ref> SP <remote sha1> LF
> +
> +For instance, if the command +git push origin master:foreign+ were run the

Just being curious, but why use +monospace text+ here?  Most of the
new text use `monospace text literally` instead in this patch.

> +hook would receive a line like the following:
> +
> +  refs/heads/master 67890 refs/heads/foreign 12345
> +
> +although the full, 40-character SHA1s would be supplied.

Perhaps ellipses are called for here?

    refs/heads/master 67890... refs/heads/foreign 12345...

 (the above abbreviates full 40-hexdigits for illustration purposes only)

> +If the foreign ref
> +does not yet exist the `<remote SHA1>` will be 40 `0`.  If a ref is to be
> +deleted, the `<local ref>` will be supplied as `(delete)` and the `<local
> +SHA1>` will be 40 `0`.  If the local commit was specified by something other
> +than a name which could be expanded (such as `HEAD~`, or a SHA1) it will be
> +supplied as it was originally given.
> +
> +If this hook exits with a non-zero status, 'git push' will abort without
> +pushing anything.  Information about why the push is rejected may be sent
> +to the user by writing to standard error.

s/standard error/& of the hook/; perhaps?  It is unclear who does
the writing and it can be misunderstood that git-push will write to
standard error upon seeing your hook that silently exits.

> diff --git a/builtin/push.c b/builtin/push.c
> index 8491e43..b158028 100644
> --- a/builtin/push.c
> +++ b/builtin/push.c
> @@ -407,6 +407,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
>  		OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
>  		OPT_BIT(0, "prune", &flags, N_("prune locally removed refs"),
>  			TRANSPORT_PUSH_PRUNE),
> +		OPT_BIT(0, "no-verify", &flags, N_("bypass pre-push hook"), TRANSPORT_PUSH_NO_HOOK),
>  		OPT_END()
>  	};

So to countermand this, you have to say --no-no-verify?  Wouldn't it
be more natural to introduce a --verify option that turns the bit
on, which automatically gives you --no-verify to turn it off?  A
bit in a flag word can be initialized to true before the flag word
is given to the parse_options() machinery to make the field default
to true, no?

^ permalink raw reply

* Re: [PATCH v2 3/3] Add sample pre-push hook script
From: Junio C Hamano @ 2013-01-14 17:42 UTC (permalink / raw)
  To: Aaron Schrab; +Cc: git
In-Reply-To: <1358054224-7710-4-git-send-email-aaron@schrab.com>

Aaron Schrab <aaron@schrab.com> writes:

> Create a sample of a script for a pre-push hook.  The main purpose is to
> illustrate how a script may parse the information which is supplied to
> such a hook.  The script may also be useful to some people as-is for
> avoiding to push commits which are marked as a work in progress.
>
> Signed-off-by: Aaron Schrab <aaron@schrab.com>
> ---
>  templates/hooks--pre-push.sample | 53 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 53 insertions(+)
>  create mode 100644 templates/hooks--pre-push.sample
>
> diff --git a/templates/hooks--pre-push.sample b/templates/hooks--pre-push.sample
> new file mode 100644
> index 0000000..15ab6d8
> --- /dev/null
> +++ b/templates/hooks--pre-push.sample
> @@ -0,0 +1,53 @@
> +#!/bin/sh
> +
> +# An example hook script to verify what is about to be pushed.  Called by "git
> +# push" after it has checked the remote status, but before anything has been
> +# pushed.  If this script exits with a non-zero status nothing will be pushed.
> +#
> +# This hook is called with the following parameters:
> +#
> +# $1 -- Name of the remote to which the push is being done
> +# $2 -- URL to which the push is being done
> +#
> +# If pushing without using a named remote those arguments will be equal.
> +#
> +# Information about the commits which are being pushed is supplied as lines to
> +# the standard input in the form:
> +#
> +#   <local ref> <local sha1> <remote ref> <remote sha1>
> +#
> +# This sample shows how to prevent push of commits where the log message starts
> +# with "WIP" (work in progress).

An example for a plausible use case is nice to have.  I would prefer
to see any new shell script to follow the Git style, though.

> +remote="$1"
> +url="$2"
> +
> +z40=0000000000000000000000000000000000000000
> +
> +IFS=' '
> +while read local_ref local_sha remote_ref remote_sha
> +do
> +	if [ "$local_sha" = $z40 ]
> +	then
> +		# Handle delete

    ... by doing what?

> +	else
> +		if [ "$remote_sha" = $z40 ]
> +		then
> +			# New branch, examine all commits
> +			range="$local_sha"
> +		else
> +			# Update to existing branch, examine new commits
> +			range="$remote_sha..$local_sha"
> +		fi
> +
> +		# Check for WIP commit
> +		commit=`git rev-list -n 1 --grep '^WIP' "$range"`
> +		if [ -n "$commit" ]
> +		then
> +			echo "Found WIP commit in $local_ref, not pushing"
> +			exit 1
> +		fi
> +	fi
> +done
> +
> +exit 0

^ permalink raw reply

* Re: [PATCH v2 0/3] pre-push hook support
From: Junio C Hamano @ 2013-01-14 17:42 UTC (permalink / raw)
  To: Aaron Schrab; +Cc: git
In-Reply-To: <1358054224-7710-1-git-send-email-aaron@schrab.com>

Aaron Schrab <aaron@schrab.com> writes:

> Main changes since the initial version:
>
>  * The first patch converts the existing hook callers to use the new
>    find_hook() function.
>  * Information about what is to be pushed is now sent over a pipe rather
>    than passed as command-line parameters.
>
> Aaron Schrab (3):
>   hooks: Add function to check if a hook exists
>   push: Add support for pre-push hooks
>   Add sample pre-push hook script

Getting much nicer.  Thanks.

^ permalink raw reply

* Re: [PATCH] rebase --preserve-merges keeps empty merge commits
From: Phil Hord @ 2013-01-14 17:50 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Matthieu Moy, git, phil.hord, Neil Horman, Martin von Zweigbergk
In-Reply-To: <7vwqvfele2.fsf@alter.siamese.dyndns.org>


Junio C Hamano wrote:
> Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:
>
>> Phil Hord <hordp@cisco.com> writes:
>>
>>> Subject: [PATCH] rebase --preserve-merges keeps empty merge commits
>> I would rephrase it as
>>
>>   rebase --preserve-merges: keep empty merge commits
>>
>> we usually give orders in commit messages, not state facts (it's not
>> clear from the existing subject line whether keeping merge commit is the
>> new behavior or a bug that the commit tries to fix).
> Thanks for giving a concise rationale on our use of imperative mood.
>
> Phil, I think you meant to and forgot to sign-off; here is what I'll
> queue.
>
> Thanks.
>

Looks good.  Thanks for the help.

Phil

^ permalink raw reply

* Re: [PATCH] t0050: mark TC merge (case change) as success
From: Torsten Bögershausen @ 2013-01-14 17:53 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Torsten Bögershausen, git, prohaska
In-Reply-To: <7v7gnghdj2.fsf@alter.siamese.dyndns.org>

On 14.01.13 00:24, Junio C Hamano wrote:
> Torsten Bögershausen <tboegi@web.de> writes:
> 
>> The test "merge (case change)" passes on a case ignoring file system
>>
>> Use test_expect_success to remove the "known breakage vanished"
>>
>> Signed-off-by: Torsten Bögershausen <tboegi@web.de>
>> ---
> 
> Interesting.  When did this change?  Do you happen to have a
> bisection?  
This seems to be the commit:

commit 6aad47dec7a72bb36c64afb6c43f4dbcaa49e7f9
Merge: e13067a 0047dd2
Author: Junio C Hamano <gitster@pobox.com>
Date:   Fri May 23 16:05:52 2008 -0700

    Merge branch 'sp/ignorecase'
    
    * sp/ignorecase:
      t0050: Fix merge test on case sensitive file systems
      t0050: Add test for case insensitive add
      t0050: Set core.ignorecase case to activate case insensitivity
      t0050: Test autodetect core.ignorecase
      git-init: autodetect core.ignorecase

Which comes from here:

commit 0047dd2fd1fc1980913901c5fa098357482c2842
Author: Steffen Prohaska <prohaska@zib.de>
Date:   Thu May 15 07:19:54 2008 +0200

    t0050: Fix merge test on case sensitive file systems
    
    On a case sensitive filesystem, "git reset --hard" might refuse to
    overwrite a file whose name differs only by case, even if
    core.ignorecase is set.  It is not clear which circumstances cause this
    behavior.  This commit simply works around the problem by removing
    the case changing file before running "git reset --hard".
    
    Signed-off-by: Steffen Prohaska <prohaska@zib.de>
    Signed-off-by: Junio C Hamano <gitster@pobox.com>

===========

>Or did the test pass from the very beginning?
Hm, reading the commit, it seems as if the "root problem" still exist:
git reset --hard does not change the case of an existing file

What is the exist behvior?



My feeling is that the test as such deserves some more improvements,
the result of the merge is not checked, files are empty so that
the content is not checked.

Another improvement:
Running under Linux gives:
not ok 6 - add (with different case) # TODO known breakage
(and running under mingw failes)
 
Please stay tuned for more updates, thanks for reviewing.
/Torsten

^ permalink raw reply

* Re: [PATCH 3/6] convert some config callbacks to match_config_key
From: Jeff King @ 2013-01-14 18:05 UTC (permalink / raw)
  To: Jonathan Nieder; +Cc: Joachim Schmitz, René Scharfe, Junio C Hamano, git
In-Reply-To: <20130114170610.GB22098@sigill.intra.peff.net>

On Mon, Jan 14, 2013 at 09:06:10AM -0800, Jeff King wrote:

>   struct config_key k;
>   parse_config_key(&k, var);
>   if (strcmp(k.section, "filter") || k.subsection))
>           return 0;
> 
> would be a better start (or having git_config do the first two lines
> itself before triggering the callback).

Here's what that looks like, along with the cleanups in submodule.c that
are made possible by it.

I "cheat" a little and use a static buffer when parsing the config key,
so that the caller does not have to deal with freeing it. It makes using
the parser literally as simple as the lines above, but it does mean it
isn't re-entrant (and worse, it has to be invoked from a config
callback, since the static buffer is tied to the config file stack).

None of that is a problem for the use here, but it is not a
generally-callable function. For that reason, it might make more sense
to have the config parser just provide the config_key, and not have a
public function at all. The downside to that is that we have to update
the function signature of all of the config callbacks.

---
 cache.h     |  7 ++++++
 config.c    | 35 ++++++++++++++++++++++++++++++
 submodule.c | 41 ++++++++++++++---------------------
 3 files changed, 58 insertions(+), 25 deletions(-)

diff --git a/cache.h b/cache.h
index c257953..df756e6 100644
--- a/cache.h
+++ b/cache.h
@@ -1119,6 +1119,13 @@ extern int update_server_info(int);
 #define CONFIG_INVALID_PATTERN 6
 #define CONFIG_GENERIC_ERROR 7
 
+struct config_key {
+	const char *section;
+	const char *subsection;
+	const char *key;
+};
+void config_key_parse(struct config_key *, const char *);
+
 typedef int (*config_fn_t)(const char *, const char *, void *);
 extern int git_default_config(const char *, const char *, void *);
 extern int git_config_from_file(config_fn_t fn, const char *, void *);
diff --git a/config.c b/config.c
index 7b444b6..7b8df3e 100644
--- a/config.c
+++ b/config.c
@@ -18,6 +18,7 @@ typedef struct config_file {
 	int eof;
 	struct strbuf value;
 	struct strbuf var;
+	struct strbuf key_parse_buf;
 } config_file;
 
 static config_file *cf;
@@ -899,6 +900,7 @@ int git_config_from_file(config_fn_t fn, const char *filename, void *data)
 		top.eof = 0;
 		strbuf_init(&top.value, 1024);
 		strbuf_init(&top.var, 1024);
+		strbuf_init(&top.key_parse_buf, 1024);
 		cf = &top;
 
 		ret = git_parse_file(fn, data);
@@ -906,6 +908,7 @@ int git_config_from_file(config_fn_t fn, const char *filename, void *data)
 		/* pop config-file parsing state stack */
 		strbuf_release(&top.value);
 		strbuf_release(&top.var);
+		strbuf_release(&top.key_parse_buf);
 		cf = top.prev;
 
 		fclose(f);
@@ -1667,3 +1670,35 @@ int config_error_nonbool(const char *var)
 {
 	return error("Missing value for '%s'", var);
 }
+
+void config_key_parse(struct config_key *key, const char *var)
+{
+	/*
+	 * We want to use a static buffer so the caller does not have to worry
+	 * about memory ownership. But since config parsing can happen
+	 * recursively, we must use storage from the stack of config files.
+	 */
+	struct strbuf *sb = &cf->key_parse_buf;
+	char *dot;
+	char *rdot;
+
+	strbuf_reset(sb);
+	strbuf_addstr(sb, var);
+
+	dot = strchr(sb->buf, '.');
+	rdot = strrchr(sb->buf, '.');
+	/* Should never happen because our keys come from git_parse_file. */
+	if (!dot)
+		die("BUG: config_key_parse was fed a bogus key");
+	key->section = sb->buf;
+	*dot = '\0';
+	key->key = rdot + 1;
+
+	if (rdot == dot)
+		key->subsection = NULL;
+	else {
+		*rdot = '\0';
+		key->subsection = dot + 1;
+	}
+
+}
diff --git a/submodule.c b/submodule.c
index 2f55436..4894718 100644
--- a/submodule.c
+++ b/submodule.c
@@ -11,9 +11,9 @@
 #include "sha1-array.h"
 #include "argv-array.h"
 
-static struct string_list config_name_for_path;
-static struct string_list config_fetch_recurse_submodules_for_name;
-static struct string_list config_ignore_for_name;
+static struct string_list config_name_for_path = STRING_LIST_INIT_DUP;
+static struct string_list config_fetch_recurse_submodules_for_name = STRING_LIST_INIT_DUP;
+static struct string_list config_ignore_for_name = STRING_LIST_INIT_DUP;
 static int config_fetch_recurse_submodules = RECURSE_SUBMODULES_ON_DEMAND;
 static struct string_list changed_submodule_paths;
 static int initialized_fetch_ref_tips;
@@ -126,47 +126,38 @@ int parse_submodule_config_option(const char *var, const char *value)
 
 int parse_submodule_config_option(const char *var, const char *value)
 {
-	int len;
+	struct config_key key;
 	struct string_list_item *config;
-	struct strbuf submodname = STRBUF_INIT;
 
-	var += 10;		/* Skip "submodule." */
+	config_key_parse(&key, var);
+	if (strcmp(key.section, "submodule") || !key.subsection)
+		return 0;
 
-	len = strlen(var);
-	if ((len > 5) && !strcmp(var + len - 5, ".path")) {
-		strbuf_add(&submodname, var, len - 5);
+	if (!strcmp(key.key, "path")) {
 		config = unsorted_string_list_lookup(&config_name_for_path, value);
 		if (config)
 			free(config->util);
 		else
-			config = string_list_append(&config_name_for_path, xstrdup(value));
-		config->util = strbuf_detach(&submodname, NULL);
-		strbuf_release(&submodname);
-	} else if ((len > 23) && !strcmp(var + len - 23, ".fetchrecursesubmodules")) {
-		strbuf_add(&submodname, var, len - 23);
-		config = unsorted_string_list_lookup(&config_fetch_recurse_submodules_for_name, submodname.buf);
+			config = string_list_append(&config_name_for_path, value);
+		config->util = xstrdup(key.subsection);
+	} else if (!strcmp(key.key, "fetchrecursesubmodules")) {
+		config = unsorted_string_list_lookup(&config_fetch_recurse_submodules_for_name, key.subsection);
 		if (!config)
-			config = string_list_append(&config_fetch_recurse_submodules_for_name,
-						    strbuf_detach(&submodname, NULL));
+			config = string_list_append(&config_fetch_recurse_submodules_for_name, key.subsection);
 		config->util = (void *)(intptr_t)parse_fetch_recurse_submodules_arg(var, value);
-		strbuf_release(&submodname);
-	} else if ((len > 7) && !strcmp(var + len - 7, ".ignore")) {
+	} else if (!strcmp(key.key, "ignore")) {
 		if (strcmp(value, "untracked") && strcmp(value, "dirty") &&
 		    strcmp(value, "all") && strcmp(value, "none")) {
 			warning("Invalid parameter \"%s\" for config option \"submodule.%s.ignore\"", value, var);
 			return 0;
 		}
 
-		strbuf_add(&submodname, var, len - 7);
-		config = unsorted_string_list_lookup(&config_ignore_for_name, submodname.buf);
+		config = unsorted_string_list_lookup(&config_ignore_for_name, key.subsection);
 		if (config)
 			free(config->util);
 		else
-			config = string_list_append(&config_ignore_for_name,
-						    strbuf_detach(&submodname, NULL));
-		strbuf_release(&submodname);
+			config = string_list_append(&config_ignore_for_name, key.subsection);
 		config->util = xstrdup(value);
-		return 0;
 	}
 	return 0;
 }

^ permalink raw reply related

* Re: [PATCH 1/6] config: add helper function for parsing key names
From: Junio C Hamano @ 2013-01-14 18:08 UTC (permalink / raw)
  To: Jeff King; +Cc: Joachim Schmitz, René Scharfe, git
In-Reply-To: <20130114150012.GA16828@sigill.intra.peff.net>

Jeff King <peff@peff.net> writes:

> The config callback functions get keys of the general form:
>
>   section.subsection.key
>
> (where the subsection may be contain arbitrary data, or may
> be missing). For matching keys without subsections, it is
> simple enough to call "strcmp". Matching keys with
> subsections is a little more complicated, and each callback
> does it in an ad-hoc way, usually involving error-prone
> pointer arithmetic.
>
> Let's provide a helper that keeps the pointer arithmetic all
> in one place.
>
> Signed-off-by: Jeff King <peff@peff.net>
> ---
> No users yet; they come in future patches.
>
>  cache.h  | 15 +++++++++++++++
>  config.c | 33 +++++++++++++++++++++++++++++++++
>  2 files changed, 48 insertions(+)
>
> diff --git a/cache.h b/cache.h
> index c257953..14003b8 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -1164,6 +1164,21 @@ extern int git_config_include(const char *name, const char *value, void *data);
>  #define CONFIG_INCLUDE_INIT { 0 }
>  extern int git_config_include(const char *name, const char *value, void *data);
>  
> +/*
> + * Match and parse a config key of the form:
> + *
> + *   section.(subsection.)?key
> + *
> + * (i.e., what gets handed to a config_fn_t). The caller provides the section;
> + * we return -1 if it does not match, 0 otherwise. The subsection and key
> + * out-parameters are filled by the function (and subsection is NULL if it is
> + * missing).
> + */
> +extern int match_config_key(const char *var,
> +		     const char *section,
> +		     const char **subsection, int *subsection_len,
> +		     const char **key);
> +

I agree with Jonathan about the naming s/match/parse/.

After looking at the callers in your later patches, I think the
counted interface to subsection is probably fine.  The caller can
check !subsection to see if it is a two- or three- level name, and

    if (parse_config_key(var, "submodule", &name, &namelen,  &key) < 0 ||
	!name)
	return 0;

is very easy to follow (that is the result of your 5th step).

^ permalink raw reply

* [PATCH] clone: do not export and unexport GIT_CONFIG
From: Junio C Hamano @ 2013-01-14 18:11 UTC (permalink / raw)
  To: git

Earlier, dc87183 (use GIT_CONFIG only in "git config", not other
programs, 2008-06-30) made sure that the environment variable is
never used outside "git config", but "git clone", after creating a
directory for the new repository and until the init_db() function
populates its .git/ directory, exported the variable for no good
reason.  No hook will run from init_db() and more importantly no
hook can run until init_db() finishes creation of the new
repository, so it cannot be used by any invocation of "git config"
by definition.

Stop doing the useless export/unexport.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin/clone.c | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index a4d8d25..6f0c1c6 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -714,8 +714,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	atexit(remove_junk);
 	sigchain_push_common(remove_junk_on_signal);
 
-	setenv(CONFIG_ENVIRONMENT, mkpath("%s/config", git_dir), 1);
-
 	if (safe_create_leading_directories_const(git_dir) < 0)
 		die(_("could not create leading directories of '%s'"), git_dir);
 
@@ -732,13 +730,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	init_db(option_template, INIT_DB_QUIET);
 	write_config(&option_config);
 
-	/*
-	 * At this point, the config exists, so we do not need the
-	 * environment variable.  We actually need to unset it, too, to
-	 * re-enable parsing of the global configs.
-	 */
-	unsetenv(CONFIG_ENVIRONMENT);
-
 	git_config(git_default_config, NULL);
 
 	if (option_bare) {
-- 
1.8.1.407.g91cb4ac

^ permalink raw reply related

* Re: [PATCH] remote-hg: store converted URL
From: Junio C Hamano @ 2013-01-14 18:14 UTC (permalink / raw)
  To: Max Horn; +Cc: git, Felipe Contreras
In-Reply-To: <1357760618-81222-1-git-send-email-max@quendi.de>

Max Horn <max@quendi.de> writes:

> From: Felipe Contreras <felipe.contreras@gmail.com>
>
> Mercurial might convert the URL to something more appropriate, like an
> absolute path.

"What it is converted *TO*" is fairly clear with ", like an ...",
but from the first reading it was unclear to me "what it is
converted *FROM*" and "*WHEN* the conversion happens".  Do you mean
that the user gives "git clone" an URL "../hg-repo" via the command
line (e.g. the argument to "git clone" is spelled something like
"hg::../hg-repo"), and that "../hg-repo" is rewritten to something
else (an absolute path, e.g. "/srv/project/hg-repo")?

> Lets store that instead of the original URL, which won't
> work from a different working directory if it's relative.

What is lacking from this description is why it even needs to work
from a different working directory.  I am guessing that remote-hg
later creates a hidden Hg repository or something in a different
place and still tries to use the URL to interact with the upstream,
and that is what breaks, but with only the above description without
looking at your original report, people who will read the "git log"
output and find this change will not be able to tell why this was
needed, I am afraid.

Of course, the above guess of mine may even be wrong, but then that
is yet another reason that the log needs to explain the change
better.

> Suggested-by: Max Horn <max@quendi.de>
> Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
> Signed-off-by: Max Horn <max@quendi.de>
> ---
> For a discussion of the problem, see also
>   http://article.gmane.org/gmane.comp.version-control.git/210250

I do not see any discussion; only your problem report.

Was this work done outside the list?  I just want to make sure this
patch is not something Felipe did not want to sign off for whatever
reason but you are passing it to the list as a patch signed off by
him.

^ permalink raw reply

* Re: [PATCH 2/3] config: Introduce diff.algorithm variable
From: Junio C Hamano @ 2013-01-14 18:33 UTC (permalink / raw)
  To: Michal Privoznik; +Cc: git, peff, trast
In-Reply-To: <72370b372a56cc5bfaa9741eae62eae2854964b2.1358006339.git.mprivozn@redhat.com>

Michal Privoznik <mprivozn@redhat.com> writes:

> Some users or projects prefer different algorithms over others, e.g.
> patience over myers or similar. However, specifying appropriate
> argument every time diff is to be used is impractical. Moreover,
> creating an alias doesn't play nicely with other tools based on diff
> (git-show for instance). Hence, a configuration variable which is able
> to set specific algorithm is needed. For now, these four values are
> accepted: 'myers' (which has the same effect as not setting the config
> variable at all), 'minimal', 'patience' and 'histogram'.
>
> Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
> ---
>  Documentation/diff-config.txt          | 17 +++++++++++++++++
>  contrib/completion/git-completion.bash |  1 +
>  diff.c                                 | 23 +++++++++++++++++++++++
>  3 files changed, 41 insertions(+)
>
> diff --git a/Documentation/diff-config.txt b/Documentation/diff-config.txt
> index 4314ad0..be31276 100644
> --- a/Documentation/diff-config.txt
> +++ b/Documentation/diff-config.txt
> @@ -155,3 +155,20 @@ diff.tool::
>  	"kompare".  Any other value is treated as a custom diff tool,
>  	and there must be a corresponding `difftool.<tool>.cmd`
>  	option.
> +
> +diff.algorithm::
> +	Choose a diff algorithm.  The variants are as follows:
> ++
> +--
> +`myers`;;
> +	The basic greedy diff algorithm.
> +`minimal`;;
> +	Spend extra time to make sure the smallest possible diff is
> +	produced.
> +`patience`;;
> +	Use "patience diff" algorithm when generating patches.
> +`histogram`;;
> +	This algorithm extends the patience algorithm to "support
> +	low-occurrence common elements".
> +--
> ++

Sounds sensible.

> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> index 383518c..33e25dc 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -1839,6 +1839,7 @@ _git_config ()
>  		diff.suppressBlankEmpty
>  		diff.tool
>  		diff.wordRegex
> +		diff.algorithm
>  		difftool.
>  		difftool.prompt
>  		fetch.recurseSubmodules
> diff --git a/diff.c b/diff.c
> index 732d4c2..ddae5c4 100644
> --- a/diff.c
> +++ b/diff.c
> @@ -36,6 +36,7 @@ static int diff_no_prefix;
>  static int diff_stat_graph_width;
>  static int diff_dirstat_permille_default = 30;
>  static struct diff_options default_diff_options;
> +static long diff_algorithm = 0;

Please do not initialize a static explicitly to a zero and instead
let BSS do its thing.

>  static char diff_colors[][COLOR_MAXLEN] = {
>  	GIT_COLOR_RESET,
> @@ -143,6 +144,20 @@ static int git_config_rename(const char *var, const char *value)
>  	return git_config_bool(var,value) ? DIFF_DETECT_RENAME : 0;
>  }
>  
> +static long parse_algorithm_value(const char *value)
> +{
> +	if (!value || !strcasecmp(value, "myers"))
> +		return 0;
> +	else if (!strcasecmp(value, "minimal"))
> +		return XDF_NEED_MINIMAL;
> +	else if (!strcasecmp(value, "patience"))
> +		return XDF_PATIENCE_DIFF;
> +	else if (!strcasecmp(value, "histogram"))
> +		return XDF_HISTOGRAM_DIFF;
> +	else
> +		return -1;
> +}
> +
>  /*
>   * These are to give UI layer defaults.
>   * The core-level commands such as git-diff-files should
> @@ -196,6 +211,13 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)
>  		return 0;
>  	}
>  
> +	if (!strcmp(var, "diff.algorithm")) {
> +		diff_algorithm = parse_algorithm_value(value);
> +		if (diff_algorithm < 0)
> +			return -1;
> +		return 0;
> +	}
> +
>  	if (git_color_config(var, value, cb) < 0)
>  		return -1;
>  
> @@ -3213,6 +3235,7 @@ void diff_setup(struct diff_options *options)
>  	options->add_remove = diff_addremove;
>  	options->use_color = diff_use_color_default;
>  	options->detect_rename = diff_detect_rename_default;
> +	options->xdl_opts |= diff_algorithm;
>  
>  	if (diff_no_prefix) {
>  		options->a_prefix = options->b_prefix = "";

^ permalink raw reply

* Re: [PATCH 3/3] diff: Introduce --diff-algorithm command line option
From: Junio C Hamano @ 2013-01-14 18:44 UTC (permalink / raw)
  To: Michal Privoznik; +Cc: git, peff, trast
In-Reply-To: <6c058f13c6bb83985e8651a8dde99e7b17879d4e.1358006339.git.mprivozn@redhat.com>

Michal Privoznik <mprivozn@redhat.com> writes:

> Since command line options have higher priority than config file
> variables and taking previous commit into account, we need a way
> how to specify myers algorithm on command line.

Yes.  We cannot stop at [2/3] without this patch.

> However,
> inventing `--myers` is not the right answer. We need far more
> general option, and that is `--diff-algorithm`.

Yes, --diff-algorithm=default would let people defeat a configured
algo without knowing how exactly to spell myers.

> The older options
> (`--minimal`, `--patience` and `--histogram`) are kept for
> backward compatibility.

That is phrasing it too strongly to be acceptable.

People who do not care any configuration can keep using --histogram
without having to retrain their fingers to type a much longer form
you introduced (i.e. --diff-algorithm=histogram).  It is and will
always be just as valid a way to ask for --histogram as the new
longhand is.

> Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
> ---
>  Documentation/diff-options.txt         | 22 ++++++++++++++++++++++
>  contrib/completion/git-completion.bash | 11 +++++++++++
>  diff.c                                 | 12 +++++++++++-
>  diff.h                                 |  2 ++
>  merge-recursive.c                      |  6 ++++++
>  5 files changed, 52 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
> index 39f2c50..4091f52 100644
> --- a/Documentation/diff-options.txt
> +++ b/Documentation/diff-options.txt
> @@ -45,6 +45,9 @@ ifndef::git-format-patch[]
>  	Synonym for `-p --raw`.
>  endif::git-format-patch[]
>  
> +The next three options are kept for compatibility reason. You should use the
> +`--diff-algorithm` option instead.
> +

Drop this.

> @@ -55,6 +58,25 @@ endif::git-format-patch[]
>  --histogram::
>  	Generate a diff using the "histogram diff" algorithm.
>  
> +--diff-algorithm={patience|minimal|histogram|myers}::
> +	Choose a diff algorithm. The variants are as follows:
> ++
> +--
> +`myers`;;
> +	The basic greedy diff algorithm.
> +`minimal`;;
> +	Spend extra time to make sure the smallest possible diff is
> +	produced.
> +`patience`;;
> +	Use "patience diff" algorithm when generating patches.
> +`histogram`;;
> +	This algorithm extends the patience algorithm to "support
> +	low-occurrence common elements".
> +--
> ++
> +You should prefer this option over the `--minimal`, `--patience` and
> +`--histogram` which are kept just for backwards compatibility.

Drop the last one, and replace it with something like:

	If you configured diff.algorithm to a non-default value and
	want to use the default one, you have to use this form and
	choose myers, i.e. --diff-algorithm=myers, as we do not have
	a short-and-sweet --myers option.

(but the above is a bit too verbose, so please shorten it appropriately).

> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> index 33e25dc..d592cf9 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -1021,6 +1021,8 @@ _git_describe ()
>  	__gitcomp_nl "$(__git_refs)"
>  }
>  
> +__git_diff_algorithms="myers minimal patience histogram"
> +
>  __git_diff_common_options="--stat --numstat --shortstat --summary
>  			--patch-with-stat --name-only --name-status --color
>  			--no-color --color-words --no-renames --check
> @@ -1035,6 +1037,7 @@ __git_diff_common_options="--stat --numstat --shortstat --summary
>  			--raw
>  			--dirstat --dirstat= --dirstat-by-file
>  			--dirstat-by-file= --cumulative
> +			--diff-algorithm=
>  "
>  
>  _git_diff ()
> @@ -1042,6 +1045,10 @@ _git_diff ()
>  	__git_has_doubledash && return
>  
>  	case "$cur" in
> +	--diff-algorithm=*)
> +		__gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}"
> +		return
> +		;;
>  	--*)
>  		__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
>  			--base --ours --theirs --no-index
> @@ -2114,6 +2121,10 @@ _git_show ()
>  			" "" "${cur#*=}"
>  		return
>  		;;
> +	--diff-algorithm=*)
> +		__gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}"
> +		return
> +		;;
>  	--*)
>  		__gitcomp "--pretty= --format= --abbrev-commit --oneline
>  			$__git_diff_common_options
> diff --git a/diff.c b/diff.c
> index ddae5c4..6418076 100644
> --- a/diff.c
> +++ b/diff.c
> @@ -144,7 +144,7 @@ static int git_config_rename(const char *var, const char *value)
>  	return git_config_bool(var,value) ? DIFF_DETECT_RENAME : 0;
>  }
>  
> -static long parse_algorithm_value(const char *value)
> +long parse_algorithm_value(const char *value)
>  {
>  	if (!value || !strcasecmp(value, "myers"))
>  		return 0;
> @@ -3633,6 +3633,16 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
>  		options->xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF);
>  	else if (!strcmp(arg, "--histogram"))
>  		options->xdl_opts = DIFF_WITH_ALG(options, HISTOGRAM_DIFF);
> +	else if (!prefixcmp(arg, "--diff-algorithm=")) {
> +		long value = parse_algorithm_value(arg+17);
> +		if (value < 0)
> +			return error("option diff-algorithm accepts \"myers\", "
> +				     "\"minimal\", \"patience\" and \"histogram\"");
> +		/* clear out previous settings */
> +		DIFF_XDL_CLR(options, NEED_MINIMAL);
> +		options->xdl_opts &= ~XDF_DIFF_ALGORITHM_MASK;
> +		options->xdl_opts |= value;
> +	}
>  
>  	/* flags options */
>  	else if (!strcmp(arg, "--binary")) {
> diff --git a/diff.h b/diff.h
> index a47bae4..54c2590 100644
> --- a/diff.h
> +++ b/diff.h
> @@ -333,6 +333,8 @@ extern struct userdiff_driver *get_textconv(struct diff_filespec *one);
>  
>  extern int parse_rename_score(const char **cp_p);
>  
> +extern long parse_algorithm_value(const char *value);
> +
>  extern int print_stat_summary(FILE *fp, int files,
>  			      int insertions, int deletions);
>  extern void setup_diff_pager(struct diff_options *);
> diff --git a/merge-recursive.c b/merge-recursive.c
> index d882060..53d8feb 100644
> --- a/merge-recursive.c
> +++ b/merge-recursive.c
> @@ -2068,6 +2068,12 @@ int parse_merge_opt(struct merge_options *o, const char *s)
>  		o->xdl_opts = DIFF_WITH_ALG(o, PATIENCE_DIFF);
>  	else if (!strcmp(s, "histogram"))
>  		o->xdl_opts = DIFF_WITH_ALG(o, HISTOGRAM_DIFF);
> +	else if (!strcmp(s, "diff-algorithm=")) {
> +		long value = parse_algorithm_value(s+15);
> +		if (value < 0)
> +			return -1;
> +		o->xdl_opts |= value;

Isn't this new hunk wrong?  DIFF_WITH_ALG() removes the previously
chosen algorithm choice before OR'ing the new one in, so that

	diff --histogram --patience

would not end up with a value PATIENCE|HISTOGRAM OR'ed together in
the algo field.

^ permalink raw reply

* Re: [PATCH 00/14] Remove unused code from imap-send.c
From: Junio C Hamano @ 2013-01-14 19:02 UTC (permalink / raw)
  To: Michael Haggerty; +Cc: Jonathan Nieder, Jeff King, git
In-Reply-To: <50F3D0ED.5030103@alum.mit.edu>

Michael Haggerty <mhagger@alum.mit.edu> writes:

> On 01/14/2013 07:57 AM, Jonathan Nieder wrote:
>> Michael Haggerty wrote:
>> 
>>>  imap-send.c | 286 +++++++++---------------------------------------------------
>>>  1 file changed, 39 insertions(+), 247 deletions(-)
>> 
>> See my replies for comments on patches 1, 6, 9, 11, and 12.  The rest
>> are
>> 
>> Reviewed-by: Jonathan Nieder <jrnieder@gmail.com>
>> 
>> The series is tasteful and easy to follow and it's hard to argue with
>> the resulting code reduction.  Thanks for a pleasant read.
>
> Thanks for your careful review.  I will re-roll the patch series as soon
> as I get the chance.

Thanks, all of you.  The numbers and the graph look very nice indeed
;-)

^ permalink raw reply

* Re: Error:non-monotonic index after failed recursive "sed" command
From: Junio C Hamano @ 2013-01-14 19:06 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: George Karpenkov, git
In-Reply-To: <50F3F852.8060800@viscovery.net>

Johannes Sixt <j.sixt@viscovery.net> writes:

> Am 1/14/2013 12:40, schrieb George Karpenkov:
>> I've managed to corrupt my very valuable repository with a recursive
>> sed which went wrong.
>> I wanted to convert all tabs to spaces with the following command:
>> 
>> find ./ -name '*.*' -exec sed -i 's/\t/    /g' {} \;
>> 
>> I think that has changed not only the files in the repo, but the data
>> files in .git directory itself. As a result, my index became
>> corrupted, and almost every single command dies:
>> 
>>> git log
>> error: non-monotonic index
>> ..git/objects/pack/pack-314b1944adebea645526b6724b2044c1313241f5.idx
>> error: non-monotonic index
>> ..git/objects/pack/pack-75c95b0defe1968b61e4f4e1ab7040d35110bfdc.idx
>> ....
> ...
> Try the reverse edit:
>
>  find .git -name '*.*' -exec sed -i 's/    /\t/g' {} \;
>
> Remove .git/index; it can be reconstructed (of course, assuming you
> started all this with a clean index; if not, you lose the staged changes).

Everybody seems to be getting an impression that .idx is the only
thing that got corrupt.  Where does that come from?

I do not see anything that prevents the original command line from
touching *.pack files.  Loose objects may have been left unmolested
as their names do not match '*.*', though.

^ permalink raw reply

* Re: [BUG] Possible bug in `remote set-url --add --push`
From: Junio C Hamano @ 2013-01-14 19:09 UTC (permalink / raw)
  To: Michael J Gruber; +Cc: Jardel Weyrich, Sascha Cunz, git
In-Reply-To: <50F40316.7010308@drmicha.warpmail.net>

Michael J Gruber <git@drmicha.warpmail.net> writes:

> It seems to me that everything works as designed, and that the man page
> talk about "push URLs" can be read in two ways,...

Hmph, but I had an impression that Jardel's original report was that
one of the --add --pushurl was not adding but was replacing.  If
that was a false alarm, everything you said makes sense to me.

Thanks.

^ permalink raw reply

* Re: [PATCH 3/3] diff: Introduce --diff-algorithm command line option
From: Junio C Hamano @ 2013-01-14 19:12 UTC (permalink / raw)
  To: Michal Privoznik; +Cc: git, peff, trast
In-Reply-To: <7vsj63bo4n.fsf@alter.siamese.dyndns.org>

Junio C Hamano <gitster@pobox.com> writes:

> Michal Privoznik <mprivozn@redhat.com> writes:
> ...
>> diff --git a/merge-recursive.c b/merge-recursive.c
>> index d882060..53d8feb 100644
>> --- a/merge-recursive.c
>> +++ b/merge-recursive.c
>> @@ -2068,6 +2068,12 @@ int parse_merge_opt(struct merge_options *o, const char *s)
>>  		o->xdl_opts = DIFF_WITH_ALG(o, PATIENCE_DIFF);
>>  	else if (!strcmp(s, "histogram"))
>>  		o->xdl_opts = DIFF_WITH_ALG(o, HISTOGRAM_DIFF);
>> +	else if (!strcmp(s, "diff-algorithm=")) {
>> +		long value = parse_algorithm_value(s+15);
>> +		if (value < 0)
>> +			return -1;
>> +		o->xdl_opts |= value;
>
> Isn't this new hunk wrong?  DIFF_WITH_ALG() removes the previously
> chosen algorithm choice before OR'ing the new one in, so that
>
> 	diff --histogram --patience
>
> would not end up with a value PATIENCE|HISTOGRAM OR'ed together in
> the algo field.

I misspoke; this is not "diff", but "merge-recursive".  The issue
may be the same here, though.

^ permalink raw reply

* Re: Error:non-monotonic index after failed recursive "sed" command
From: Matthieu Moy @ 2013-01-14 19:13 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Johannes Sixt, George Karpenkov, git
In-Reply-To: <7v622zbn3s.fsf@alter.siamese.dyndns.org>

Junio C Hamano <gitster@pobox.com> writes:

> Everybody seems to be getting an impression that .idx is the only
> thing that got corrupt.  Where does that come from?

It's the only thing that appear in the error message. This does not
imply that it is the only corrupt thing, but gives a little hope that it
may still be the case.

Actually, I thought the "read-only" protection should have protected
files in object/ directory, but a little testing shows that "sed -i"
gladly accepts to modify read-only files (technically, it does not
modify it, but creates a temporary file with the new content, and then
renames it to the new location). So, the hope that pack files are
uncorrupted is rather thin unfortunately.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

^ permalink raw reply

* [PATCH] builtin/reset.c: Fix a sparse warning
From: Ramsay Jones @ 2013-01-14 19:28 UTC (permalink / raw)
  To: martinvonz; +Cc: GIT Mailing-list


In particular, sparse issues an "symbol not declared. Should it be
static?" warning for the 'parse_args' function. Since this function
does not require greater than file visibility, we suppress this
warning by simply adding the static modifier to it's decalaration.

Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
---

Hi Martin,

When you re-roll your "reset" patches (branch 'mz/reset-misc'), could
you please squash this into commit b24b3654 ("reset.c: extract function
for parsing arguments", 09-01-2013). Note that this patch is on top of
the pu branch (@75ea4ed3), which includes Junio's style fix patch
(commit 9f45c39f, "[SQUASH???] style fix", 10-01-2013).

Thanks!

ATB,
Ramsay Jones

 builtin/reset.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/reset.c b/builtin/reset.c
index a37044e..c69f9da 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -171,7 +171,7 @@ static void die_if_unmerged_cache(int reset_type)
 
 }
 
-const char **parse_args(int argc, const char **argv, const char *prefix, const char **rev_ret)
+static const char **parse_args(int argc, const char **argv, const char *prefix, const char **rev_ret)
 {
 	const char *rev = "HEAD";
 	unsigned char unused[20];
-- 
1.8.1

^ permalink raw reply related

* Re: [PATCH] builtin/reset.c: Fix a sparse warning
From: Martin von Zweigbergk @ 2013-01-14 19:35 UTC (permalink / raw)
  To: Ramsay Jones; +Cc: GIT Mailing-list
In-Reply-To: <50F45C7B.9030608@ramsay1.demon.co.uk>

On Mon, Jan 14, 2013 at 11:28 AM, Ramsay Jones
<ramsay@ramsay1.demon.co.uk> wrote:
>
> In particular, sparse issues an "symbol not declared. Should it be
> static?" warning for the 'parse_args' function. Since this function
> does not require greater than file visibility, we suppress this
> warning by simply adding the static modifier to it's decalaration.

Oops, how did I miss that? Will fix in re-roll. Thanks.

Martin

^ permalink raw reply

* [ANNOUNCE] Git v1.8.1.1
From: Junio C Hamano @ 2013-01-14 19:54 UTC (permalink / raw)
  To: git; +Cc: Linux Kernel

The latest maintenance release Git v1.8.1.1 is now available at
the usual places.  This contains many bugfixes that have been
cooking on the 'master' branch since v1.8.1 was released.

The release tarballs are found at:

    http://code.google.com/p/git-core/downloads/list

and their SHA-1 checksums are:

44b90aab937b0e0dbb0661eb5ec4ca6182e60854  git-1.8.1.1.tar.gz
952e0950d40bb141357be88a63f4cbb58258a4f5  git-htmldocs-1.8.1.1.tar.gz
5089613a434ba09c94f6694d546c246838377760  git-manpages-1.8.1.1.tar.gz

Also the following public repositories all have a copy of the v1.8.1.1
tag and the maint branch that the tag points at:

  url = git://repo.or.cz/alt-git.git
  url = https://code.google.com/p/git-core/
  url = git://git.sourceforge.jp/gitroot/git-core/git.git
  url = git://git-core.git.sourceforge.net/gitroot/git-core/git-core
  url = https://github.com/gitster/git

Git 1.8.1.1 Release Notes
=========================

Fixes since v1.8.1
------------------

 * The attribute mechanism didn't allow limiting attributes to be
   applied to only a single directory itself with "path/" like the
   exclude mechanism does.

 * When attempting to read the XDG-style $HOME/.config/git/config and
   finding that $HOME/.config/git is a file, we gave a wrong error
   message, instead of treating the case as "a custom config file does
   not exist there" and moving on.

 * After failing to create a temporary file using mkstemp(), failing
   pathname was not reported correctly on some platforms.

 * http transport was wrong to ask for the username when the
   authentication is done by certificate identity.

 * The behaviour visible to the end users was confusing, when they
   attempt to kill a process spawned in the editor that was in turn
   launched by Git with SIGINT (or SIGQUIT), as Git would catch that
   signal and die.  We ignore these signals now.

 * A child process that was killed by a signal (e.g. SIGINT) was
   reported in an inconsistent way depending on how the process was
   spawned by us, with or without a shell in between.

 * After "git add -N" and then writing a tree object out of the
   index, the cache-tree data structure got corrupted.

 * "git apply" misbehaved when fixing whitespace breakages by removing
   excess trailing blank lines in some corner cases.

 * A tar archive created by "git archive" recorded a directory in a
   way that made NetBSD's implementation of "tar" sometimes unhappy.

 * When "git clone --separate-git-dir=$over_there" is interrupted, it
   failed to remove the real location of the $GIT_DIR it created.
   This was most visible when interrupting a submodule update.

 * "git fetch --mirror" and fetch that uses other forms of refspec
   with wildcard used to attempt to update a symbolic ref that match
   the wildcard on the receiving end, which made little sense (the
   real ref that is pointed at by the symbolic ref would be updated
   anyway).  Symbolic refs no longer are affected by such a fetch.

 * The "log --graph" codepath fell into infinite loop in some
   corner cases.

 * "git merge" started calling prepare-commit-msg hook like "git
   commit" does some time ago, but forgot to pay attention to the exit
   status of the hook.

 * "git pack-refs" that ran in parallel to another process that
   created new refs had a race that can lose new ones.

 * When a line to be wrapped has a solid run of non space characters
   whose length exactly is the wrap width, "git shortlog -w" failed
   to add a newline after such a line.

 * The way "git svn" asked for password using SSH_ASKPASS and
   GIT_ASKPASS was not in line with the rest of the system.

 * "gitweb", when sorting by age to show repositories with new
   activities first, used to sort repositories with absolutely
   nothing in it early, which was not very useful.

 * "gitweb", when sorting by age to show repositories with new
   activities first, used to sort repositories with absolutely
   nothing in it early, which was not very useful.

 * When autoconf is used, any build on a different commit always ran
   "config.status --recheck" even when unnecessary.

 * Some scripted programs written in Python did not get updated when
   PYTHON_PATH changed.

 * We have been carrying a translated and long-unmaintained copy of an
   old version of the tutorial; removed.

 * Portability issues in many self-test scripts have been addressed.


Also contains other minor fixes and documentation updates.

----------------------------------------------------------------

Changes since v1.8.1 are as follows:

Aaron Schrab (1):
      Use longer alias names in subdirectory tests

Adam Spiers (1):
      api-allocation-growing.txt: encourage better variable naming

Antoine Pelisse (1):
      merge: Honor prepare-commit-msg return code

Christian Couder (1):
      Makefile: detect when PYTHON_PATH changes

Jean-Noël AVILA (1):
      Add directory pattern matching to attributes

Jeff King (9):
      run-command: drop silent_exec_failure arg from wait_or_whine
      launch_editor: refactor to use start/finish_command
      run-command: do not warn about child death from terminal
      launch_editor: propagate signals from editor to git
      completion: complete refs for "git commit -c"
      refs: do not use cached refs in repack_without_ref
      tests: turn on test-lint by default
      fix compilation with NO_PTHREADS
      run-command: encode signal death as a positive integer

Jens Lehmann (1):
      clone: support atomic operation with --separate-git-dir

John Keeping (4):
      git-fast-import(1): remove duplicate '--done' option
      git-shortlog(1): document behaviour of zero-width wrap
      git-fast-import(1): combine documentation of --[no-]relative-marks
      git-fast-import(1): reorganise options

Jonathan Nieder (6):
      config, gitignore: failure to access with ENOTDIR is ok
      config: treat user and xdg config permission problems as errors
      doc: advertise GIT_CONFIG_NOSYSTEM
      config: exit on error accessing any config file
      build: do not automatically reconfigure unless configure.ac changed
      docs: manpage XML depends on asciidoc.conf

Junio C Hamano (20):
      apply.c:update_pre_post_images(): the preimage can be truncated
      format_commit_message(): simplify calls to logmsg_reencode()
      sh-setup: work around "unset IFS" bug in some shells
      fetch: ignore wildcarded refspecs that update local symbolic refs
      xmkstemp(): avoid showing truncated template more carefully
      t0200: "locale" may not exist
      t9502: do not assume GNU tar
      t4014: fix arguments to grep
      t3600: Avoid "cp -a", which is a GNUism
      t9020: use configured Python to run the test helper
      compat/fnmatch: update old-style definition to ANSI
      t9200: let "cvs init" create the test repository
      merge --no-edit: do not credit people involved in the side branch
      SubmittingPatches: who am I and who cares?
      SubmittingPatches: mention subsystems with dedicated repositories
      Documentation: full-ness of a bundle is significant for cloning
      SubmittingPatches: remove overlong checklist
      SubmittingPatches: give list and maintainer addresses
      Prepare for 1.8.1.1
      Git 1.8.1.1

Kirill Brilliantov (1):
      Documentation: correct example restore from bundle

Mark Levedahl (1):
      Makefile: add comment on CYGWIN_V15_WIN32API

Matthew Daley (1):
      gitweb: Sort projects with undefined ages last

Max Horn (1):
      configure.ac: fix pthreads detection on Mac OS X

Michael Schubert (2):
      git-subtree: ignore git-subtree executable
      git-subtree: fix typo in manpage

Michał Kiedrowicz (1):
      graph.c: infinite loop in git whatchanged --graph -m

Nguyễn Thái Ngọc Duy (4):
      cache-tree: remove dead i-t-a code in verify_cache()
      cache-tree: replace "for" loops in update_one with "while" loops
      cache-tree: fix writing cache-tree when CE_REMOVE is present
      cache-tree: invalidate i-t-a paths after generating trees

Orgad Shaneh (1):
      gitweb: fix error in sanitize when highlight is enabled

Paul Fox (1):
      launch_editor: ignore terminal signals while editor has control

Rene Bredlau (1):
      http.c: Avoid username prompt for certifcate credentials

René Scharfe (2):
      archive-tar: split long paths more carefully
      t1402: work around shell quoting issue on NetBSD

Sebastian Schuberth (1):
      nedmalloc: Fix a compile warning (exposed as error) with GCC 4.7.2

Steffen Prohaska (2):
      shortlog: fix wrapping lines of wraplen
      strbuf_add_wrapped*(): Remove unused return value

Sven Strickroth (3):
      git-svn, perl/Git.pm: add central method for prompting passwords
      perl/Git.pm: Honor SSH_ASKPASS as fallback if GIT_ASKPASS is not set
      git-svn, perl/Git.pm: extend and use Git->prompt method for querying users

Thomas Ackermann (1):
      Remove Documentation/pt_BR/gittutorial.txt

Torsten Bögershausen (2):
      t9810: Do not use sed -i
      t9020: which is not portable

W. Trevor King (1):
      remote-hg: Fix biridectionality -> bidirectionality typos

^ permalink raw reply

* Re: Ediff interactive add
From: Rémi Vanicat @ 2013-01-14 19:57 UTC (permalink / raw)
  To: git mailing list
In-Reply-To: <50EFF882.5010206@mpp.mpg.de>

Frederik Beaujean <beaujean-rVlqnlWY17WELgA04lAiVw@public.gmane.org>
writes:

> On 13-01-11 01:47 AM, Samuel Wales wrote:
>> I have more on this, but if possible it would be best to make ediff do
>> that natively.  I don't know if that's possible.
> Thanks for your prompt replies. The reason I looked for this feature
> is that it is available in the package git-emacs. There I can choose
> Git - 
> Add to index - Select changes in current file. Then ediff starts, and
> I can modify the buffer named <index>:FILENAME at will.
> After I answer 'y' to 'Quit this Ediff session?',  another question comes up
> 'Add changes to the git index? (y or n)'. With 'y' I see the message
> Saving file /tmp/git-emacs-tmp6991oXZ...'
>
> So I guess all it takes is saving a temporary file and adding its
> content to the index. Given my lack of experience in lisp programming,
> I don't know how hard it actually is to implement in magit,
> though. But a quick look into the source code of git-emacs revealed
> this function
>

[...]

> I would be very happy if this became available in magit.

Could you test what has just been pushed in master, it should do it.

-- 
Rémi Vanicat

^ permalink raw reply

* [PATCH v2 2/3] config: Introduce diff.algorithm variable
From: Michal Privoznik @ 2013-01-14 19:58 UTC (permalink / raw)
  To: git; +Cc: gitster, peff, trast
In-Reply-To: <cover.1358193364.git.mprivozn@redhat.com>

Some users or projects prefer different algorithms over others, e.g.
patience over myers or similar. However, specifying appropriate
argument every time diff is to be used is impractical. Moreover,
creating an alias doesn't play nicely with other tools based on diff
(git-show for instance). Hence, a configuration variable which is able
to set specific algorithm is needed. For now, these four values are
accepted: 'myers' (which has the same effect as not setting the config
variable at all), 'minimal', 'patience' and 'histogram'.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
---
 Documentation/diff-config.txt          | 17 +++++++++++++++++
 contrib/completion/git-completion.bash |  1 +
 diff.c                                 | 23 +++++++++++++++++++++++
 3 files changed, 41 insertions(+)

diff --git a/Documentation/diff-config.txt b/Documentation/diff-config.txt
index 4314ad0..be31276 100644
--- a/Documentation/diff-config.txt
+++ b/Documentation/diff-config.txt
@@ -155,3 +155,20 @@ diff.tool::
 	"kompare".  Any other value is treated as a custom diff tool,
 	and there must be a corresponding `difftool.<tool>.cmd`
 	option.
+
+diff.algorithm::
+	Choose a diff algorithm.  The variants are as follows:
++
+--
+`myers`;;
+	The basic greedy diff algorithm.
+`minimal`;;
+	Spend extra time to make sure the smallest possible diff is
+	produced.
+`patience`;;
+	Use "patience diff" algorithm when generating patches.
+`histogram`;;
+	This algorithm extends the patience algorithm to "support
+	low-occurrence common elements".
+--
++
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 383518c..33e25dc 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1839,6 +1839,7 @@ _git_config ()
 		diff.suppressBlankEmpty
 		diff.tool
 		diff.wordRegex
+		diff.algorithm
 		difftool.
 		difftool.prompt
 		fetch.recurseSubmodules
diff --git a/diff.c b/diff.c
index 732d4c2..e9a7e4d 100644
--- a/diff.c
+++ b/diff.c
@@ -36,6 +36,7 @@ static int diff_no_prefix;
 static int diff_stat_graph_width;
 static int diff_dirstat_permille_default = 30;
 static struct diff_options default_diff_options;
+static long diff_algorithm;
 
 static char diff_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_RESET,
@@ -143,6 +144,20 @@ static int git_config_rename(const char *var, const char *value)
 	return git_config_bool(var,value) ? DIFF_DETECT_RENAME : 0;
 }
 
+static long parse_algorithm_value(const char *value)
+{
+	if (!value || !strcasecmp(value, "myers"))
+		return 0;
+	else if (!strcasecmp(value, "minimal"))
+		return XDF_NEED_MINIMAL;
+	else if (!strcasecmp(value, "patience"))
+		return XDF_PATIENCE_DIFF;
+	else if (!strcasecmp(value, "histogram"))
+		return XDF_HISTOGRAM_DIFF;
+	else
+		return -1;
+}
+
 /*
  * These are to give UI layer defaults.
  * The core-level commands such as git-diff-files should
@@ -196,6 +211,13 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)
 		return 0;
 	}
 
+	if (!strcmp(var, "diff.algorithm")) {
+		diff_algorithm = parse_algorithm_value(value);
+		if (diff_algorithm < 0)
+			return -1;
+		return 0;
+	}
+
 	if (git_color_config(var, value, cb) < 0)
 		return -1;
 
@@ -3213,6 +3235,7 @@ void diff_setup(struct diff_options *options)
 	options->add_remove = diff_addremove;
 	options->use_color = diff_use_color_default;
 	options->detect_rename = diff_detect_rename_default;
+	options->xdl_opts |= diff_algorithm;
 
 	if (diff_no_prefix) {
 		options->a_prefix = options->b_prefix = "";
-- 
1.8.0.2

^ permalink raw reply related

* [PATCH v2 1/3] git-completion.bash: Autocomplete --minimal and --histogram for git-diff
From: Michal Privoznik @ 2013-01-14 19:58 UTC (permalink / raw)
  To: git; +Cc: gitster, peff, trast
In-Reply-To: <cover.1358193364.git.mprivozn@redhat.com>

Even though --patience was already there, we missed --minimal and
--histogram for some reason.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
---
 contrib/completion/git-completion.bash | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index a4c48e1..383518c 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1031,7 +1031,7 @@ __git_diff_common_options="--stat --numstat --shortstat --summary
 			--no-ext-diff
 			--no-prefix --src-prefix= --dst-prefix=
 			--inter-hunk-context=
-			--patience
+			--patience --histogram --minimal
 			--raw
 			--dirstat --dirstat= --dirstat-by-file
 			--dirstat-by-file= --cumulative
-- 
1.8.0.2

^ permalink raw reply related

* [PATCH v2 3/3] diff: Introduce --diff-algorithm command line option
From: Michal Privoznik @ 2013-01-14 19:58 UTC (permalink / raw)
  To: git; +Cc: gitster, peff, trast
In-Reply-To: <cover.1358193364.git.mprivozn@redhat.com>

Since command line options have higher priority than config file
variables and taking previous commit into account, we need a way
how to specify myers algorithm on command line. However,
inventing `--myers` is not the right answer. We need far more
general option, and that is `--diff-algorithm`.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
---
 Documentation/diff-options.txt         | 23 +++++++++++++++++++++++
 contrib/completion/git-completion.bash | 11 +++++++++++
 diff.c                                 | 12 +++++++++++-
 diff.h                                 |  2 ++
 merge-recursive.c                      |  9 +++++++++
 5 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index 39f2c50..01b97b3 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -55,6 +55,29 @@ endif::git-format-patch[]
 --histogram::
 	Generate a diff using the "histogram diff" algorithm.
 
+--diff-algorithm={patience|minimal|histogram|myers}::
+	Choose a diff algorithm. The variants are as follows:
++
+--
+`myers`;;
+	The basic greedy diff algorithm.
+`minimal`;;
+	Spend extra time to make sure the smallest possible diff is
+	produced.
+`patience`;;
+	Use "patience diff" algorithm when generating patches.
+`histogram`;;
+	This algorithm extends the patience algorithm to "support
+	low-occurrence common elements".
+--
++
+For instance, if you configured diff.algorithm variable to a
+non-default value and want to use the default one, then you
+have to use `--diff-algorithm=myers` option.
+
+You should prefer this option over the `--minimal`, `--patience` and
+`--histogram` which are kept just for backwards compatibility.
+
 --stat[=<width>[,<name-width>[,<count>]]]::
 	Generate a diffstat. By default, as much space as necessary
 	will be used for the filename part, and the rest for the graph
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 33e25dc..d592cf9 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1021,6 +1021,8 @@ _git_describe ()
 	__gitcomp_nl "$(__git_refs)"
 }
 
+__git_diff_algorithms="myers minimal patience histogram"
+
 __git_diff_common_options="--stat --numstat --shortstat --summary
 			--patch-with-stat --name-only --name-status --color
 			--no-color --color-words --no-renames --check
@@ -1035,6 +1037,7 @@ __git_diff_common_options="--stat --numstat --shortstat --summary
 			--raw
 			--dirstat --dirstat= --dirstat-by-file
 			--dirstat-by-file= --cumulative
+			--diff-algorithm=
 "
 
 _git_diff ()
@@ -1042,6 +1045,10 @@ _git_diff ()
 	__git_has_doubledash && return
 
 	case "$cur" in
+	--diff-algorithm=*)
+		__gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}"
+		return
+		;;
 	--*)
 		__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
 			--base --ours --theirs --no-index
@@ -2114,6 +2121,10 @@ _git_show ()
 			" "" "${cur#*=}"
 		return
 		;;
+	--diff-algorithm=*)
+		__gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}"
+		return
+		;;
 	--*)
 		__gitcomp "--pretty= --format= --abbrev-commit --oneline
 			$__git_diff_common_options
diff --git a/diff.c b/diff.c
index e9a7e4d..3e021d5 100644
--- a/diff.c
+++ b/diff.c
@@ -144,7 +144,7 @@ static int git_config_rename(const char *var, const char *value)
 	return git_config_bool(var,value) ? DIFF_DETECT_RENAME : 0;
 }
 
-static long parse_algorithm_value(const char *value)
+long parse_algorithm_value(const char *value)
 {
 	if (!value || !strcasecmp(value, "myers"))
 		return 0;
@@ -3633,6 +3633,16 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
 		options->xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF);
 	else if (!strcmp(arg, "--histogram"))
 		options->xdl_opts = DIFF_WITH_ALG(options, HISTOGRAM_DIFF);
+	else if (!prefixcmp(arg, "--diff-algorithm=")) {
+		long value = parse_algorithm_value(arg+17);
+		if (value < 0)
+			return error("option diff-algorithm accepts \"myers\", "
+				     "\"minimal\", \"patience\" and \"histogram\"");
+		/* clear out previous settings */
+		DIFF_XDL_CLR(options, NEED_MINIMAL);
+		options->xdl_opts &= ~XDF_DIFF_ALGORITHM_MASK;
+		options->xdl_opts |= value;
+	}
 
 	/* flags options */
 	else if (!strcmp(arg, "--binary")) {
diff --git a/diff.h b/diff.h
index a47bae4..54c2590 100644
--- a/diff.h
+++ b/diff.h
@@ -333,6 +333,8 @@ extern struct userdiff_driver *get_textconv(struct diff_filespec *one);
 
 extern int parse_rename_score(const char **cp_p);
 
+extern long parse_algorithm_value(const char *value);
+
 extern int print_stat_summary(FILE *fp, int files,
 			      int insertions, int deletions);
 extern void setup_diff_pager(struct diff_options *);
diff --git a/merge-recursive.c b/merge-recursive.c
index 33ba5dc..ea9dbd3 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -2068,6 +2068,15 @@ int parse_merge_opt(struct merge_options *o, const char *s)
 		o->xdl_opts = DIFF_WITH_ALG(o, PATIENCE_DIFF);
 	else if (!strcmp(s, "histogram"))
 		o->xdl_opts = DIFF_WITH_ALG(o, HISTOGRAM_DIFF);
+	else if (!strcmp(s, "diff-algorithm=")) {
+		long value = parse_algorithm_value(s+15);
+		if (value < 0)
+			return -1;
+		/* clear out previous settings */
+		DIFF_XDL_CLR(o, NEED_MINIMAL);
+		o->xdl_opts &= ~XDF_DIFF_ALGORITHM_MASK;
+		o->xdl_opts |= value;
+	}
 	else if (!strcmp(s, "ignore-space-change"))
 		o->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;
 	else if (!strcmp(s, "ignore-all-space"))
-- 
1.8.0.2

^ permalink raw reply related


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