* [PATCH 5/6] submodule: use match_config_key when parsing config
From: Jeff King @ 2013-01-14 15:04 UTC (permalink / raw)
To: Joachim Schmitz; +Cc: René Scharfe, Junio C Hamano, git
In-Reply-To: <20130114145845.GA16497@sigill.intra.peff.net>
This makes the code a lot simpler to read by dropping a
whole bunch of constant offsets.
As a bonus, it means we also feed the whole config variable
name to our error functions:
[before]
$ git -c submodule.foo.fetchrecursesubmodules=bogus checkout
fatal: bad foo.fetchrecursesubmodules argument: bogus
[after]
fatal: bad submodule.foo.fetchrecursesubmodules argument: bogus
Signed-off-by: Jeff King <peff@peff.net>
---
submodule.c | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/submodule.c b/submodule.c
index 2f55436..4361207 100644
--- a/submodule.c
+++ b/submodule.c
@@ -126,15 +126,17 @@ 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 string_list_item *config;
struct strbuf submodname = STRBUF_INIT;
+ const char *name, *key;
+ int namelen;
- var += 10; /* Skip "submodule." */
+ if (match_config_key(var, "submodule", &name, &namelen, &key) < 0 ||
+ !name)
+ return 0;
- len = strlen(var);
- if ((len > 5) && !strcmp(var + len - 5, ".path")) {
- strbuf_add(&submodname, var, len - 5);
+ if (!strcmp(key, "path")) {
+ strbuf_add(&submodname, name, namelen);
config = unsorted_string_list_lookup(&config_name_for_path, value);
if (config)
free(config->util);
@@ -142,22 +144,22 @@ int parse_submodule_config_option(const char *var, const char *value)
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);
+ } else if (!strcmp(key, "fetchrecursesubmodules")) {
+ strbuf_add(&submodname, name, namelen);
config = unsorted_string_list_lookup(&config_fetch_recurse_submodules_for_name, submodname.buf);
if (!config)
config = string_list_append(&config_fetch_recurse_submodules_for_name,
strbuf_detach(&submodname, NULL));
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, "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);
+ strbuf_add(&submodname, name, namelen);
config = unsorted_string_list_lookup(&config_ignore_for_name, submodname.buf);
if (config)
free(config->util);
--
1.8.1.rc1.10.g7d71f7b
^ permalink raw reply related
* [PATCH 6/6] submodule: simplify memory handling in config parsing
From: Jeff King @ 2013-01-14 15:07 UTC (permalink / raw)
To: Joachim Schmitz; +Cc: René Scharfe, Junio C Hamano, git
In-Reply-To: <20130114145845.GA16497@sigill.intra.peff.net>
We keep a strbuf for the name of the submodule, even though
we only ever add one buffer (which we know the length of) to
it. Let's just use xmemdupz instead, which is slightly more
efficient and makes it easier to follow what is going on.
Unfortunately, we still end up having to deal with some
memory ownership issues in some code branches, as we have to
allocate the string in order to do a string list lookup, and
then only sometimes want to hand ownership of that string
over to the string_list. Still, making that explicit in the
code (as opposed to sometimes detaching the strbuf, and then
always releasing it) makes it a little more obvious what is
going on.
Signed-off-by: Jeff King <peff@peff.net>
---
I'm undecided on this one. I think the result is easier to follow, but
others might find the original easier. This would be a lot more
readable if the config parser gave us a broken-out representation with
real C strings. Then we could pass the subsection straight to the
string_list functions for lookup, and using the "dup" flag of string
list, avoid even having to deal with memory duplication at all.
submodule.c | 30 ++++++++++++++----------------
1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/submodule.c b/submodule.c
index 4361207..23a8490 100644
--- a/submodule.c
+++ b/submodule.c
@@ -127,7 +127,6 @@ int parse_submodule_config_option(const char *var, const char *value)
int parse_submodule_config_option(const char *var, const char *value)
{
struct string_list_item *config;
- struct strbuf submodname = STRBUF_INIT;
const char *name, *key;
int namelen;
@@ -136,37 +135,36 @@ int parse_submodule_config_option(const char *var, const char *value)
return 0;
if (!strcmp(key, "path")) {
- strbuf_add(&submodname, name, namelen);
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);
+ config->util = xmemdupz(name, namelen);
} else if (!strcmp(key, "fetchrecursesubmodules")) {
- strbuf_add(&submodname, name, namelen);
- config = unsorted_string_list_lookup(&config_fetch_recurse_submodules_for_name, submodname.buf);
+ char *name_cstr = xmemdupz(name, namelen);
+ config = unsorted_string_list_lookup(&config_fetch_recurse_submodules_for_name, name_cstr);
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, name_cstr);
+ else
+ free(name_cstr);
config->util = (void *)(intptr_t)parse_fetch_recurse_submodules_arg(var, value);
- strbuf_release(&submodname);
} else if (!strcmp(key, "ignore")) {
+ char *name_cstr;
+
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, name, namelen);
- config = unsorted_string_list_lookup(&config_ignore_for_name, submodname.buf);
- if (config)
+ name_cstr = xmemdupz(name, namelen);
+ config = unsorted_string_list_lookup(&config_ignore_for_name, name_cstr);
+ if (config) {
free(config->util);
- else
- config = string_list_append(&config_ignore_for_name,
- strbuf_detach(&submodname, NULL));
- strbuf_release(&submodname);
+ free(name_cstr);
+ } else
+ config = string_list_append(&config_ignore_for_name, name_cstr);
config->util = xstrdup(value);
return 0;
}
--
1.8.1.rc1.10.g7d71f7b
^ permalink raw reply related
* Re: git list files
From: Jeff King @ 2013-01-14 15:28 UTC (permalink / raw)
To: Jonathan Nieder
Cc: Стойчо Слепцов,
git, Jakub Narębski, Matthieu Moy
In-Reply-To: <20130114070832.GA4820@elie.Belkin>
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
* [PATCH] pretty: use prefixcmp instead of memcmp on NUL-terminated strings
From: René Scharfe @ 2013-01-14 16:34 UTC (permalink / raw)
To: git discussion list; +Cc: Junio C Hamano
This conversion avoids the need for magic string length numbers in the
code. And unlike memcmp(), prefixcmp() is careful to not run over the
end of a string.
Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
---
pretty.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/pretty.c b/pretty.c
index 92c839f..01795de 100644
--- a/pretty.c
+++ b/pretty.c
@@ -966,7 +966,7 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
if (!end)
return 0;
- if (!memcmp(begin, "auto,", 5)) {
+ if (!prefixcmp(begin, "auto,")) {
if (!want_color(c->pretty_ctx->color))
return end - placeholder + 1;
begin += 5;
@@ -1301,7 +1301,7 @@ static void pp_header(const struct pretty_print_context *pp,
continue;
}
- if (!memcmp(line, "parent ", 7)) {
+ if (!prefixcmp(line, "parent ")) {
if (linelen != 48)
die("bad parent line in commit");
continue;
@@ -1325,11 +1325,11 @@ static void pp_header(const struct pretty_print_context *pp,
* FULL shows both authors but not dates.
* FULLER shows both authors and dates.
*/
- if (!memcmp(line, "author ", 7)) {
+ if (!prefixcmp(line, "author ")) {
strbuf_grow(sb, linelen + 80);
pp_user_info(pp, "Author", sb, line + 7, encoding);
}
- if (!memcmp(line, "committer ", 10) &&
+ if (!prefixcmp(line, "committer ") &&
(pp->fmt == CMIT_FMT_FULL || pp->fmt == CMIT_FMT_FULLER)) {
strbuf_grow(sb, linelen + 80);
pp_user_info(pp, "Commit", sb, line + 10, encoding);
--
1.8.0
^ permalink raw reply related
* Re: [BUG] Possible bug in `remote set-url --add --push`
From: Jonathan Nieder @ 2013-01-14 16:41 UTC (permalink / raw)
To: Michael J Gruber; +Cc: Jardel Weyrich, Sascha Cunz, Junio C Hamano, git
In-Reply-To: <50F40316.7010308@drmicha.warpmail.net>
Michael J Gruber wrote:
> All that "set-url --push --add" does is adding a remote.foo.pushurl
> entry to the config. If there was none, there will be one after that.
>
> If there is no pushurl entry, "push" takes the url entry instead. This
> is the "default URL for push", but not a pushurl entry.
That is how it is implemented, but it is hard for me with a straight
face to say that is what most users expect.
Wouldn't the least confusing thing be to just error out for "set-url
--push --add" when there is no existing pushurl? That way, the
operator can use plain "set-url --push" to clarify whether whether he
meant to include the pull URLs in the new pushurl set.
My two cents,
Jonathan
^ permalink raw reply
* Re: [PATCH 3/6] convert some config callbacks to match_config_key
From: Jonathan Nieder @ 2013-01-14 16:55 UTC (permalink / raw)
To: Jeff King; +Cc: Joachim Schmitz, René Scharfe, Junio C Hamano, git
In-Reply-To: <20130114150322.GC16828@sigill.intra.peff.net>
Jeff King wrote:
> --- a/convert.c
> +++ b/convert.c
> @@ -465,10 +465,8 @@ static int read_convert_config(const char *var, const char *value, void *cb)
> * External conversion drivers are configured using
> * "filter.<name>.variable".
> */
> - if (prefixcmp(var, "filter.") || (ep = strrchr(var, '.')) == var + 6)
> + if (match_config_key(var, "filter", &name, &namelen, &ep) < 0 || !name)
> return 0;
Hm, I actually find the preimage more readable here.
I like the idea of having a function to do this, though. Here are a
couple of ideas for making the meaning obvious again for people like
me:
Rename match_config_key() to something like parse_config_key()?
match_ makes it sound like its main purpose is to match it against a
pattern, but really it is more about decomposing into constituent
parts.
Rename ep to something like 'key' or 'filtertype'? Without the
explicit string processing, it is not obvious what ep is the end of.
[...]
> --- a/userdiff.c
> +++ b/userdiff.c
> @@ -188,20 +188,13 @@ static struct userdiff_driver *parse_driver(const char *var,
> const char *value, const char *type)
> {
> struct userdiff_driver *drv;
> - const char *dot;
> - const char *name;
> + const char *name, *key;
> int namelen;
>
> - if (prefixcmp(var, "diff."))
> - return NULL;
> - dot = strrchr(var, '.');
> - if (dot == var + 4)
> - return NULL;
> - if (strcmp(type, dot+1))
> + if (match_config_key(var, "diff", &name, &namelen, &key) < 0 ||
> + strcmp(type, key))
> return NULL;
>
> - name = var + 5;
> - namelen = dot - name;
> drv = userdiff_find_by_namelen(name, namelen);
What happens in the !name case? (Honest question --- I haven't checked.)
Generally I like the cleanup. Thanks for tasteful patch.
Jonathan
^ permalink raw reply
* Re: [PATCH 3/6] convert some config callbacks to match_config_key
From: Jeff King @ 2013-01-14 17:06 UTC (permalink / raw)
To: Jonathan Nieder; +Cc: Joachim Schmitz, René Scharfe, Junio C Hamano, git
In-Reply-To: <20130114165527.GB3121@elie.Belkin>
On Mon, Jan 14, 2013 at 08:55:28AM -0800, Jonathan Nieder wrote:
> Jeff King wrote:
>
> > --- a/convert.c
> > +++ b/convert.c
> > @@ -465,10 +465,8 @@ static int read_convert_config(const char *var, const char *value, void *cb)
> > * External conversion drivers are configured using
> > * "filter.<name>.variable".
> > */
> > - if (prefixcmp(var, "filter.") || (ep = strrchr(var, '.')) == var + 6)
> > + if (match_config_key(var, "filter", &name, &namelen, &ep) < 0 || !name)
> > return 0;
>
> Hm, I actually find the preimage more readable here.
The big thing to me is getting rid of the manual "6" there, which is bad
for maintainability (it must match the length of "filter", and there is
no compile-time verification).
> Rename match_config_key() to something like parse_config_key()?
> match_ makes it sound like its main purpose is to match it against a
> pattern, but really it is more about decomposing into constituent
> parts.
There is already a git_config_parse_key, but it does something else. I
wanted to avoid confusion there. And I was trying to indicate that this
was not just about parsing, but also about matching the section.
Basically I was trying to encapsulate the current technique and have as
little code change as possible. But maybe:
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).
> Rename ep to something like 'key' or 'filtertype'? Without the
> explicit string processing, it is not obvious what ep is the end of.
Ah, so that is what "ep" stands for. I was thinking it is a terrible
variable name, but I was trying to keep the patch minimal.
> > - if (prefixcmp(var, "diff."))
> > - return NULL;
> > - dot = strrchr(var, '.');
> > - if (dot == var + 4)
> > - return NULL;
> > - if (strcmp(type, dot+1))
> > + if (match_config_key(var, "diff", &name, &namelen, &key) < 0 ||
> > + strcmp(type, key))
> > return NULL;
> >
> > - name = var + 5;
> > - namelen = dot - name;
> > drv = userdiff_find_by_namelen(name, namelen);
>
> What happens in the !name case? (Honest question --- I haven't checked.)
Segfault, I expect. Thanks for catching.
I actually wrote this correctly once, coupled with patch 4, but screwed
it up when teasing it apart into two patches. It should be:
if (match_config_key(var, "diff", &name, &namelen, &key) < 0 ||
!name ||
strcmp(type, key))
return NULL;
Patch 4 replaces this with correct code (as it moves it into
userdiff_config).
-Peff
^ permalink raw reply
* 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 = ⊤
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
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox